0
点赞
收藏
分享

微信扫一扫

IIC通信协议,搞懂这篇就够了

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

文章首发微信公众号:混说Linux,欢迎大家关注获取更多相关文章。

IIC通信协议,搞懂这篇就够了icon-default.png?t=M3K6https://mp.weixin.qq.com/s?__biz=MzIwNDQwMjIwNQ==&mid=2247484368&idx=1&sn=0af552051a01299b9e23db15b0e7f602&chksm=96c1f8a2a1b671b496fc2d0de57275d70f22b2fa8f308e8b3b4742938517976b877e62cdaca9#rd

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

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

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

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

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

I2C通信的实现

一. 使用I2C控制器实现

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

I2C通信协议

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

一. 空闲状态

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

二. 从设备地址

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

三. 起始(START)信号

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

// 起始信号
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由低电平跳变到高电平。

// 停止信号
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,也就是前面的起始信号停止信号)。

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

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

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

// 等待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” 即可获取基于STM32上实现软件模拟IIC的完整代码。

微信公众号:混说Linux

点击原文:《IIC通信协议,搞懂这篇就够了》

举报

相关推荐

0 条评论