OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6557|回复: 3

I2C通信时序图解析

[复制链接]

3

主题

21

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2016-1-7
在线时间
103 小时
发表于 2018-12-5 23:22:23 | 显示全部楼层 |阅读模式
本帖最后由 w627255898 于 2018-12-5 23:28 编辑

转自https://www.cnblogs.com/Tangledice/p/7622794.html
一、I2C协议简介
  I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地 使用在系统内多个集成电路(IC)间的通讯。
  关于I2C协议的更多内容,可阅读《I2C总线协议》,本博文主要分析I2C波形图,对于I2C的基础知识不在做介绍。
二、I2C协议标准代码2.1 起始信号&停止信号
  起始信号:当 SCL 线是高电平时 SDA 线从高电平向低电平切换。
  停止信号:当 SCL 线是高电平时 SDA 线由低电平向高电平切换。
2.1.1 起始信号代码
[mw_shl_code=c,true]void I2C_Start(void)
{
    I2C_SDA_High();     //SDA=1
    I2C_SCL_High();     //SCL=1
    I2C_Delay();
    I2C_SDA_Low();
    I2C_Delay();
    I2C_SCL_Low();
    I2C_Delay();
}[/mw_shl_code]
2.1.2 停止信号代码

[mw_shl_code=c,true]void I2C_Stop(void)
{
    I2C_SDA_Low();
    I2C_SCL_High();
    I2C_Delay();
    I2C_SDA_High();
    I2C_Delay();
}[/mw_shl_code]2.2 发送一个字节
  CPU向I2C总线设备发送一个字节(8bit)数据
[mw_shl_code=c,true]u8 I2C_SendByte(uint8_t Byte)
{
    uint8_t i;

    /* 先发送高位字节 */
    for(i = 0 ; i < 8 ; i++)
    {
        if(Byte & 0x80)
        {
            I2C_SDA_High();
        }
        else
        {
            I2C_SDA_Low();
        }
        I2C_Delay();
        I2C_SCL_High();
        I2C_Delay();
        I2C_SCL_Low();
        I2C_Delay();

        if(i == 7)
        {
            I2C_SDA_High();                     /* 释放SDA总线 */
        }
        Byte <<= 1;                             /* 左移一位  */

        I2C_Delay();
    }
} [/mw_shl_code]

2.3 读取一个字节
&#8195;&#8195;CPU从I2C总线设备上读取一个字节(8bit数据)

[mw_shl_code=c,true]u8 I2C_ReadByte(void)
{
    uint8_t i;
    uint8_t value;

    /* 先读取最高位即bit7 */
    value = 0;
    for(i = 0 ; i < 8 ; i++)
    {
        value <<= 1;
        I2C_SCL_High();
        I2C_Delay();
        if(I2C_SDA_READ())
        {
            value++;
        }
        I2C_SCL_Low();
        I2C_Delay();
    }

    return value;
}[/mw_shl_code]
2.4 应答
2.4.1 CPU产生一个ACK信号
[mw_shl_code=c,true]void I2C_Ack(void)
{
    I2C_SDA_Low();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();
    I2C_SCL_Low();
    I2C_Delay();

    I2C_SDA_High();
}[/mw_shl_code]
2.4.2 CPU产生一个非ACK信号
[mw_shl_code=c,true]void I2C_NoAck(void)
{
    I2C_SDA_High();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();
    I2C_SCL_Low();
    I2C_Delay();
}[/mw_shl_code]
2.4.3 CPU产生一个时钟,并读取器件的ACK应答信号
[mw_shl_code=c,true]uint8_t I2C_WaitToAck(void)
{
    uint8_t redata;

    I2C_SDA_High();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();

    if(I2C_SDA_READ())
    {
        redata = 1;
    }
    else
    {
        redata = 0;
    }
    I2C_SCL_Low();
    I2C_Delay();

    return redata;
}[/mw_shl_code]
三、I2C通信时序图解析
&#8195;&#8195;有了上边的I2C总线标准代码的基础,下面我们进入本博文所要讲解的内容,怎么分析I2C的时序图,以O2Micro的OZ9350为例,OZ9350是一款模拟前端(AFE)的IC器件。是一款性价比不错的电源管理芯片,由于其通讯是通过I2C来进行通讯的,所以这里用OZ9350的I2C通讯做例子进行讲解。
3.1 写数据
&#8195;&#8195;首先我们先来看一下写数据的时序图,如下图所示:
&#8195;&#8195;将上图中的写数据时序图进行分解,经分解后如下图所示:

&#8195;&#8195;结合I2C总线协议的知识,我们可以知道OZ9350的I2C写数据由一下10个步骤组成。
&#8195;&#8195;第一步,发送一个起始信号。
&#8195;&#8195;第二步,发送7bit从机地址,即OZ9350的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
&#8195;&#8195;第三步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
&#8195;&#8195;第四步,发送寄存器地址,8bit数据。
&#8195;&#8195;第五步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
&#8195;&#8195;第六步,发送一个数据,8bit数据。
&#8195;&#8195;第七步,产生一个ACK应答信号,此应答信号为从机器件产生的应答信号。
&#8195;&#8195;第八步,发送一个CRC校验码,此CRC校验值为2、4、6步数据产生的校验码。
&#8195;&#8195;第九步,既可以发送一个应答信号,也可以发送一个无应答信号,均有从机器件产生。
&#8195;&#8195;第十步,发送一个停止信号。
&#8195;&#8195;接下来,按照以上是个步骤,可以写出OZ9350的i2c写数据的函数。代码如下:
[mw_shl_code=c,true]u8 I2C_WriteBytes(void)
{
    I2C_Start();                    //1

    I2C_SendByte(Slaver_Addr | 0);  //2
    I2C_WaitToAck();                //3

    I2C_SendByte(Reg_Addr);         //4
    I2C_WaitToAck();                //5

    I2C_SendByte(data);             //6
    I2C_WaitToAck();                //7

    I2C_SendByte(crc);              //8
    I2C_WaitToAck();                //9

    I2C_Stop();                     //10
}[/mw_shl_code]

3.2 读数据
&#8195;&#8195;读数据的时序图如下图所示:

&#8195;&#8195;读数据的时序图经分解后如下图所示:

&#8195;&#8195;通过分解后的时序图,可以看到OZ9350的读数据由以下13个步骤组成。
&#8195;&#8195;第一步,发送一个起始信号。
&#8195;&#8195;第二步,发送7bit从机地址,即OZ9350的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
&#8195;&#8195;第三步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
&#8195;&#8195;第四步,发送寄存器地址。
&#8195;&#8195;第五步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
&#8195;&#8195;第六步,再次发送一个骑士信号。
&#8195;&#8195;第七步,发送7bit从机地址,即OZ9350的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
&#8195;&#8195;第八步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
&#8195;&#8195;第九步,读取一个字节(8bit)的数据。
&#8195;&#8195;第十步,产生一个ACK应答信号,此应答信号为CPU产生。
&#8195;&#8195;第十一步,读取一个CRC校验码。
&#8195;&#8195;第十二步,产生一个NACK信号。此无应答信号由CPU产生。
&#8195;&#8195;第十三步,产生一个停止信号。
&#8195;&#8195;接下来,由以上分析步骤,可以写出OZ9350的I2C读数据代码。如下所示:
[mw_shl_code=c,true]u8 I2C_ReadBytes(void)
{
    u8 data;
    u8 crc;

    I2C_Start();                    //1

    I2C_SendByte(Slaver_Addr | 0);  //2
    I2C_WaitToAck();                //3

    I2C_SendByte(Reg_Addr);         //4
    I2C_WaitToAck();                //5

    I2C_Start();                   //6

    I2C_SendByte(Slaver_Addr | 1);  //7 1-读
    I2C_WaitToAck();                //8

    data=I2C_ReadByte();            //9

    I2C_Ack();                      //10

    crc=I2C_ReadByte();             //11

    I2C_NoAck();                    //12

    I2C_Stop();                     //13
}[/mw_shl_code]


四、结语
&#8195;&#8195;关于怎样分析I2C通信的时序图,在理解原理的基础上还需要自己多动手练习,只有这样才能熟练掌握。如果在博文中出现错误之处,还望指正。




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-12-6 08:28:43 | 显示全部楼层
本帖最后由 秋天 于 2018-12-6 14:01 编辑

谢谢分享  补充楼主  我采集了模拟iic的时序图



iic时序图.jpg






Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-12-6 08:29:10 | 显示全部楼层
楼主写的不错
Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4307
金钱
4307
注册时间
2018-6-30
在线时间
808 小时
发表于 2018-12-6 09:48:19 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 08:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表