gpio模拟I2C总线c代码实现

来源:互联网 发布:安卓写轮眼优化教程 编辑:程序博客网 时间:2024/05/30 05:03
#include <reg52.h>#define uchar unsigned char#define uint unsigned  intsbit I2C_SCL = P2^6;                //模拟I2C总线的引脚定义sbit I2C_SDA = P2^7;#define I2C_DELAY_VALUE    12       //定义I2C总线时钟的延时值,要根据实际情况修改,取值1~255                                    //SCL信号周期约为(I2C_DELAY_VALUE*4+15)个机器周期#define I2C_STOP_WAIT_VALUE  120    //定义I2C总线停止后在下一次开始之前的等待时间,取值1~65535                                    //等待时间约为(I2C_STOP_WAIT_VALUE*8)个机器周期#define I2C_Delay()                 // 延时,模拟I2C总线专用{    I2C_Delay_t = (I2C_DELAY_VALUE);    while ( --I2C_Delay_t != 0 );}unsigned char data I2C_Delay_t;void I2C_Init(){    I2C_SCL = 1;    I2C_Delay();    I2C_SDA = 1;    I2C_Delay();}void I2C_Start()          //SCL处于高电平期间,当SDA出现下降沿时启动I2C总线{    I2C_SDA = 1;          //不论SDA和SCL处于什么电平状态,本函数总能正确产生起始状态    I2C_Delay();          //本函数也可以用来产生重复起始状态    I2C_SCL = 1;          //本函数执行后,I2C总线处于忙状态    I2C_Delay();    I2C_SDA = 0;    I2C_Delay();    I2C_SCL = 0;    I2C_Delay();}void I2C_Write(char dat)     //向I2C总线写1个字节的数据{    unsigned char t = 8;     //dat:要写到总线上的数据    do    {               I2C_SCL = 1;        I2C_Delay();        I2C_SCL = 0;        I2C_Delay();        I2C_SDA = (bit)(dat & 0x80);        dat <<= 1;    } while ( --t != 0 );}bit I2C_GetAck()        //读取从机应答位{    bit ack;            //从机在收到每个字节的数据后,要产生应答位    I2C_SDA = 1;        //从机在收到最后1个字节的数据后,一般要产生非应答位    I2C_Delay();    I2C_SCL = 1;    I2C_Delay();    ack = I2C_SDA;    I2C_SCL = 0;    I2C_Delay();    return ack;         //0:从机应答  //1:从机非应答}   void I2C_Stop()         //产生I2C总线的停止状态{    unsigned int t = I2C_STOP_WAIT_VALUE;    I2C_SDA = 0;            I2C_Delay();               //SCL处于高电平期间,当SDA出现上升沿时停止I2C总线    I2C_SCL = 1;               //不论SDA和SCL处于什么电平状态,本函数总能正确产生停止状态    I2C_Delay();               //本函数执行后,I2C总线处于空闲状态    I2C_SDA = 1;    I2C_Delay();    while ( --t != 0 );        //在下一次产生Start之前,要加一定的延时}bit I2C_Puts( uchar SlaveAddr, uint SubAddr, uchar SubMod, char *dat, uint Size){                                    //I2C总线综合发送函数,向从机发送多个字节的数据    unsigned char i;                 //*dat:要发送的数据    char a[3];                       //Size:数据的字节数    if ( Size == 0 ) return 0;       //检查长度    a[0] = (SlaveAddr << 1);         //SlaveAddr:从机地址(7位纯地址,不含读写位)    if ( SubMod > 2 ) SubMod = 2;    //SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址    switch ( SubMod )                //确定子地址    {    case 0:        break;    case 1:   a[1] = (char)(SubAddr);  //SubAddr:从机的子地址        break;    case 2:   a[1] = (char)(SubAddr >> 8);              a[2] = (char)(SubAddr);        break;    default:        break;    }    SubMod++;                 //发送从机地址,接着发送子地址(如果有子地址的话)    I2C_Start();    for ( i=0; i<SubMod; i++ )    {        I2C_Write(a[i]);        if ( I2C_GetAck() )        {            I2C_Stop();            return 1;        }    }    do                        //发送数据    {        I2C_Write(*dat++);        if ( I2C_GetAck() ) break;    } while ( --Size != 0 );    I2C_Stop();               //发送完毕,停止I2C总线,并返回结果    if ( Size == 0 )    {        return 0;    }    else    {        return 1;            //0:发送成功   1:在发送过程中出现异常    }}#define MAX517_I2C_ADDR  0X58     //MAX517 器件地址unsigned char num_v ;             //MAX517 输出数字量bit complete_flag;                //I2C 通信成功标志void Delay(unsigned int t) reentrant  //延时子程序{  while(--t)  {      unsigned int j = 110;       while(--j);  }}char code DX516[3] _at_ 0x3b;     //保留0x3b开始的3个字节main(void){    I2C_Init();       Delay(1000);    num_v = 0;    complete_flag = I2C_Puts(MAX517_I2C_ADDR,0,1,&num_v,1);    Delay(1000);       while(1)    {                   num_v ++;        complete_flag = I2C_Puts(MAX517_I2C_ADDR,0,1,&num_v,1);        Delay(100);       }}
http://blog.csdn.net/muyexuanwo/article/details/6230431