zoukankan      html  css  js  c++  java
  • gpio模拟I2C总线c代码实现

    #include <reg52.h>
    #define uchar unsigned char
    #define uint unsigned  int
    sbit 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

  • 相关阅读:
    网页改版的A/B测试(A/B test)
    好看又实用的英文字体
    十大Web压力测试工具
    javascript中的setInterval()方法
    jquery中find方法和children方法的区别
    .net之路
    blur事件
    理解委托的两类必要方法
    jquery中的过滤操作
    推荐一个好的分区软件win7调整磁盘的大小
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124677.html
Copyright © 2011-2022 走看看