×
单片机 > 单片机程序设计 > 详情

51单片机——I2C总线

发布时间:2020-06-15 发布时间:
|

UART 属于异步通信,比如电脑发送给单片机,电脑只负责把数据通过TXD 发送出来即可,接收数据是单片机自己的事情。而 I2C 属于同步通信, SCL 时钟线负责收发双方的时钟节拍, SDA 数据线负责传输数据。 I2C 的发送方和接收方都以 SCL 这个时钟节拍为基准进行数据的发送和接收。

        I2C总线包括SCL,SDA 两根信号线,其中SCL是时钟线,SDA是数据线。



1、起始信号

UART 通信是从一直持续的高电平出现一个低电平标志起始位;而 I2C 通信的起始信号的定义是 SCL 为高电平期间, SDA 由高电平向低电平变化产生一个下降沿,表示起始信号。

 

2、数据传输

UART 是低位在前,高位在后;而 I2C 通信是高位在前,低位在后。UART 通信数据位是固定长度,波特率分之一,一位一位固定时间发送完毕就可以了。而 I2C 没有固定波特率,但是有时序的要求,要求当 SCL 在低电平的时候, SDA 允许变化。

 

3、停止信号

UART 通信的停止位是一位固定的高电平信号; 而 I2C 通信停止信号的定义是 SCL 为高电平期间, SDA 由低电平向高电平变化产生一个上升沿,表示结束信号。

 

4、写完从器件之后等待从器件的应答

在主器件完成对从器件的写操作时候(每次会有一个字节的数据),主器件会等待从器件发送指示信号,这个指示信号是说从器件已经接受到了主器件的数据,这是由从器件的硬件来完成的,不需要主器件来软件操作,只需要等待;

 

5、主器件读完数据后向从器件发送应答信号

这其实包括两种情况,一种是主器件读完后还要继续读就要发送一个继续读的信号(其实就是发送0),另一种就是不再继续读了,就要发送停止读信号(其实就是发送1)。

 

6、I2C寻址模式

I2C 通信的起始信号(Start)后,首先要发送一个从机的地址,这个地址一共有 7位,紧跟着的第 8 位是数据方向位(R/W),“ 0”表示接下来要发送数据(写),‘“ 1”表示接下来是请求数据(读)。第九位 ACK应答。 


  1. #include  

  2. #include  

  3.   

  4. #define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}  

  5. sbit I2C_SCL = P3 ^ 7;  

  6. sbit I2C_SDA = P3 ^ 6;  

  7.   

  8. /* 产生总线起始信号 */  

  9. void I2CStart()  

  10. {  

  11.   I2C_SDA = 1; //首先确保SDA、SCL都是高电平  

  12.   I2C_SCL = 1;  

  13.   I2CDelay();  

  14.   I2C_SDA = 0; //先拉低SDA  

  15.   I2CDelay();  

  16.   I2C_SCL = 0; //再拉低SCL  

  17. }  

  18. /* 产生总线停止信号 */  

  19. void I2CStop()  

  20. {  

  21.   I2C_SCL = 0; //首先确保SDA、SCL都是低电平  

  22.   I2C_SDA = 0;  

  23.   I2CDelay();  

  24.   I2C_SCL = 1; //先拉高SCL  

  25.   I2CDelay();  

  26.   I2C_SDA = 1; //再拉高SDA  

  27.   I2CDelay();  

  28. }  

  29. /* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */  

  30. bit I2CWrite(unsigned char dat)  

  31. {  

  32.   bit ack; //用于暂存应答位的值  

  33.   unsigned char mask;  //用于探测字节内某一位值的掩码变量  

  34.   

  35.   for (mask = 0x80; mask != 0; mask >>= 1) //从高位到低位依次进行  

  36.   {  

  37.     if ((mask & dat) == 0) //该位的值输出到SDA上  

  38.     {  

  39.       I2C_SDA = 0;  

  40.     }  

  41.     else  

  42.     {  

  43.       I2C_SDA = 1;  

  44.     }  

  45.     I2CDelay();  

  46.     I2C_SCL = 1;          //拉高SCL  

  47.     I2CDelay();  

  48.     I2C_SCL = 0;          //再拉低SCL,完成一个位周期  

  49.   }  

  50.   I2C_SDA = 1;   //8位数据发送完后,主机释放SDA,以检测从机应答  

  51.   I2CDelay();  

  52.   I2C_SCL = 1;   //拉高SCL  

  53.   ack = I2C_SDA; //读取此时的SDA值,即为从机的应答值  

  54.   I2CDelay();  

  55.   I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线  

  56.   

  57.   return (~ack); //应答值取反以符合通常的逻辑:  

  58.   //0=不存在或忙或写入失败,1=存在且空闲或写入成功  

  59. }  

  60. /* I2C总线读操作,并发送非应答信号,返回值-读到的字节 */  

  61. unsigned char I2CReadNAK()  

  62. {  

  63.   unsigned char mask;  

  64.   unsigned char dat;  

  65.   

  66.   I2C_SDA = 1;  //首先确保主机释放SDA  

  67.   for (mask = 0x80; mask != 0; mask >>= 1) //从高位到低位依次进行  

  68.   {  

  69.     I2CDelay();  

  70.     I2C_SCL = 1;      //拉高SCL  

  71.     if(I2C_SDA == 0)  //读取SDA的值  

  72.     {  

  73.       dat &= ~mask;  //为0时,dat中对应位清零  

  74.     }  

  75.     else  

  76.     {  

  77.       dat |= mask;  //为1时,dat中对应位置1  

  78.     }  

  79.     I2CDelay();  

  80.     I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位  

  81.   }  

  82.   I2C_SDA = 1;   //8位数据发送完后,拉高SDA,发送非应答信号  

  83.   I2CDelay();  

  84.   I2C_SCL = 1;   //拉高SCL  

  85.   I2CDelay();  

  86.   I2C_SCL = 0;   //再拉低SCL完成非应答位,并保持住总线  

  87.   

  88.   return dat;  

  89. }  

  90. /* I2C总线读操作,并发送应答信号,返回值-读到的字节 */  

  91. unsigned char I2CReadACK()  

  92. {  

  93.   unsigned char mask;  

  94.   unsigned char dat;  

  95.   

  96.   I2C_SDA = 1;  //首先确保主机释放SDA  

  97.   for (mask = 0x80; mask != 0; mask >>= 1) //从高位到低位依次进行  

  98.   {  

  99.     I2CDelay();  

  100.     I2C_SCL = 1;      //拉高SCL  

  101.     if(I2C_SDA == 0)  //读取SDA的值  

  102.     {  

  103.       dat &= ~mask;  //为0时,dat中对应位清零  

  104.     }  

  105.     else  

  106.     {  

  107.       dat |= mask;  //为1时,dat中对应位置1  

  108.     }  

  109.     I2CDelay();  

  110.     I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位  

  111.   }  

  112.   I2C_SDA = 0;   //8位数据发送完后,拉低SDA,发送应答信号  

  113.   I2CDelay();  

  114.   I2C_SCL = 1;   //拉高SCL  

  115.   I2CDelay();  

  116.   I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线  

  117.   

  118.   return dat;  

  119. }  



关键字:51单片机  I2C总线

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会