打印
[牛人杂谈]

IIC的应答与非应答在IO模拟中的实现方式

[复制链接]
884|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 | 只看该作者
如何让主机响应从机的应答呢?
/*
I2C ACK/NACK
应答信号:第九个时钟周期的时钟高电平时候读取SDA数据,如果SDA此时为0,则表示应答,如果为1则表示非应答。
*/
void I2C_ACK()
{
        IO_SDA_SET_H();
       
        IO_SCL_SET_H();
        if(Get_IO_SDA()==0)
        IO_SCL_SET_L();
        else
        while(Get_IO_SDA()==1);
        IO_SCL_SET_L();
}

使用特权

评论回复
板凳
gaoyang9992006|  楼主 | 2023-5-26 23:03 | 只看该作者
那么如果MCU作为响应方如何产生应答和非应答信号呢?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>

#define SDAH digitalWrite(SDA, HIGH)
#define SDAL digitalWrite(SDA, LOW)
#define SCLH digitalWrite(SCL, HIGH)
#define SCLL digitalWrite(SCL, LOW)
#define SDAD digitalRead(SDA)

// GPIO引脚定义
#define SDA 0
#define SCL 1

// 延迟函数
void delayMicroseconds(unsigned int microseconds) {
    usleep(microseconds);
}

// 初始化GPIO引脚
void initI2C() {
    wiringPiSetup();
    pinMode(SDA, OUTPUT);
    pinMode(SCL, OUTPUT);
}

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

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

// 主函数示例
int main() {
    // 初始化I2C引脚
    initI2C();

    // 发送应答信号
    sendAck();

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

    return 0;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1951

主题

15890

帖子

206

粉丝