I2C通信基本原理以及使用C语言实现

  I2C总线是一种简单、双向二线制同步串行总线。它只需要两根线即SCL(时钟信号线)和SDA(数据线),就可在连接于总线上的器件之间传送信息。

  I2C采用的是主从式通信方式,通信的过程完全由主设备决定。通讯的起始信号和终止信号都由主设备发送。

 

 

起始信号:在SCL时钟信号在高电平期间,SDA信号产生一个下降沿,起始之后SDA和SCL都为0。

 1 void I2C_Start()
 2 {
 3     I2C_SDA = 1;
 4     I2C_Delay10us();
 5     I2C_SCL = 1;
 6     I2C_Delay10us(); //建立时间是I2C_SDA保持时间>4.7us
 7 
 8     I2C_SDA = 0;  //保持时间是>4us
 9     I2C_Delay10us();
10     I2C_SCL = 0;
11     I2C_Delay10us();
12 }

 

 终止信号:在SCL时钟信号在高电平期间,SDA信号产生一个上升沿,终止后保持SDA和SCL都为1,表示总线空闲。

 1 void I2C_Stop()
 2 {
 3     I2C_SDA = 0;
 4     I2C_Delay10us();
 5     I2C_SCL = 1;
 6     I2C_Delay10us(); //建立时间是I2C_SDA保持时间>4.7us
 7 
 8     I2C_SDA = 1;
 9     I2C_Delay10us();
10 }

 

I2C总线上可以挂多个从设备,为了区分从设备,每个设备都有自己的地址编码。当主从通讯时,主设备必须先发送一个从设备的地址。在SCL时钟信号线处于低电平时,SDA数据线上的地址信息要开始准备了。I2C在传送地址信息时都是从高位开始传送。

 SCL时钟信号低电平转换为高电平再转换为低电平,一个bit的数据传送完毕。如果数据传送成功,从设备将会返回一个应答信号,此时,总线应该要处于空闲状态,等待应答信号。

 1 uchar I2C_SendByte(uchar dat, uchar ack)
 2 {
 3     uchar a = 0, b = 0;//最大255,一个机器周期1us 最大延时255us
 4 
 5     for(a=0; a<8; a++)
 6     {
 7         I2C_SDA = dat >> 7;
 8         dat = dat << 1;
 9         I2C_Delay10us();
10         I2C_SCL = 1;
11         I2C_Delay10us();//建立时间>4.7us
12         I2C_SCL = 0;
13         I2C_Delay10us();//建立时间>4us
14     }
15 
16     I2C_SDA = 1;
17     I2C_Delay10us();
18     I2C_SCL = 1;
19     I2C_Delay10us();
20 
21     while(I2C_SDA && (ack == 1)) // 等待应答,也就是等待从设备把I2C_SDA拉低
22     {
23         b++;
24         if(b > 200)
25         {
26             I2C_SCL = 0;
27             I2C_Delay10us();
28             return 0;
29         }
30     }
31 
32     I2C_SCL = 0;
33     I2C_Delay10us();
34     return 1;
35 }

 

当从设备需要读取从设备数据时,总线同样需要处于空闲状态。当SCL低电平转换为高电平时,读取一个bit的数据,SCL再次转换为低电平时,读取结束。数据从高位开始读取。

 1 uchar I2C_ReadByte()
 2 {
 3     uchar a = 0, dat = 0;
 4     I2C_SDA = 1;  //起始和发送一个字节之后I2C_SCL都是0
 5     I2C_Delay10us();
 6     for(a=0; a<8; a++)
 7     {
 8         I2C_SCL = 1;
 9         I2C_Delay10us();
10         dat <<= 1;
11         dat |= I2C_SDA;
12         I2C_Delay10us();
13         I2C_SCL = 0;
14         I2C_Delay10us();
15     }
16     return dat;
17 
18 }

 

posted @ 2018-12-08 21:39  佳木  阅读(2981)  评论(0编辑  收藏  举报