找回密码
 立即注册
查看: 57|回复: 2

请大咖赐教IIC读一个字节的代码意思

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:582
  • 最近打卡:2025-10-15 07:15:58

27

主题

123

回帖

443

积分

中级会员

积分
443
发表于 4 天前 | 显示全部楼层 |阅读模式
STC32G12K实验箱代码包第二十七节“27-I2C从机中断模式与IO口模拟I2C主机进行自发自收”中从IIC读取一个字节函数do循环上方SDA =1 这一行是什么意思,没明白,在实验过程中,屏蔽这一行,首次读取是对的,第二次读取就错了,请大佬详解,最好结合时序图,谢谢


u8 I2C_ReadAbyte(void)          //read A byte from I2C
{
    u8 i,dat;
    i = 8;
    SDA = 1;    //为何要事先拉高电平。
    do
    {
        SCL = 1;
        I2C_Delay();
        dat <<= 1;
        if(SDA)     dat++;
        SCL  = 0;
        I2C_Delay();
    }
    while(--i);
    return(dat);
}


另外等候从机应答代码第一行SDA=1拉高电平延时是什么意思,实验过程中,屏蔽了这个延时(如下红色字体代码),代码也能正常工作。

void IIC_WAITACK(void)        //等到从机ACK
{
        SDA        = 1;
//        IIC_DELAY();
        SCL = 1;
        IIC_DELAY();
        ack = SDA;
        IIC_DELAY();
        SCL = 0;
        IIC_DELAY();
}


回复

使用道具 举报 送花

3

主题

1880

回帖

608

积分

等待验证会员

积分
608
发表于 4 天前 | 显示全部楼层
在I²C通信中,SDA = 1;这一行代码的作用是在读取一个字节之前,确保SDA(数据线)处于高电平状态。这一操作看似简单,实则与I²C总线的电气特性和通信时序密切相关。下面我们从I²C协议、硬件接口和时序角度详细解释这一行代码的意义,并结合时序图帮助理解。

一、I²C通信的基本原理

I²C(Inter-Integrated Circuit)是一种半双工同步串行通信协议,使用两根线进行通信:
SCL(Serial Clock):时钟线,由主机控制,用于同步数据传输。
SDA(Serial Data):数据线,用于传输数据,由主机或从机控制。

I²C总线采用漏极开路(Open-Drain)输出结构,因此所有设备只能主动拉低SDA/SCL,而不能主动拉高。总线的高电平由外部上拉电阻提供。

二、为何在读取前要执行SDA = 1;

1. 硬件层面:确保SDA为高电平

在STM32或其他单片机中,I/O口配置为开漏输出(Open-Drain)时,写1并不意味着引脚实际输出高电平,而是释放引脚,使其由外部上拉电阻拉高。因此:
SDA = 1;表示将SDA引脚设为高阻态(释放),允许外部上拉将其拉高。
如果不执行这一步,SDA可能仍被上一次操作拉低,导致后续读取错误。

2. 协议层面:为读取数据做准备

在I²C通信中,主机读取数据时,每个数据位的采样发生在SCL上升沿。在SCL上升沿到来前,SDA必须稳定在某个电平(高或低)。因此:
在每次读取数据位前,必须确保SDA已经释放(即高阻态),否则可能被上一次操作遗留的低电平干扰。
执行SDA = 1;正是为了释放SDA线,使其恢复高电平,为后续的数据位读取做好准备。

三、为何屏蔽这一行会导致首次正确、第二次错误?

情景分析:
首次读取时:SDA可能初始状态为高电平,因此即使没有执行SDA = 1;,也能正确读取。
第二次读取时:由于上一次读取过程中,SDA可能被拉低(例如在ACK/NACK响应中),若不释放SDA,则SDA仍保持低电平,导致主机误读为“0”。

举例说明:

假设你在读取第一个字节时SDA为高电平,读取成功;但在读取第二个字节时,SDA仍被拉低(未释放),那么即使从机发送的是“1”,主机也会读到“0”,导致数据错误。

四、结合I²C时序图分析

以下是I²C读取一个字节的标准时序图:
  1. SCL:  ↑↑↑↑↑↑↑↑
  2.        ↑    ↑    ↑    ↑    ↑    ↑    ↑    ↑    ↑
  3. SDA:   [D7] [D6] [D5] [D4] [D3] [D2] [D1] [D0]
复制代码
每个数据位在SCL上升沿被采样。
在SCL上升沿之前,SDA必须稳定。
在SCL下降沿之后,SDA可以改变。

在读取前,若SDA未释放(未执行SDA = 1;),则可能SDA仍为低电平,导致第一个数据位(D7)被误读为“0”。

五、代码逻辑分析

我们来看你提供的代码片段:

```c
u8 I2CReadAbyte(void)          //read A byte from I2C
{
    u8 i,dat;
    i = 8;
    SDA = 1;    //为何要事先拉高电平。
    do
    {
        SCL = 1;
        I2CDelay();
        dat

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:328
  • 最近打卡:2025-10-15 08:50:20
已绑定手机

85

主题

3256

回帖

7196

积分

荣誉版主

无情的代码机器

积分
7196
发表于 4 天前 | 显示全部楼层

豆包解答:和楼上智能回答一个意思
截图202510121618236042.jpg
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-16 05:38 , Processed in 0.116040 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表