嵌入式总线与通信

本文详细介绍了I2C通信协议的特性、工作原理、硬件连接方式以及如何在一条数据线上实现双向传输。内容包括I2C的起始和停止信号、地址传输、数据传输格式等,并探讨了I2C总线死锁的原因及解决方法。此外,还简述了SPI通信协议,强调其数据读取时机和开始、结束信号。
摘要由CSDN通过智能技术生成

I2C通信

I2C通信的特点

I2C是一种通信协议(规定传输格式),也是一种通信接口(SOC中规范的电路),也是一种总线(指传输所用的信号线)。
I2C通信是串行(一位一位传输数据)、同步的(除数据线外还需要时钟信号)、半双工(某一时刻只能一个发一个收,不能同时收发)
I2C通信支持多主机,某一时刻发起数据传输的机器就是主机,多个主机同时发起传输时,有总线仲裁机制(总线仲裁具体看嵌入式三级书138)。
I2C总线最长约7.5m,传输速率有100kb/s、400kb/s、高速模式可达3.4Mb/s,用于板级芯片直接的短距离低速通信。

I2C通信协议

一个通俗例子:老师和学生传球
操场上,一个老师(主机,I2C某一时刻只能有一个主机),多个学生(从机),老师将球(数据)传给学生或从学生那里要球需要进行以下操作:
1、大喊一声“球”,使得所有有接老师球或者传球给老师的准备(老师:球!)
2、老师叫某个同学的名字,表示将与这个同学进行传球或者接球(老师:张三!)
3、老师告诉该同学是传球还是接球(老师:接球!或传球!)
4、该同学回答老师,表示自己能否接球或者传球(张三:好!或者不好!)
5、老师传球或者接球,老师传给学生,学生接到球后回应老师,学生传给老师,老师接球后回应学生
6、老师说干得漂亮!(表示此次互动结束)
上述例子就是I2C协议传输一个数据帧的过程,具体为:
1、主机发出start信号,表示开始本次传输
2、主机发出从机设备地址信号,表示对某一个从机进行操作
3、主机发出信号,表示数据传输的方向,是主到从还是从到主
4、从机发出应答信号,表示自己准备好接收或者发出数据
5、数据传输,主机发给从机,则从机回应,从机发给主机,则主机回应,这个回应信号就是这个数据帧的结束位
6、主机发出结束信号,结束本次数据的传输(注意,不是每个数据帧的结束,是这次数据传输整体的结束)

用框图表示主机和从机的读写过程如下,上面是主机写从机,下面是主机读从机,黑色是主机发的数据,红色是从机发的数据:
在这里插入图片描述
I2C通信一般两条信号线,一条SDA用于传输数据,一条SCL用于传输时钟信号,下面结合这两条线具体说明上图的数据格式:
START信号:SCL保持高电平,SDA由高变低
设备地址:7位,和方向位合在一起,行成一个8位数据帧,先传最高位(MSB)。主机发出START信号后,每一个时钟周期发送一个二进制位,第八个时钟周期时设备地址和方向位都发送完毕。在第九个时钟主机等待从设备发出的回应信号。每一位数据在SCL的低电平期间可以发生变化,在SCL的高电平期间必须保持稳定。
方向位:1位
回应:1位,低电平有效
数据:8位
STOP信号:SCL保持高电平,SDA由低变高

总的来说,I2C一个数据帧一般是九个时钟周期,前八个时钟周期用于传输数据,第九个时钟周期是回应。

下图是S3C2440A手册上的I2C时序图:
在这里插入图片描述

I2C硬件连接

I2C在一条数据线SDA上如何实现双向传输?(如何实现半双工)

从上面的分析可知,在读或者写中,一次数据传输需要双方互相发信号,要么数据要么回应,I2C如何通过SDA一条线实现双方的数据发送的呢?一根数据线,一般是单工或者半双工,这里相当于问的是如何实现半双工。

要完成半双工,需要满足以下几点:
1、设备A发送数据时,设备B不应该发送数据
2、设备A发送数据时,设备B阴极的电平变化不应该影响SDA线上的数据电平

第一点可以通过时钟信号来控制,因为I2C的发送都是卡死了的,比如START信号过后,就是该主机发送8个时钟,这8时钟内从机就不发数据。
第二点可以通过上拉电阻和三极管来控制,三极管使用开漏集电路,作为输出,具体电路见下图:
I2C接口的开漏电路
发送端如果输出高电压(逻辑1),经过非门之后会变成低电压,低电压不会驱动三极管,三极管呈高阻态,由于上拉电阻的存在,SDA上是高电压(逻辑1)。发送端如果输出低电压(逻辑0),经过非门之后会变成高电压,高电压打通三极管,SDA接地,呈现逻辑0。
我们假设设备A和设备B发送端同时施加电压,列出一个设备A发送端、设备B发送端以及SDA电压的真值表。
在这里插入图片描述
若AB都为0,非门后,都会打通三极管,SDA接地,为0
若A为0,B为1,非门后,A打通三极管,SDA接地,为0
若A为1,B为0,非门后,B打通三极管,SDA接地,为0
若A为1,B为1,非门后,都不打通三极管,SDA为1
从上面的分析可知,如果某一设备不想影响SDA上面的电平,则不驱动三极管就行。当设备A作为主设备发数据时,它负载给SDA传输数据,这个时候设备B的发送端就不要驱动三极管,也就是输出0,这样设备B那边的发送端就会是高阻态,这样设备B发送端上面的电气波动就不会影响SDA上的数据。那么SDA上的数据全部由设备A控制。

SCL的处理: 上面的三极管和上拉电阻连接图是SDA的,SCL和SDA的连接类似,也是要加三极管和上拉电阻。SCL加三极管和上拉电阻的作用在于暂时停止传输(中场休息,或者拥有单独处理每个数据帧的能力)。前面我们说了,I2C每个数据帧是九个位,也就是九个时钟周期,SCL上传输的是时钟信号,该信号由主设备发出,也就是说在平常时候是全部由主设备来驱动SCL的(主设备三极管打通,从设备三极管关闭),在某个数据帧结束后,如果主或者从设备觉得传输过快,处理不过来,可以通过一直驱动三极管(也就是一直将自身SCL的发送端置1),注意前面的真值表,只要有某一个设备的发送端一直是1,SCL上的电压会一直是0,I2C通信协议约定当SCL时低电平时暂停数据传输(因为每一位数据都是在SCL高电平时才保持稳定)。

上面对于SCL的说法可能有点问题,下面是《嵌入式系统开发技术》138的解释:
在这里插入图片描述

SOC上的I2C通用硬件接口

根据上述知识,我们最简只需要两个引脚加一些三极管、上拉电阻和时钟电路就可以自己模拟I2C的通信,但是这样的模拟需要手动编写代码去解析I2C数据帧,很麻烦。一般的SOC,比如S3C2440A,都有集成专门的I2C接口(或者叫I2C控制器)。
I2C接口主要完成以下功能:
1、配置I2C传输速率。方法为将SOC传过来的时钟(PCLK)进行分频(开发者设置I2C分频寄存器)
2、地址译码。I2C接口内有好几个寄存器,不同的寄存器一般称为**“端口”**,比如I2C数据寄存器就是数据端口,I2C控制寄存器就是控制端口,这些寄存器有不同的地址,我们要想对这些寄存器进行操作,就必须有地址译码,通过硬件通过译码器选中某个具体的寄存器。
3、串并/并串数据的转换。ARM的SOC内部一般通过外围总线APB传输数据到I2C接口,I2C接口需要将内部传来的并行数据转换成串行数据发送到从设备,也需要将来自从设备的串行数据转换成并行数据发送给APB总线。
4、触发中断。CPU一般通过IRQ中断接收I2C通信的数据,I2C接口有状态寄存器,根据通信状态触发中断。
5、总线仲裁,前面说过I2C支持多主结构,当多个主设备冲突时,需要仲裁机制。
一个传统的I2C接口原理框图如下所示:
在这里插入图片描述

I2C接口与接口之间的连接

下图是各个I2C设备之间的连接示意图,是SOC与SOC,SOC与具有I2C接口的设备之间的连接:
在这里插入图片描述
下图是SOC和具体某个设备之间的连接,具体是S3C2440和铁电存储器芯片FM24CL64之间的连接:
在这里插入图片描述

I2C设备在整个ARM体系中的位置

上面我们说了I2C接口在ARM SOC中的位置和具体布局,说了不同接口之间如何通过I2C总线(SDA加SCL)进行互联,现在我们说一下I2C接口在整个ARM SOC中的位置,如下图所示:
在这里插入图片描述

I2C的死锁和总线仲裁

I2C总线仲裁

嵌入式三级书P138

I2C总线死锁

I2C死锁时表现为SCL为高,SDA一直为低。
主设备复位导致的I2C死锁过程:

在I2C主设备进行读写操作的过程中,主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。

从设备:正常时序下:SDA信号是在SCL为低的状态下改变,即从应答SDA为低电平时,此时SCL应为为低电平(即从设备是先拉低SDA信号,等待主设备SCL由高变低,“取走”ACK信号后,从再释放SDA为高)。但如果此时时序被打乱,例如单片机I2C通信时突然复位,SCL突然变高,则从设备SDA一直为低,等待SCL变低。
主:SDA被从拉低,故主认为I2C总线占用,一直等待SDA变高。

I2C死锁解决方法
尽量选用带复位输人的I2C从器件。
将所有的从I2C设备的电源连接在一起,通过MOS管连接到主电源,而MOS管的导通关断由I2C主设备来实现。
在I2C从设备设计看门狗的功能。
在I2C主设备中增加I2C总线恢复程序。每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。这种方法有很大的局限性,因为大部分主设备的I2C模块由内置的硬件电路来实现,软件并不能够直接控制SCL信号模拟产生需要时钟脉冲。
在I2C总线上增加一个额外的总线恢复设备。这个设备监视I2C总线。当设备检测到SDA信号被拉低超过指定时间时,就在SCL总线上产生9个时钟脉冲,使I2C从设备完成读操作,从死锁状态上恢复出来。总线恢复设备需要有具有编程功能,一般可以用单片机或CPLD实现这一功能。
在I2C上串入一个具有死锁恢复的I2C缓冲器,当缓冲器检测到输出侧SDA或SCL信号被拉低30ms时,就自动断开I2C总线输人侧与输出 侧 的连接。并且在输出侧SCL信号上产生16个时钟脉冲来释放总线。
另外,对于有些不标准的I2C设备,只要总线上发送从机地址就会有响应。这样由于从机的错误响应,使得各个I2C总线异常,甚至钳住总线,导致 I2C 总线进人一种死锁状态。对于这样的不标准I2C设备,单独使用一个总线,避免干扰,或者单独一个独立引脚,控制电源。

对于I2C要求不高的设备最好用模拟I2C实现,控制灵活,则不会死锁!
————————————————
版权声明:本文为CSDN博主「Frey_Liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/helaisun/article/details/107745934

SPI通信

数据读取时机:时钟信号的上升沿或者下降沿采样数据,上升还是下降可人为配置。SPI mode,四种,模式0和3是上升沿采数据。选择是上升还是下降,取决于SOC上外接的SPI设备是上升还是下降。
开始信号:片选信号从高变低,表示开始传输,整个读写过程中,片选信号要保持低电平
结束信号:片选信号从低变高,传输结束

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值