打印
[STC单片机]

I2C通信协议的使用及经验总结

[复制链接]
2550|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
skw168|  楼主 | 2019-1-3 19:40 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 skw168 于 2019-1-3 20:09 编辑

先讲点题外的,毕业后一直从事电子方面的工作,对于单片机,以前学过,但是当时不感兴趣,以为学好模拟及数字电路即可;
从2015年开始,因为工作原因开始慢慢接触国产单片机,然后才发觉单片机的强大,相同的功能,用模拟电路实现比较复杂,调试也困难,如果用单片机,硬件电路相对简单,调试方便;
从16年开始,慢慢开始用单片机做自己的制作,做过的项目有:T12数显烙铁,936数显烙铁,普通风扇改遥控,定时,调速等等,因为性格急躁,很多项目都是做到后面,潦草收工;这些,以后有时间再慢慢聊;
上面的项目,基本都是一个单片机能玩转,没有涉及通信协议;最近发现,单片机与外界通信后,能够玩的更开怀;
不扯了,开始正题;

I2C是飞利浦公司推出的2线制双向通信协议,两根传输线分别是SCL和SDA;

I2C操作可以简单归纳为6种

1。起始信号
描述:SCL为高电平期间,SDA由高电平向低电平间的变化
下面是程序:

void I2C_Start() //I2C开始程序************************************
{
        SDA = 1;
        delay_us(10);
        SCL = 1;
        delay_us(10);
        SDA = 0;
        delay_us(10);
        SCL = 0;
        delay_us(10);
}

2.终止信号
描述:SCL为高电平期间,SDA由低电平向高电平的变化

void I2C_Stop() //I2C结束程序************************************
{
        SDA = 0;
        delay_us(10);
        SCL = 1;
        delay_us(10);
        SDA = 1;
        delay_us(10);               
}

3.写数据信号
描述:SCL由低电平向高电平变化后,开始传送1bit数据

void I2C_Send_Byte(unsigned char dat) //I2C发送数据*******************************************************
{
    unsigned char i,temp;
    temp = dat;
    for(i = 0; i <8; i++)
    {
        SCL = 0;
        delay_us(10);
        if((temp & 0x80) == 0x80)//从最高位开始传送,当SCL为低电平时,SDA数据才可以改变
        {
            SDA = 1;
        }
        else
        {
            SDA = 0;
        }
        delay_us(10);
        SCL = 1;  //在SCL为上升沿时发送数据
        delay_us(10);        
        temp <<= 1;
    }
    SCL = 0;
    delay_us(10);
}

4.读数据信号
描述:SCL由高电平向低电平变化后,开始读取1bit数据

unsigned char I2C_Receive_Byte() //I2C接收数据********************************************************************
{
    unsigned char a,dat=0;
    //SDA = 1;
    delay_us(10);
    for(a = 0; a < 8; a++)
    {
        SCL = 1;
        delay_us(10);
        dat <<= 1;
        dat |= SDA;
        delay_us(10);
        SCL = 0;
        delay_us(10);
    }
    return dat;
}

5.接收ACK信号
void I2C_Check_ACK() //I2C等待外部ACK信号******************************************
{
    bit a;
    unsigned char b=0;
    a = 0;
    SDA = 1;
    delay_us(10);
    SCL = 1;
    while(a == 0)
    {
        if(SDA == 0)
        {
            a = 1;
        }

        if(b < 100)
        {
            b++;
        }
        else
        {
            a = 1;
        }
    }
    SCL = 0;
    delay_us(10);
}

6.发送ACK或NACK信号
void I2C_Send_ACK(bit ACK) //I2C产生ACK或者NACK信号
{
    SDA = ACK; //ACK=0为ACK信号,ACK=1为NACK信号
    delay_us(10);   
    SCL = 1;
    delay_us(10);   
}
讲讲调试时遇到的坑:
时钟信号SCL为高电平时,SDA数据必须保持稳定,
SCL为低电平时,SDA的数据才能改变(也就是I2C时序问题)

附上I2C时序图


根据上图,讲解下I2C发送数据的全过程:
起始信号→依次发送8位数据→等待ACK信号→依次发送8位数据→等待ACK→(可多次循环)→停止信号

PS:发现21IC的有些功能挺方便的,比如帖子编辑功能,半年前发的帖子,现在居然还可以编辑。。。。。。














相关帖子

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

本版积分规则

37

主题

137

帖子

6

粉丝