打印
[菜农助学交流]

使用GPIO模拟IIC时序进行IIC的读写操作

[复制链接]
5783|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
denvice|  楼主 | 2011-7-12 13:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 denvice 于 2011-7-13 12:11 编辑

看多了大家奉献的帖子,这里我也奉献一帖,虽然新唐单片机的IIC够多,但是我实在是无聊呵呵写了一个GPIO模拟IIC的程序,和大家一起来学习学习。
/************************************
函数功能:通过PA.0,PA.2向2404写入和
读出单字节数据。写入以后将数据读出来,
如果写进去的数据和读出来的数据相等,
则让PB.0的LED闪烁起来
*************************************/
#include <stdio.h>
#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"

void start(void) //起始信号
{
  DrvGPIO_SetBit(E_GPA, 0);         //sda=1
  DrvSYS_Delay(5);                    //延时5us
  DrvGPIO_SetBit(E_GPA, 2);          //scl=1
  DrvSYS_Delay(5);                         //延时5us
  DrvGPIO_ClrBit(E_GPA, 0);          //sda=0
  DrvSYS_Delay(5);                           //延时5us
}

void stop(void) //停止信号
{
  DrvGPIO_ClrBit(E_GPA, 0);         //sda=0
  DrvSYS_Delay(5);                           //延时5us
  DrvGPIO_SetBit(E_GPA, 2);          //scl=1
  DrvSYS_Delay(5);                           //延时5us
  DrvGPIO_SetBit(E_GPA, 0);          //sda=1
  DrvSYS_Delay(5);                            //延时5us
}

void waitack(void)//等待应答信号
{
int i;
DrvGPIO_SetBit(E_GPA, 2);          //scl=1
DrvSYS_Delay(5);                            //延时5us
DrvGPIO_Open(E_GPA,0, E_IO_INPUT); //将sda置为输入
while(DrvGPIO_GetBit(E_GPA,0)&&i<255)
i++;
DrvGPIO_Open(E_GPA,0, E_IO_OUTPUT);//将sda置为输出
DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
DrvSYS_Delay(5);                                 //延时5us

}

void noack(void) //非应答信号
{
  DrvGPIO_SetBit(E_GPA, 0);          //sda=1
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_SetBit(E_GPA, 2);          //scl=1
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_ClrBit(E_GPA, 0);         //sda=0
  DrvSYS_Delay(5);
}

void ack(void)          //应答信号
{
  DrvGPIO_ClrBit(E_GPA, 0);         //sda=0
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_SetBit(E_GPA, 2);          //scl=1
  DrvSYS_Delay(5);                             //延时5us
  DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
  DrvSYS_Delay(5);                                 //延时5us
  DrvGPIO_SetBit(E_GPA, 0);          //sda=1
  DrvSYS_Delay(5);

}


void write8bit(int input)         //写一个字节数据
{
     int i;
  DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
  DrvSYS_Delay(5);                           //延时5us
   for(i=0;i<8;i++)
   {         
   if((input<<i)&0x80)
   DrvGPIO_SetBit(E_GPA, 0);          //sda=1
   else
   DrvGPIO_ClrBit(E_GPA, 0);         //sda=0
   DrvSYS_Delay(5);                            //延时5us
   DrvGPIO_SetBit(E_GPA, 2);          //scl=1
   DrvSYS_Delay(5);                                   //延时5us
   DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
   DrvSYS_Delay(5);
   
        }                                 
  DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_SetBit(E_GPA, 0);         //sda=1
  DrvSYS_Delay(5);                            //延时5us
}

int read8bit(void)                   //读一个字节数据
{
int temp,rbyte=0;

        DrvGPIO_Open(E_GPA,0, E_IO_INPUT); //将sda置为输入
        for(temp=0;temp<8;temp++)
        {
         rbyte=rbyte<<1;
         if(DrvGPIO_GetBit(E_GPA,0))  
         rbyte=rbyte|0x01;                           //延时5us
     DrvGPIO_SetBit(E_GPA, 2);          //scl=1
     DrvSYS_Delay(5);                                 //延时5us
     DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
     DrvSYS_Delay(5);
         }
        DrvGPIO_Open(E_GPA,0, E_IO_OUTPUT);//将sda置为输出
        DrvGPIO_ClrBit(E_GPA, 2);          //scl=0 //调试连续读操作时发现不能将SCL拉高读完一次数据后
        DrvGPIO_SetBit(E_GPA, 0);          //sda=1
        DrvSYS_Delay(5);                           //延时5us
        return(rbyte);
}

void init(void)
{
DrvGPIO_SetBit(E_GPA, 0);          //sda=1
DrvGPIO_SetBit(E_GPA, 2);          //scl=1
}

void writebyte(int add,int dat)          //将一个字节数据dat写入某个地址add
{
start();
if(add>=256)                                                //2402的地址是A0,但是2404的高256位地址为A2
write8bit(0xA2);
else
write8bit(0xA0);

waitack();

if(add>=256)
write8bit(add-256);
else
write8bit(add);
waitack();

write8bit(dat);
waitack();

stop();
}

int readbyte(char add)
{
        int byte;
        
        start();
        if(add>=256)
        write8bit(0xA2);
        else
        write8bit(0xA0);
        waitack();
        
        if(add>=256)
        write8bit(add-256);
        else
        write8bit(add);
        waitack();
        
        start();
        if(add<256)
        write8bit(0xA1);
        else
        write8bit(0xA3);
        waitack();
        
        byte=read8bit();
        noack();
        stop();
        return byte;
}

void delay_loop(void)
{
uint32_t j;
                 for(j=0;j<60000;j++);               
                for(j=0;j<60000;j++);
            for(j=0;j<60000;j++);               
                for(j=0;j<60000;j++);
}

int main()
{
    int a;
        UNLOCKREG(x);    //解锁
        DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);          //配置晶振
    DrvSYS_Delay(5000);
        LOCKREG(x);


        DrvGPIO_Open(E_GPA, 0, E_IO_OUTPUT);//将管脚配置为输出                                                
        DrvGPIO_Open(E_GPA, 2, E_IO_OUTPUT);//                                                        
        DrvGPIO_Open(E_GPA, 4, E_IO_OUTPUT);//                                                                 
        DrvGPIO_Open(E_GPB, 0, E_IO_OUTPUT);//
    writebyte(20,3);     //将3写入2402的地址20的寄存器中
    delay_loop();
        a=readbyte(20);                 //读取2402地址20处的数据

         while(1)
         {
                 if(a==3)
        {
        DrvGPIO_ClrBit(E_GPB,0);
        delay_loop();
        DrvGPIO_SetBit(E_GPB,0);
        delay_loop();
        
         }
         }
}

NUC100.rar

835.07 KB

相关帖子

沙发
denvice|  楼主 | 2011-7-12 13:22 | 只看该作者
自己顶一个

使用特权

评论回复
板凳
hotpower| | 2011-7-13 10:47 | 只看该作者
不错!值得鼓励。
GPIO模拟I2C最大的好处是熟悉IIC协议。
不过ack()和noack()应该有测试返回值才能通用和安全。

使用特权

评论回复
地板
denvice|  楼主 | 2011-7-14 09:58 | 只看该作者
感谢神赐了我一条裤子啊:)

使用特权

评论回复
5
hotpower| | 2011-7-14 11:08 | 只看该作者
虽然奖励了裤子,但不鼓励在新唐的m0上软件模拟iic。

使用特权

评论回复
6
denvice|  楼主 | 2011-7-14 16:02 | 只看该作者
呵呵确实不值得鼓励,只是方便大家学习IIC

使用特权

评论回复
7
恋子炎| | 2013-5-3 09:36 | 只看该作者
waitack里面的i有什么用?

使用特权

评论回复
8
恋子炎| | 2013-5-3 17:50 | 只看该作者
  DrvGPIO_ClrBit(E_GPA, 2);          //scl=0
  DrvSYS_Delay(5);                            //延时5us
  DrvGPIO_SetBit(E_GPA, 0);         //sda=1
  DrvSYS_Delay(5);                            //延时5us
这几句貌似没什么用吧,写完8个bit之后就可以直接进入,等待ACK了啊,为什么还要这样做呢?

使用特权

评论回复
9
Harvard| | 2018-8-16 19:57 | 只看该作者
hotpower 发表于 2011-7-14 11:08
虽然奖励了裤子,但不鼓励在新唐的m0上软件模拟iic。

为何不鼓励? 大神, 是因为自带的iic 足够稳定,没必要? 还是其他原因

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

162

帖子

2

粉丝