【IIC通信协议】

I2C(IIC)属于两线式串行总线,由飞利浦公司开发用于微控制器(MCU)和外围设备(从设备)进行通信的一种总线,属于一主多从(一个主设备(Master),多个从设备(Slave))的总线结构总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其他设备

物理I2C接口有两根双向线,串行时钟线(SCL)串行数据线(SDA) 组成,可用于发送和接收数据,但是通信都是由主设备发起,从设备被动响应,实现数据的传输。

640.png


I2C主设备与从设备的一般通信过程

注:两个设备是SCL和SCL连接,SDA和SDA连接

一. 主设备给从设备发送/写入数据:

  1. 主设备发送起始(START)信号

  2. 主设备发送设备地址到从设备

  3. 等待从设备响应(ACK)

  4. 主设备发送数据到从设备,一般发送的每个字节数据后会跟着等待接收来自从设备的响应(ACK)

  5. 数据发送完毕,主设备发送停止(STOP)信号终止传输

640-16987421934761.png

二. 主设备从从设备接收/读取数据

  1. 设备发送起始(START)信号

  2. 主设备发送设备地址到从设备

  3. 等待从设备响应(ACK)

  4. 主设备接收来自从设备的数据,一般接收的每个字节数据后会跟着向从设备发送一个响应(ACK)

  5. 一般接收到最后一个数据后会发送一个无效响应(NACK),然后主设备发送停止(STOP)信号终止传输

640-16987421934772.png

注:具体通信过程需视具体时序图而定


I2C通信的实现

一. 使用I2C控制器实现

就是使用芯片上的I2C外设,也就是硬件I2C,它有相应的I2C驱动电路,有专用的IIC引脚,效率更高,写代码会相对简单,只要调用I2C的控制函数即可不需要用代码去控制SCL、SDA的各种高低电平变化来实现I2C协议,只需要将I2C协议中的可变部分(如:从设备地址、传输数据等等)通过函数传参给控制器,控制器自动按照I2C协议实现传输,但是如果出现问题,就只能通过示波器看波形找问题。

二. 使用GPIO通过软件模拟实现

软件模拟I2C比较重要因为软件模拟的整个流程比较清晰哪里出来bug很快能找到问题模拟一遍会对I2C通信协议更加熟悉

如果芯片上没有IIC控制器,或者控制接口不够用了,通过使用任意IO口去模拟实现****IIC通信协议,手动写代码去控制IO口的电平变化,模拟IIC协议的时序,实现IIC的信号和数据传输,下面会讲到根据通信协议如何用软件去模拟


I2C通信协议

IIC总线协议无非就是几样东西:起始信号停止信号应答信号、以及数据有效性

一. 空闲状态

时钟线(SCL)和数据线(SDA)接上拉电阻默认高电平表示总线是空闲状态

二. 从设备地址

从设备地址用来区分总线上不同的从设备,一般发送从设备地址的时候会在最低位加上读/写信号,比如设备地址为0x50,0表示读,1表示写,则读数据就会发送0x50,写数据就会发送0x51。

三. 起始(START)信号

I2C通信的起始信号由主设备发起,SCL保持高电平,SDA由高电平跳变到低电平。

640-16987421934773.png

// 起始信号
void IIC_start(void)
{
    // 1.首先把数据线设置为输出模式
    // 总线空闲, SCL和SDA输出高
    SCL = 1;  
    SDA = 1;
    delay_us(5);
    
    // SDA由高变低
    SDA = 0;
    delay_us(5);
    
    // 拉低SCL开始传输数据
    SCL = 0;
}

四. 停止(STOP)信号

I2C通信的停止信号由主设备终止,SCL保持高电平,SDA由低电平跳变到高电平。

640-16987421934774.png

// 停止信号
void IIC_stop(void)
{
    // 1.首先把数据线设置为输出模式
    
    // 拉高时钟线
    SDA = 0;
    delay_us(5);
    SCL = 1;
    delay_us(5);
    
    // SDA由低变高
    SDA = 1;
}

五. 数据有效性

I2C总线进行数据传送时,在SCL的每个时钟脉冲期间传输一个数据位,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有在时钟线SCL上的信号为低电平期间,数据线SDA上的高电平或低电平状态才允许变化,因为当SCL是高电平时,数据线SDA的变化被规定为控制命令STARTSTOP,也就是前面的起始信号停止信号)。

640-16987421934775.png

六. 应答信号(ACK:有效应答,NACK:无效应答)

接收端收到有效数据后向对方响应的信号,发送端每发送一个字节(8位)数据,在第9个时钟周期释放数据线去接收对方的应答。

当SDA是低电平为有效应答(ACK),表示对方接收成功

当SDA是高电平为无效应答(NACK),表示对方没有接收成功

发送数据需要等待接收方的应答:

// 等待ACK   1-无效    0-有效
u8 IIC_wait_ack(void)
{
    u8 ack = 0;
    // 数据线设置为输入
    // 拉高时钟线
    SCL = 1;
    delay_us(5);
    // 获取数据线的电平
    if(SDA)
    {   // 无效应答
        ack = 1;
        IIC_stop();
    }
    else
    {   // 有效应答
        ack = 0;
        // 拉低SCL开始传输数据
        SCL = 0;
        delay_us(5);
    }
    return ack;
}

接收数据需要向发送方发送应答:

void IIC_ack(u8 ack)
{
    // 数据线设置为输出
    SCL = 0;
    delay_us(5);
    
    if(ack)
        SDA = 1; // 无效应答
    else
        SDA = 0; // 有效应答      
    delay_us(5);
    SCL = 1;
    // 保持数据稳定
    delay_us(5);
    // 拉低SCL开始传输数据
    SCL = 0;
}
### IIC通信协议概述 IIC(Inter-Integrated Circuit),即内部集成电路总线,是一种同步串行通信协议,由Philips公司开发。该协议允许多个器件通过两条信号线进行全双工通信:一条用于发送时钟脉冲(SCL),另一条负责数据传输(SDA)。这种设计简化了硬件连接并减少了所需的引脚数量[^1]。 #### 协议工作原理 在IIC通信过程中,主机控制着整个会话流程,包括启动条件、停止条件以及设置时钟频率等操作。当需要发起一次新的通讯时,主机会先发出起始位通知从机准备接收命令;接着传送地址信息指明目标节点身份;随后依据具体需求执行读写动作直至结束标志的到来表示此次交互完成[^2]。 对于每字节的数据交换,在第9个周期内还需要附加确认应答机制来确保双方已经成功接收到消息内容。如果接收方能够正常处理,则拉低SDA电平作为回应;反之则保持高阻态不变以告知对方存在错误情况发生[^3]。 ```cpp // C++代码示例展示简单的IIC写入函数 void iic_write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t data){ start_condition(); // 发送开始条件 send_byte(deviceAddress << 1 | WRITE); // 发送设备地址加上写指令 wait_for_acknowledge(); // 等待ACK响应 send_byte(registerAddress); // 发送寄存器地址 wait_for_acknowledge(); send_byte(data); // 发送要写入的数据 wait_for_acknowledge(); stop_condition(); // 结束本次通信 } ``` #### 应用场景分析 得益于其简洁性和灵活性特点,IIC广泛存在于各类电子产品之中: - **传感器模块**:如温度湿度计、加速度陀螺仪组合单元等; - **存储装置**:EEPROM、Flash Memory等非易失性记忆体组件; - **实时时钟RTC电路板卡**:提供精准的时间基准服务给其他外围设施使用; - **显示驱动屏控制器**:LCD/OLED显示屏背后的逻辑运算核心部分往往也采用此方式实现与MCU之间的联系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值