一文带你搞懂IIC协议所有知识以及常见面经

1.1 IIC协议基础知识

1.1.1 IIC概念

    IIC是属于同步半双工通信协议,主机和从机都能双向数据传输但是同一时间只能有一个数据发送方和数据接收方。 IIC适用于小数据量以及传输距离短得场合使用。

 1.1.2 IIC 的物理结构

      IIC总共有2条通信总线(SDA,SCL),SCL为时钟同步线,用于主机和从机间数据同步操作;

这两条线使用的是开漏输出和上拉电阻,为什么需要使用开漏输出呢,原因如下:

     开漏输出概念:开漏输出就是不输出电压,低电平时接地,高电平时不接地。如果外接上拉电阻,则在输出高电平时电压会拉到上拉电阻的电源电压。这种方式适合在连接的外设电压比单片机电压低的时候。

     开漏输出的作用:

    防止短路: 在一些情况下(比如总线), 多个GPIO口可能会连接在同一根线上, 存在某个GPIO输出高电平, 另一个GPIO输出低电平的情况. 如果使用推挽输出, 你会发现这个GPIO的VCC和另一个GPIO的GND接在了一起, 也就是短路了(凉凉了). 如果换成开漏输出呢? VCC和GND多了个电阻, 这样电路就是安全的.所以总线一般会使用开漏输出.

    线与: 开漏输出还能实现线与 (自行百度), 减少一个与门, 简化电路.

    答案:IIC协议支持多个主设备与多个从设备在一条总线上, 如果不用开漏输出, 而用推挽输出, 会出现主设备之间短路的情况. 至于为什么需要上拉电阻, 那是因为IIC通信需要输出高电平的能力.

    

1.1.3 地址组成

     IIC的从设备都有其唯一的设备地址,主机依靠从机的地址实现点到点通信。

     IIC设备地址为8位,其中高7位为设备地址,最低位为读写位。读写位用低电平0表示写,高电平1表示读。

最大支持挂载的设备?

   IIC的从设备地址如果是七位地址支持最大2^7-1=127个从设备挂载,剩下一个用作广播地址,实际上,已有IIC的设备种类远远多于这个限制,在一条总线上出现相同的地址的IIC设备的概率相当高。IIC标准提出10位的地址方案。当使用10位设备地址,可以挂载的设备理论上可以达到1024个。

     实际上IIC能够挂载的设备地址会受到总线电容和总线电压的限制,IIC协议规定总线电容不超过400pF,然而随着挂载设备的提升,总线的电容会升高,信号的质量和传输的可靠性可能会受到影响,因此实际设计中的经验值建议不超过8个设备。

    10位地址对IIC协议的影响有两点:

      1.地址帧为两个字节长,原来的是一个字节

      2.第一个字节前五位最高有效作用为用作10位地址标识,约定是“11110”

     

1.1.4 速度

    IIC的传输速度有多种标准模式,快速模式,高速模式都是双向传输,高速模式会兼容低俗模式,而超快速传输是单向传输且不兼容其他模式。要记住的是最快的速度1标准速度为100kb/s,最快的双向速度传输为3.4Mb/s

    标准模式速率:100kbit/s, 标准模式是I2C总线最基本的通讯速度。在标准模式下,时钟频率最高可以达到100 kHz,总线电容最大为400 pF。这种通讯速度适用于较长的总线和较慢的设备,如LCD显示屏、温度传感器等。

    快速模式速率:400kbit/s, 快速模式是I2C总线的一种较快的通讯速度。在快速模式下,时钟频率最高可以达到400 kHz,总线电容最大为400 pF。这种通讯速度适用于数据传输速度要求较高的设备,如EEPROM、实时时钟等。

    快速模式+:1Mbit/s,快速模式加是I2C总线的一种改进版快速模式。在快速模式加下,时钟频率最高可以达到1 MHz,总线电容最大为400 pF。这种通讯速度适用于对数据传输速度要求更高的设备,如高速ADC、高速数字信号处理器等。

    高速模式:3.4Mbit/s, 高速模式是I2C总线的一种较快的通讯速度。在高速模式下,时钟频率最高可以达到3.4 MHz,总线电容最大为400 pF。这种通讯速度适用于对数据传输速度要求非常高的设备,如高清视频处理器、高速闪存等。

    超快速模式:5Mbit/s,超高速模式是I2C总线的一种非常快的通讯速度。在超高速模式下,时钟频率最高可以达到5 MHz,总线电容最大为200 pF。这种通讯速度适用于需要超高速数据传输的设备,如图像处理器、高速网络接口等。

    注意:上拉电阻的数值决定了总线上的电平转换速度,较大的上拉电阻会导致总线上的电平变化速度较慢,而较小的上拉电阻则会使电平变化速度更快。当需要提高IIC总线上的速率的时候,因此,在调整速度的时候需要调整相应的上拉电阻数值。

可以采取以下两种方法来调整上拉电阻:

       1.减小上拉电阻的数值:通过减小上拉电阻的阻值,可以加快总线上的电平变化速度,从而提高总线的速率。

        2.使用强驱动能力的器件:除了调整上拉电阻的数值外,还可以选择具有较高驱动能力的器件来驱动IIC总线。这些器件能够提供更大的电流,从而加快总线上的电平变化速度,进而提高总线的速率。

1.2 IIC的信号

    IIC总线在没有通信时的状态称为空闲状态,此时IIC总线的SDA和SCL两条线都处于高电平。在通信的时候,IIC的信号有四种:

    a. 起始信号

    开始条件:SDA,SCL都为高

    起始信号:SCL为高电平时,SDA从高到低。

    结束条件:SDA和SCL都处于低电平。

    b.停止信号

    开始条件:SDA,SCL都为低

    时钟线拉高:SCL拉高先

    结束信号:在时钟线为高的时候,SDA从低变高

   c.应答信号

    应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;

    有效应答:SDA为低电平,SCL经历一个完整的时候, 也就是SCL为高电平时候,SDA为低电平

    

     应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

  有效非应答:SDA为高电平,SCL经历一个完整的时候, 也就是SCL为高电平时候,SDA为高电平

   d.数据信号

    发送数据和接收数据时通用。当SCL为高电平,如果SDA始终为高电平时表示逻辑1,如果SDA始终为低电平表示逻辑0.

1.3 IIC发送数据帧

    发送一帧

起始条件+要发送到的地址(0,发送数据)+接收应答位+发送的8位数据+接收应答位+…+停止条件

  接收一帧

起始条件+发送要读取的地址(0,为发送数据)+接收应答位+读取的8位数据+发送应答位(0, 应答)+…+读取的8位数据+应答位(1,不应答,因为想停止读取)+停止条件

   随机读,先发送要读取的寄存器地址,再接收该地址数据

起始条件+要发送到的地址(1, 读取数据)+接收应答位+发送的8位数据+接收应答位+起始条件+要读取的地址(0,为发送数据)+接收应答位+读取的8位数据+发送应答位(0, 应答)+…+读取的8位数据+发送应答位(1,不应答,因为想停止读取)+停止条件

   字节写

起始条件+要发送到的设备地址(0,为发送数据)+应答位+要发送到要写入的地址+应答位+发送的8位数据+应答位+…+停止条件

1.4 IIC 的时序列总结  以及代码实现

起始信号代码:

void IIC_Start(void)
{
    SDA_H;            // 拉高SDA
    SCL_H;            // 拉高SCL  先拉高两条线是为了确保空闲状态两个都是高电平
    delay_us(speed);  // 延时控制速度
    SDA_L;            // 启动信号,SCL高电平的时候,SDA从高电平变为低电平
    delay_us(speed);  // 延时,控制速度
    SCL_L;            // 为了准备下一个时钟周期以及接下来的数据传输做准备。
}

中止信号代码:

void IIC_Stop(void)
{
    SDA_L;  //  
    SCL_L;  // 拉低SCL代码是为了确保从设备能够检测出SDA的变化
    delay_us(speed);
    SCL_H;  //SCL线 
    SDA_H;  // 拉高SDA线,当SCL为高时,SDA线一个上升沿代表停止
    delay_us(speed);
}

应答信号代码

//产生ACK应答,读取从机一字节数据后还要接着读的时候使用
//SCL在SDA一直为低电平期间完成低高电平转换
void IIC_ACK(void)
{
    SCL_L;   // 拉低SCL是为了让从设备检测到SDA的变化
    SDA_L;   // SDA为低电平表示ACK应答信号
    delay_us(speed);
    SCL_H;   // 经历一个完整的高电平时钟
    delay_us(speed);
    SCL_L;   
}

//不产生ACK应答,读取从机一字节数据后不读了的时候使用    
//SCL在SDA一直为高电平期间完成低高电平转换
void IIC_NACK(void)
{
    SCL_L;   // 拉低SCL是为了让从设备检测到SDA的变化
    SDA_H;   // SDA为高电平表示ACK应答信号
    delay_us(speed);
    SCL_H;   // 经历一个完整的高电平时钟
    delay_us(speed);
    SCL_L;   
}
//等待ACK应答    
//发送完一个字节后(释放SDA)的下一个时钟高电平时期,读取SDA电平,0为收到应答
bool IIC_Wait_ACK(unsigned int timeOut)
{
    SDA_H;
    delay_us(speed);
    SCL_H;
    delay_us(speed);
    while(SDA_R)
    {
        if(--timeOut)
        {
           printf("Wait IIC timeOut\r\n");
           IIC_Stop();            // 超时未收到应答,停止总线
           return IIC_Err;  //返回失败
        }
        delay_us(speed);
    }
    SCL_L;
    return IIC_OK;   
}

发送一个字节的数据:

void IIC_Send_Byte(unsigned char byte)
{
    unsigned char count = 0;
    SCL_L;              // 拉低时钟进行数据传输
    for(;count < 8; count++)
    {
        if(byte & 0x80)
          SDA_H;
        else
          SDA_L;
        byte <<= 1;  // 数据从高位开始发送,大端传输
        delay_us(speed);
        SCL_H;       // SCL经历一个完整的时钟
        delay_us(speed);
        SCL_L;
    }
}

读取一个字节的数据:

unsigned char IIC_Read_Byte(void)
{
    unsigned char count = 0, receive = 0;
    SDA_H;   // 拉高SDA是为了更好地读取从机的数据
    for(; count < 8; count++)
    {
        SCL_L; // 拉低从机放数据
        delayus(speed); 
        SCL_H;  // 拉高主机读取数据
        receive <<= 1;
        if(SDA_R)  //如果读取的是高电平
        {
            receive += 1;  
        }
        delayus(speed);
    }
    return receive;
}

发送到从机一个字节的具体流程

void IIC_SEND_Slave_Byte(uint8_t slaveaddr,uint8_t registeraddr,uint8_t byte)
{
    IIC_Start(); \\ 开始信号
    IIC_Send_Byte(slaveaddr); \\ 发送从机地址,最低为0
    IIC_Wait_Ack();       \\ 等待应答
    IIC_Send_Byte(registeraddr); \\ 发送寄存器地址
    IIC_Wait_Ack();       \\ 等待应答
    IIC_Send_Byte(byte); \\ 发送寄存器地址
    IIC_Wait_Ack();       \\ 等待应答
    IIC_Stop();     \\ 停止传输   
    
}

发送多个字节的具体流程

void IIC_SEND_Slave_BYTES(uint8_t slaveaddr,uint8_t  registeraddr,uint8_t  *pbuffer,uint16_t  num ){
    IIC_Start();
    IIC_Send_Byte(slaveaddr);
    IIC_Wait_Ack();
    IIC_Send_Byte(registeraddr);
    IIC_Wait_Ack();
    for(int i = 0; i < num; i++)
    {
      IIC_Send_Byte(*(pbuffer+i));
      IIC_Wait_Ack();  // 没发送一个字节都需要一个应答
    }
    IIC_Stop();  // 中止通讯
    
}

指定地址读:

void I2C_READ_Slave_BYTES(u8 slaveaddr,u8 registeraddr,u8 *pbuffer,u16 num )
{
    IIC_Start();  // 开始通信
    IIC_Send_Byte(slaveaddr);
    IIC_Wait_Ack();
    IIC_Send_Byte(registeraddr);
    IIC_Wait_Ack();
    IIC_Start();   // 重新开始信号
    IIC_Send_Byte(slaveaddr + 0x01); // 改为读信号
    IIC_Wait_Ack();
    for(int i = 0; i < num; i++)
    {
        *(pbuffer+i) = IIC_Read_Byte();
        if(i == num - 1)  // 字节没发完需要给个应答信号,发到最后一个字节的时候给个非应答信号
        {
          IIC_NAck();
        }else
        {
          IIC_Ack();   
        }
    }
    IIC_Stop();    
    
}

1.5 IIC同步

 什么是线与,就是所有连接到该线的电平均为1才为1,有一个为0则为0。

1.当发送数据都为1时候,数据线的呈现的逻辑为高电平。

2.当发送数据有0的时候,数据线的呈现的逻辑为低电平。

线与逻辑如何实现仲裁

     通过线与逻辑就可以仲裁主机,如下图所示,在第四个红框的时候,主器件A和主器件B发送的数据为高电平,主器件C为低电平。此时数据线呈现低电平,A和B与数据线电平不相同,退出竞争。C相同获得数据线的归属权。

  

     时钟同步只会在仲裁时发生。SCL是由主机产生的时钟信号,用于和从机确定数据发送和采样的时间点。倘若处在仲裁期间,会有多个主机同时发送往SCL上发送时钟信号。两个主机配置的通信速率可能不同,因此时钟频率必然不同;即使配置了相同的通信速率,两者开始发送数据的时间也不同。这就要使用时钟同步来完成。

    1.时钟同步是通过连接到SCL总线的I2C接口“线与”实现

    2.SCL线上的低电平时间是由时钟低电平最长的器件决定,SCL的高电平则是由高电平时间最短的期间决定   

    3.时钟同步解决了I2C总线设备间的速度同步

       总结: 时钟同步是在主设备冲突的时候发生的,在仲裁期间,会有多个主机同时发送往SCL上发送时钟信号,需要时钟同步调整速率一致,具体来说就是SCL线上的低电平时间是由时钟低电平最长的设备决定,SCL的高电平则是由高电平时间最短的期间决定 ,通过这一方法可以同步所有设备的时钟,更好的实现仲裁。

1.6 IIC仲裁    

     IIC的仲裁是通过线与逻辑实现仲裁的,比较主机发送的数据和数据线上的数据。发送的数据一致,继续竞争,数据不一致,退出竞争。仲裁只有在系统使用多个主设备时才需要,而从设备(slave)不参与仲裁程序。当然,只有在主线空闲的情况下,主设备才可以发起传输。两个主机可以在启动条件的最小保持时间内生成一个启动条件,从而在总线上生成一个有效的传输启动条件,然后仲裁程序决定哪一个主设备可以完成它的传输。下面就是仲裁的规则:

    谁现在SDA线上发送低电平,谁就掌握对总线的控制权。

    IIC总线的控制权完全取决于竞争主设备发送的地址和数据,因此没有中央主设备,总线上也没有任何优先级顺序。


仲裁的步骤:

    1.当两个master对同一个地址的slave进行传输时,多个master会都能进入数据周期,仲裁会单比特对单比特进行比较。
    2.在SCL为高的每一个比特位期间,每个主设备检查SDA线的电平是否与它所发送的相匹配。这个过程很可能需要比对很多位。
    3.如果传输的数据时完全相同的,则这个主设备可以完成地发送整个事务。
当主设备发送的比特位与SDA线不匹配时,例如图中DATA1在SCL线的第三个周期,此时DATA1拉高,而DATA2W为低,DATA1和DATA2在线与后SDA为低,匹配不成功。当主设备1检测到一个与自身不相符的低电平,这时会关闭主设备1的SDA传输驱动,另一个主设备2会继续完成传输。

        总结: IIC的仲裁是发生在多个主设备想要利用总线产生总线冲突时,按“低电平优先”的原则,把总线判给在数据线上先发送低电平的器件,当主设备发现总线电平与自己不一致的时候就会退出竞争。

1.7 时钟拉伸

       时钟拉伸就是完成时钟同步中的事,将主从设备间数据传输同步。时钟拉伸是通过保持SCL信号拉低来暂停事务的,期间传输不能继续,直到SCL信号再次被拉高。时钟拉伸需要设备包含SCL驱动程序,而大多数的从设备不包含SCL驱动程序,所以他们无法拉伸时钟。

​         在字节传输级别,设备可能能够以较快地速度接受字节数据,但是需要更多的时间来存储接受到的字节或准备传输另一个字节。在字节发送ACK位之后,从设备可以拉低SCL总线,迫使主设备进入等待状态,直到设备准备好下一个字节的传输。

​         在比特级别,无论是否为I2C总线提供有限的硬件,都可以通过延长每个时钟的低周期来降低总线时钟时钟的速度。

       总结: 时钟拉伸是用于调整主从设备速率不一致的时候发生的,当从设备速度较慢或需要处理其他事情的时候,从设备主动拉低SCL线通知主设备,直到SCL释放SCL,主设备才进入下一个时许,时钟拉伸解决了I2C主从设备的数率同步问题,使得数据传输更可靠。

1.8 面试问题:

  1.IIC的驱动程序的了解?

  2. 最多可以挂载多少个设备?

       从设备数量

        IIC的从设备地址为7位地址,减去一位广播地址0x00,2^7 -1= 127个地址,所以IIC在使用7位地址的时候最多支持127个设备,如果使用10位地址最多支持1024个设备。然而上述只是一个理论可以挂载的数量,实际上,挂载设备数量还收到电容的影响,I2C总线上的每个设备都有一定的输入和输出电容。当总线上连接的设备数量增加时,总线电容的总和也会增加。这样,总线的负载能力和传输速度可能会受到影响。一般来说IIC能够接受的挂载数量为8个以内。(7位,127, 一位广播, 10位1024, 实际, 电容, 8个)

      主设备数量

      IIC支持多个主设备,但是同一个时刻只能有一个主设备处于活动状态,当一个主设备发起通信时,它会控制整个总线,并与所选的从设备进行数据交换。其他主设备和从设备会保持静默状态,直到当前的主设备释放总线。一旦当前的主设备完成与从设备的通信,它将释放总线,然后其他主设备可以竞争获取总线控制权,并选择与所选的从设备进行通信,这种机制确保在同一时刻只有一个主设备在总线上工作,避免冲突和数据干扰。主设备的对总线的控制的决定权是依赖于IIC基于硬件的线与功能实现的仲裁机制来决定的。(多设备,同一时刻只有一个主设备处于活动,这是IIC基于线与功能的仲裁机制来实现的 )

3. IIC 仲裁协议, 时钟同步, 时钟拉伸(时钟拓展)

       IIC的仲裁是发生在多个主设备想要利用总线产生总线冲突时,按“低电平优先”的原则,把总线判给在数据线上先发送低电平的器件,并且仲裁只发生在SCL的高电平期间。(主设备之间,冲突,低电平优先,只发生在SCL的高电平)

      时钟同步是在主设备冲突的时候发生的,在仲裁期间,会有多个主机同时发送往SCL上发送时钟信号,需要时钟同步调整速率一致,具体来说就是SCL线上的低电平时间是由时钟低电平最长的设备决定,SCL的高电平则是由高电平时间最短的期间决定 ,通过这一方法可以同步所有设备的时钟,更好的实现仲裁。(主设备速率不一致, 时钟同步调整,低电平最长低电平, 高电平需要等待所有低电平变为高电平,更好实现仲裁)

     时钟拉伸是用于调整主从设备速率不一致的时候发生的,当从设备速度较慢或需要处理其他事情的时候,从设备主动拉低SCL线通知主设备,直到SCL释放SCL,主设备才进入下一个时序,时钟拉伸解决了I2C主从设备的数率同步问题,使得数据传输更可靠。(从设备速率不一致, 从主动拉低SCL, 解决主从速率同步问题)

  4.IIC通讯如何去选择一个device?有广播的功能吗?支持多个device传输数据?

       IIC的从设备地址有其唯一的设备地址,当主设备想要选择从设备的时候会发送一个起始信号,然后发送设备地址加上读写位,收到从设备应答后就可以发送或者接收从设备的数据。(地址唯一, 起始 + 设备地址(读/写) + 应答 + 发送/接收数据)

   IIC协议本身并不具备广播功能,因为IIC是一个用于点对点的串行通信协议,然而其存在一个特殊地址,称为广播地址0x00,使用该地址可以发送一些所有设备都感兴趣的命令,这在某种程度上类似于广播,但并不是真正的广播,因为它不涉及数据传输,而仅仅是一个信号,用来唤醒所有设备或执行某些所有设备都认可的操作。(点到点通信协议,广播地址0X00,命令信号, 不传输数据)

    IIC支持在总线上挂载多个设备,但由于IIC是一种半双工的协议,意味着在任何给定的时间,在同一时间段只能有一个主设备和一个从设备通信,且只有一个通信数据的方向是活跃的。如果一定要同时通信,可以考虑使用多个I2C总线,或者采用轮询访问,主设备可以循环遍历每个从设备的地址,并依次与它们通信。(半双工, 同一时间主从一个方向通信, 实现方式:轮询)

  5.IIC协议中上拉电阻和速率的关系,如果是速率高,上拉电阻如何调整?

     上拉电阻的数值决定了总线上的电平转换速度。较大的上拉电阻会导致总线上的电平变化速度较慢,而较小的上拉电阻则会使电平变化速度更快。当需要提高IIC总线的速率时,一方面可以通过通过减小上拉电阻的阻值,加快总线上的电平变化速度,从而提高总线的速率;另一方面,除了调整上拉电阻的数值外,还可以选择具有较高驱动能力的器件来驱动IIC总线,这些器件能够提供更大的电流,从而加快总线上的电平变化速度,进而提高总线的速率。(电阻大电平转换慢,电阻小电平转换慢, 两种方法调整速率:减少电阻,采用驱动能力强的器件 )

  6.IIC为什么要开漏输出和上拉电阻。

      由于IIC支持一主多从或多主多从通信方式,多个设备挂载在同一个总线上,如果采用推挽输出,其中一个设备输出高电平,另一个设备输出低电平就会造成短路。而开漏输出允许多个设备共享同一个总线或信号线,通过合理的电平控制,实现对总线或信号线的协调使用,避免冲突和干扰。(一主多从,多主多从, 短路)

       开漏输出需要使用外部上拉电阻来提供引脚的高电平信号。这是因为开漏输出只能提供低电平信号,而不能主动提供高电平信号。因此,在使用开漏输出时,需要添加适当大小的上拉电阻以确保正确的高电平水平。(开漏输出只能输出低电平,需要加上拉电阻才能提供高电平)

  7.IIC的优势有哪些

       简单且灵活:I2C仅需要两根线(SDA和SCL)来进行通信,使得硬件连接和布线变得简单。

       可靠性高:I2C协议采用了主从架构,由主设备控制总线上的数据传输。主设备协调和同步设备之间的通信,避免了设备之间的冲突。带有确认的数据传输是得数据更加可靠。

       多设备支持:IIC支持一主多从,每个设备都有唯一的地址,主设备可以通过指定地址来选择与之通信的设备,同时IIC还支持多主多从,通过特有的IIC特有的线与仲裁机制,实现多个主机设备发送数据冲突的时候确只有一个主机继续发送数据,避免了数据的冲突和错误。

       低功耗:I2C在基本模式下使用了开漏输出结构,使得设备在非活动状态下可以撤离总线,从而降低功耗。此外,I2C还支持多速率传输,可以根据需求选择适当的速率,进一步降低功耗。

        (简单且灵活:两条线    可靠性高:主从架构,应答信号,   多设备支持:从设备地址, 仲裁,   低功耗:开漏输出, 多速率传输)

8. 软件IIC和硬件IIC的区别

     硬件IIC是通过专门的硬件电路实现的,而软件IIC是通过软件控制GPIO口管脚来模拟IIC协议的时许的。总结来说,硬件I2C具有高速传输、低占用率和稳定性高的优点,适用于对传输速度和稳定性要求较高的场景;而软件I2C具有灵活性高和可移植性强的特点,适用于没有硬件I2C支持或需要扩展硬件I2C功能的场景

     硬件IIC的优势:高速传输 + 低占用率(不需要CPU的干预)+稳定性高(时序由硬件控制,不受外部干扰)

      软件IIC的优势:灵活性高(任意GPIO口)+ 可移植性强 + 适用范围广 。

9.通过IIC配置外设失败了,一般从哪几种角度出发排查

  • 硬件连接问题:检查IIC总线的物理连接是否正确。确保SDA(数据线)和SCL(时钟线)正确连接到外设和主控制器,并且没有短路或断开的情况。还要确保上拉电阻的数值和位置正确。
  • 电源供电问题:确认外设和主控制器都正常供电,并检查电源电压是否在可接受范围内。低电压可能导致通信错误或不稳定。
  • 地址设置问题:检查外设的地址设置是否正确。确保外设的IIC地址与要求的地址匹配。有些外设具有可编程地址,因此需要验证是否正确设置了地址。
  • IIC协议参数设置问题:确保主控制器和外设之间的IIC协议参数设置一致,如速率、传输模式等。确认主控制器发送的start bit、stop bit等控制信号正确地驱动外设。
  • 软件程序问题:检查软件代码是否正确实现了IIC通信协议。确认发送和接收的数据格式、顺序、时序是否符合规范。还要确保正确处理ACK(应答)信号和超时等异常情况。
  • 外设工作状态问题:检查外设自身是否正常工作。对于某些外设,可能需要进行初始化或配置才能正常通信。确保外设处于正确的模式或状态。
  • 检查时序:使用示波器或逻辑分析仪检查I2C通信的时序,确保START、ACK、STOP条件等都符合I2C协议要求

链接:

I2C的硬件实现_硬件iic-CSDN博客

STM32硬件I2C与软件模拟I2C超详解_stm32 i2c-CSDN博客

I2C中的时钟同步与仲裁_iic从机时钟-CSDN博客

【接口协议】04.IIC_牛客网

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值