两招教你搞懂IIC通信协议,建议收藏后看

两招教你搞懂IIC通信协议,建议收藏后看

STM32上实现软件模IIC的完整代码找我要

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

///插播一条:我自己在今年年初录制了一套还比较系统的入门单片机教程,想要的同学找我拿就行了免費的,私信我就可以~点我头像黑色字体加我地球呺也能领取哦。最近比较闲,带做毕设,带学生参加省级或以上比///

正文开始:

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

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

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

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

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

3.等待从设备响(ACK)

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

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

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

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

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

3.等待从设备响(ACK)

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

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

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

I2C通信的实现

.使I2C控制器实现

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

.使GPIO通过软件模拟实现

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

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

I2C通信协议

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

.空闲状态

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

.从设备地址

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

.(START)信号

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

//起始信号voidIIC_start(void){

// 1.首先把数据线设置为输出模式//总线空, SCLSDA输出高SCL=1;

SDA=1;

delay_us(5);

// SDA由高变低SDA=0;

delay_us(5);

//SCL开始传输数据SCL=0;}

.(STOP)信号

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

//停止信号voidIIC_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个时钟周期释放数据线去接收对方的应答。

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

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

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

//ACK 1- 0-有效u8IIC_wait_ack(void){

u8ack=0;

//数据线设置为输入

//拉高时钟线SCL=1;

delay_us(5);

//获取数据线的电平if(SDA)

{//无效应答ack=1;

IIC_stop();

}

else

{//有效应答ack=0;

//SCL开始传输数据SCL=0;

delay_us(5);

}

returnack;}

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

voidIIC_ack(u8ack){

//数据线设置为输出

SCL=0;

delay_us(5);

if(ack)

SDA=1;//无效应答else

SDA=0;//有效应delay_us(5);

SCL=1;

//保持数据稳定delay_us(5);

//SCL开始传输数据SCL=0;}返回搜狐,查看更多

平台声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
阅读 ()
大家都在看
我来说两句
0人参与, 0条评论
登录并发表