I2C总线

来源:互联网 发布:淘宝客不显示佣金 编辑:程序博客网 时间:2024/06/05 14:20

最近用到超声波测距模块,用了HC-SR04和KS103两个模块。
KS103模块用到I2C和串口通信模式,这里做个记录。
首先整理下I2C的,串口的后续跟上。。。

I2C总线(Inter Intergrated Circuit Bus)是同步通信的一种特殊形式,具有接口线少、控制简单、器件封装形式小、通信速率较高等特点。

I2C总线由数据线SDA和时钟线SCL两条线构成通信线路,既可发送数据也可接收数据。在cpu与被控IC之间、IC与IC都可进行双向传送,最高传送速率为400kbps,各种被控制器件均并联在总线上,但每个器件有唯一的地址。
总线在空闲状态下均保持高电平,连到总线上的任一器件输出低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。

1.发送启动信号:在SCL为高电平期间,SDA出现下降沿则为启动信号。
这里写图片描述

2.发送停止信号:在SCL为高电平期间,SDA上产生一上升沿信号。
这里写图片描述

3.发送寻址信号:主机发送启动信号后,在发出寻址信号。器件寻址有7位和10位两种。
7位寻址方式,寻址信号由一个字节构成,高七位为地址位,最低位为方向位,用以表明主机与从器件的数据传送方向。0表示主机写数据到从器件,1表示主机从从器件读数据。
这里写图片描述

4.数据位的有效规定:I2C在进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
这里写图片描述

5.数据传输:主机发送寻址信号并得到从器件应答后,便可进行数据传输,每次一个字节,但每次传输都应在得到应答信号后再进行下一个字节传送。

6.应答信号:每传送一个字节数据(含地址及命令字)后,都要有一个应答信号,以确定数据传送是否被对方收到。应答信号由接收设备产生,在SCL信号为高电平期间,接收设备将SDA拉为低电平,便是数据传输正确,产生应答。
这里写图片描述

7.非应答信号:当主机为接收设备是,主机对最后一个字节不应答,以向发送设备表示数据传送结束。

8.I2C总线通信格式:
这里写图片描述

在一次数据传输过程中,可以有以下几种组合方式:

  1. 主机向从机发送数据,数据传送方向在整个传送过程中不变。
  2. 主机在第一个字节后,立即从从机读数据。
  3. 在传送过程中,当需要改变传送方向时,需将起始信号和从机地址各重复产生一次,而两次读/写方向正好相反。

为保证数据传送的可靠性,标准I2C总线的数据传送有严格的时序要求。这里写图片描述

void start(void) //I2C start{    SDA = 1;    delay();    SCL = 1;    delay();    SDA = 0;    delay();}void stop(void) //I2C stop{    SDA = 0;    delay();    SCL = 1;    delay();    SDA = 1;    delay();}void ack(void) //ack{    unsigned char i;    SCL = 1;    delay();    while(SDA == 1 && i < 200)    {        i++;    }    SCL = 0;    delay();}void no_ack() //not ack{    SDA = 1;    delay();    SCL = 1;    delay();    SCL = 0;    delay();}void i2c_write_byte(unsigned char dat) //write a byte{    unsigned char i;    SCL = 0;    for(i = 0; i < 8; i++)    {        if(dat & 0x80)        {            SDA = 1;        }        else        {            SDA = 0;        }        dat = dat << 1;        delay();        SCL = 1;        delay();        SCL = 0;        delay();    }    SDA = 1;    delay();}unsigned char i2c_read_byte(void) //read a byte{    unsigned char i,dat;    SCL = 0;    delay();    SDA = 1;    delay();    for(i = 0; i < 8; i++)    {        SCL = 1;        delay();        dat = dat << 1;        if(SDA == 1)        {            dat++;        }        SCL = 0;        delay();    }    return dat;}void init_i2c(void) //i2c init{    SDA = 1;    delay();    SCL = 1;    delay();}

关于应答和非应答
应答:是一个低电平信号。
非应答:是一个高电平信号。

非应答的三种情况:
1. 由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。
2. 如果从机对主机进行了应答,但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”通知主机,主机则应发出终止信号以结束数据的继续传送。
3. 当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放SDA线,以允许主机产生终止信号。

关于总线仲裁:当有多个节点需要控制总线,就需要总线仲裁机制裁决。
总线仲裁分为SCL时钟同步和SDA线仲裁。

找到一篇博客,原文在此
http://blog.sina.com.cn/s/blog_403f820c0100bd0x.html

  1. SCL线的同步(时钟同步)
    SCL同步是由于总线具有线“与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号。这就是SCL的同步原理
    这里写图片描述

时钟的同步

2 SDA仲裁

SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线
3 仲裁过程
这里写图片描述
I2C总线的仲裁机制
两个主节点的仲裁过程
上图是以两个节点为例的仲裁过程。DATA1和DATA2分别是主节点向总线所发送的数据信号,SDA为总线上所呈现的数据信号,SCL是总线上所呈现的时钟信号。当主节点1、2同时发送起始信号时,两个主节点都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号与自己发送的信号相同,继续发送数据。第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“与”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不一样,就断开数据的输出级,转为从机接收状态。这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据与主节点2所发送的数据一样,而主节点1在转为从节点后继续接收数据,同样也没有丢掉SDA线上的数据。因此在仲裁过程中数据没有丢失。
总结:SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。

0 0