STM32通信协议IIC基本原理

简单介绍一下IIC,内容适用于有一定IIC基础,但是又不是很清楚的朋友。

I²C(Inter-Integrated Circuit)字面上的意思是集成电路总线,它其实是I²C Bus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I²C的正确读法为“I平方C”(“I-squared-C”),而“I二C”(“I-two-C”)则是另一种错误但被广泛使用的读法。

IIC通信依据于两根通信线,是一种双线半双工的串口通信。

双线是一种极简的通信方式,简单必然会带来较为复杂的通信协议设置。双线为时钟线SCL、数据线SDA。

这儿插入一句
一根线上的信号形式共计四种0、1、下降沿、上升沿。(这里面是开漏模式,接上拉电阻,开漏就是高电平1,如果不明白可以忽略括号里面的内容),因此两根信号线之间共有4*4=16种表达方式。
我们需要的就是这16个不同的形式来规定IIC通信协议。

简单来说,一个通信协议,最基本也要包括以下几个基础的内容:
空闲状态
起始信号和停止信号
应答信号
数据的有效性(如何确保信号正确)
数据传输

我将以上这五种情况,列在了EXCEL表中,大致如下图所示:

1、空闲、起始、停止
信号表达形式

空闲: 当SCL和SDA均为高电平时候,表示为空闲。意义为:当前设备均为空闲状态,允许你开始传输数据,只有空闲时,起始信号才会被读取。
起始信号: SCL仍表达为高电平,突然,SDA变为0,产生了一个下降沿,此时就表示产生起始信号。意义为:主机要开始发送信息,所有从机做好准备(有些从机空闲时待机模式,所以来个起始信号提醒一下(暂且这么理解))。
停止信号: 数据传输结束,需要告诉从机,“要停止传输数据了”。这时,SCL设置为高电平、SDA设置为低电平,在SCL保持为高电平时间,SDA跳变为高,产生一个上升沿,此时就表示停止信号。意义为:信息传输结束,大家休息。
时序图如下:
起始停止信号
一旦起始信号产生,就进入了数据传输部分。数据传输时,数据传输和有效性如下图所示:
切记:数据传输过程是在起始信号后、停止信号前。因此,下表的电平信号需要在这二者中间才有效。
数据传输
这儿插入一句话:
数据传输的基本规则:
1、时钟线SCL不断产生高低电平,从而产生通信时钟
2、数据线负责传输数据(也就是传输不同的高低电平信号)
明显的,从机想要收到信号,第一、从机需要记录一个一个电平信号;第二、需要给SDA时间去变换电平信号去表达正确的需要传输的电平信号。

由上述基本规则可以得到几点简单的规定
1、规定好何时记录电平信号、何时允许SDA变换信号
2、记录电平信号时,SDA不允许变动(很好理解,SDA在记录时间变动,从机就无法明白数据是高还是低)

很好的,数据传输规矩按下文定义
1、数据传输需要在起始信号后、停止信号前
2、何时记录信号?:SCL为高时记录信号。何时变换信号?:SCL为低时,允许SDA变换信号
3、记录电平信号时,SDA不允许变动

时序图如下:
时序图

以上是IIC最基本的通信规则了,已经满足设备间的数据通信了。但是最基本的规则不足以支撑稳定的、有效的数据传输。

这时候添加一些规则让通信更加稳定有效:应答信号

IIC的应答信号:主机发送数据是以字节为单位发送的,也就8b。每当一个字节发送结束后,主机会释放控制权,让从机获得控制权,从机发送一个符号来表示应答ok。然后,从机释放控制权,主机继续发送下一字节的内容。

插入一句,什么叫控制权。IIC一共就两根线,SCL、SDA。其中从机是没有办法产生时钟信号的,因此控制权就只能通过SDA线交接。意思就是,谁使用SDA线传输数据,谁就有控制权。因此上面一句话,翻译过来就是:
每当一个字节发送结束后,主机会释放控制权(主机将SDA变为空闲,SDA设置为1就是空闲),让从机获得控制权(让从机可以在SDA线上输出电平),从机发送一个符号(发送一个低电平(因为主机释放后SDA是1,只能由从机变成0来表示从机收到信号))来表示应答ok。

基于以上的内容,我们就可以通过软件来进行模拟IIC通信。相对于硬件IIC,软件IIC有以下优缺点:
1、引脚自由,可以自由使用引脚
2、数据相对稳定(据说STM32硬件IIC有BUG,我也只是听说)
3、还是比硬件IIC吃一点资源,不过还好,不是很吃资源。

基于以上的规则,我们在软件层面来写软件IIC吧!!!

基本配置:
两根线的配置
SCL:推挽输出
SDA:推挽输出+上拉输入(毕竟是半双工,有输出也有输入)

一下这8个函数足够驱动IIC通信:
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号

函数内部具体如何实现的,下一节继续!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值