[牛人杂谈] IIC的应答与非应答在IO模拟中的实现方式

[复制链接]
1422|2
 楼主| gaoyang9992006 发表于 2023-5-26 23:01 | 显示全部楼层 |阅读模式
I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,用于在数字电路之间进行短距离数据传输。在I2C通信中,设备之间通过两根总线进行数据交换,即串行数据线(SDA)和串行时钟线(SCL)。在I2C通信中,设备可以充当主设备(master)或从设备(slave)。
2C通信中的应答与非应答位用于确认数据的传输状态。应答位指示接收数据的设备是否成功接收到数据,而非应答位则表示设备无法接收数据或不需要进一步的数据传输。

在每个数据字节的传输期间,发送设备(主设备或从设备)都会提供一个数据位,并在下一个时钟周期期间等待接收设备的应答位。应答位由接收设备控制。

应答位有两种状态:

应答(ACK):表示接收设备成功接收到数据字节,并准备好接收下一个数据字节。在应答位为ACK时,接收设备会拉低SDA线,以确认数据接收。

非应答(NACK):表示接收设备无法接收数据字节,或者不需要进一步的数据传输。在非应答位为NACK时,接收设备会将SDA线保持高电平,表示拒绝接收数据。

在一个I2C传输的最后一个数据字节之后,发送设备通常会提供一个停止条件(Stop Condition),以结束传输。停止条件是发送设备将SDA线从低电平拉高到高电平时产生的。

需要注意的是,应答位由接收设备控制,而发送设备只是等待接收设备的应答。如果发送设备检测到非应答位,则可以根据具体应用程序采取相应的错误处理措施,比如重新发送数据或中止传输。

总之,应答与非应答位在I2C通信中起到了确认数据传输状态的作用,确保数据的可靠传输。


 楼主| gaoyang9992006 发表于 2023-5-26 23:02 | 显示全部楼层
如何让主机响应从机的应答呢?
  1. /*
  2. I2C ACK/NACK
  3. 应答信号:第九个时钟周期的时钟高电平时候读取SDA数据,如果SDA此时为0,则表示应答,如果为1则表示非应答。
  4. */
  5. void I2C_ACK()
  6. {
  7.         IO_SDA_SET_H();
  8.        
  9.         IO_SCL_SET_H();
  10.         if(Get_IO_SDA()==0)
  11.         IO_SCL_SET_L();
  12.         else
  13.         while(Get_IO_SDA()==1);
  14.         IO_SCL_SET_L();
  15. }

 楼主| gaoyang9992006 发表于 2023-5-26 23:03 | 显示全部楼层
那么如果MCU作为响应方如何产生应答和非应答信号呢?
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <wiringPi.h>

  5. #define SDAH digitalWrite(SDA, HIGH)
  6. #define SDAL digitalWrite(SDA, LOW)
  7. #define SCLH digitalWrite(SCL, HIGH)
  8. #define SCLL digitalWrite(SCL, LOW)
  9. #define SDAD digitalRead(SDA)

  10. // GPIO引脚定义
  11. #define SDA 0
  12. #define SCL 1

  13. // 延迟函数
  14. void delayMicroseconds(unsigned int microseconds) {
  15.     usleep(microseconds);
  16. }

  17. // 初始化GPIO引脚
  18. void initI2C() {
  19.     wiringPiSetup();
  20.     pinMode(SDA, OUTPUT);
  21.     pinMode(SCL, OUTPUT);
  22. }

  23. // 发送应答信号
  24. void sendAck() {
  25.     SDAL;   // 将SDA拉低表示应答
  26.     SCLH;   // 将SCL拉高,产生一个时钟脉冲
  27.     delayMicroseconds(2);
  28.     SCLL;   // 将SCL拉低,准备下一次数据传输
  29. }

  30. // 发送非应答信号
  31. void sendNack() {
  32.     SDAH;   // 将SDA拉高表示非应答
  33.     SCLH;   // 将SCL拉高,产生一个时钟脉冲
  34.     delayMicroseconds(2);
  35.     SCLL;   // 将SCL拉低,准备下一次数据传输
  36. }

  37. // 主函数示例
  38. int main() {
  39.     // 初始化I2C引脚
  40.     initI2C();

  41.     // 发送应答信号
  42.     sendAck();

  43.     // 发送非应答信号
  44.     sendNack();

  45.     return 0;
  46. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2052

主题

16403

帖子

222

粉丝
快速回复 在线客服 返回列表 返回顶部