嵌入式Linux学习(1)——通信总线协议简介

目录

一. UART

1.1 单工/双工通信 ​编辑

1.2 UART帧格式

1.2.1 Q/A

1.3 UART硬件结构

二. 基于UART的协议

2.1 RS232

 2.1.1 RS232协议存在的问题

2.2 RS485

2.2.1 差分信号 

2.2.2 RS485优势

三. IIC

3.1 通信过程

3.2 IIC总线寻址

3.3 IIC总线信号 

3.3.1 起始与停止信号

3.3.2 同步信号

3.3.3 字节传送与应答/结束

3.4 IIC典型时序

3.5 主从机的选择

四. SPI

4.1 寻址方式

4.2 通信过程

4.2.1 极性和相位

4.3 IIC vs SPI

五. 小结


本篇简单介绍嵌入式里5种经典的通信总线协议:UART、RS232、RS485、I2C、SPI。

一. UART

嵌入式Linux学习(1)——通信总线协议简介_第1张图片

异步通信:意味着UART的通信双方没有统一的基准时钟。 

1.1 单工/双工通信 嵌入式Linux学习(1)——通信总线协议简介_第2张图片

1. 单工通信:只能是发送器向接收器发送数据,接收器是不能向发送器发送数据的。 

2. 双工通信:即可以是发送器向接收器发送数据,也可以是接收器向发送器发送数据,根据能否同时进行区分为全双工和半双工。一般来讲只有一根数据线连接的大多是半双工通信的。

(1) 半双工:同一时刻,只能是发送器向接收器发送数据,或者是接收器向发送器发数据

(2) 全双工:发送器向接收器发数据的同时,接收器也可以向发送器发送数据。

1.2 UART帧格式

嵌入式Linux学习(1)——通信总线协议简介_第3张图片

1. 空闲位

数据线在空闲的时候必须置为高电平。

2. 起始位

起始位必须是低电平。

因为空闲位一直是高电平,如果起始位也是高点平的话,那就无法区别当前是空闲状态还是要开始发送数据的状态了。

3. 数据位

数据可以是5~8位,一般都是8位。先发送最低位最后发送最高位。

4. 校验位

UART是使用奇偶校验。当接收方收到数据后“数一数”1的个数,再看下校验位的值就知道数据是否有出现错误。校验位为可选项。

嵌入式Linux学习(1)——通信总线协议简介_第4张图片

嵌入式Linux学习(1)——通信总线协议简介_第5张图片

5. 停止位

数据结束标志,可以是1位,1.5位,2位的高电平。

1.2.1 Q/A

1. Q:接收方是如何知道发送方发送的是0101还是00110011?

    A:通过波特率。单纯从信号变化上来看,0101和00110011看起来是一样在变,只是高低电平持续的时间不同,接收方与发送方保持相同的波特率即可区别是01还是0011。例如波特率为1,则表示每秒去采集一次数据。

嵌入式Linux学习(1)——通信总线协议简介_第6张图片

2. Q:为什么每发送一次数据都要经历一遍“开始位,校验位,停止位”这个过程?

A:因为因为收发双方是异步通信,意思就是双方没有一个基准时钟,各自维护自己的时钟,那么即使双方时钟误差极小,那么数据量一大(即一次发送的持续时长过长),数据量就错乱了,导致后续的全部数据都错乱,而发送少的数据位就经历一遍这个过程,就相当于重新开始计数,就可以减少这个误差带来的问题。

1.3 UART硬件结构

嵌入式Linux学习(1)——通信总线协议简介_第7张图片

嵌入式Linux学习(1)——通信总线协议简介_第8张图片

一般SoC内部都会集成有UART控制器,使用者使用UART通信时只需要配置UART操作的寄存器来控制"1.2  UART帧格式"中提到的流程,例如配置UART数据中是否有校验位,有几个数据位,波特率是怎样的即可。

二. 基于UART的协议

UART只规定了收发的时序,即“先发起始位,再发数据位,校验位,最后发停止位”;只规定了高低电平,但是并没有规定高电平指的是多少伏,低电平指的是多少伏。

在实际项目中,很少直接用UART串口通信的,因为会存在如下问题:

1. 电气接口不统一    

(1) UART只是对信号的时序进行了定义,而未定义接口的电气特性;        

(2) UART通信时一般直接使用处理器使用的电平,即TTL电平,但不同的处理器使用的电平存在差异, 所以不同的处理器使用UART通信时一般不能直接相连;

——例如国外的电器可能会因为电压不同而不能使用,虽然可能都是通过高电平上电运转的。    

(3) UART没有规定不同器件连接时连接器的标准,所以不同器件之间通过UART通信时连接很不方便;

——例如都没有按国标生产的插头和插板,可能插头A根本不能插入到插板B中,即使能插入也不知道插头A和插板B的哪个头是零线/火线/地线。

2. 抗干扰能力差    

UART一般直接使用TTL信号来表示0和1, 但TTL信号的抗干扰能力较差,数据在传输过程中很容易出错  。

3. 通信距离极短    

因为TTL信号的抗干扰能力较差,所以其通信距离也很短,一般只能用于一个电路板上的两个不芯片之间的通信

所以后面又引入了基于UART通信的RS232和RS485协议。

RS:RS即推荐标准。是由电子工业协会在 60 年代开发的,以促进调制解调器和计算机终端之间的通信

2.1 RS232

RS232协议是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家、计算机终端生产厂家共同制定的用于串行通讯的标准。   

该标准规定采用一个标准的连接器,标准中对连接器的每个引脚的作用加以规定,还对信号的电平加以规定。现在常用的遵循RS232协议的PC机连接器如下图所示,只有9根线,这是IBM简化后的连接器,但是真正使用的也只有3根(TXD/RXD/GND),起初规定的是25根线。

嵌入式Linux学习(1)——通信总线协议简介_第9张图片

RS232编程与普通的UART串口编程没有任何区别,可以理解为相对于UART只是在更底层的电气特性上增加了一个硬件模块而已。

1. 规定接口    

该标准规定采用一个25引脚的DB-25连接器,标准中对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定; 后来IBM的PC机将RS232简化成了DB-9连接器,后来成为事实标准; 现在工业控制的RS-232接口一般只使用RXD、TXD、GND三条线

2. 规定信号电平   

该标准规定逻辑“1”的电平为-5v到-15v,逻辑“0”的电平为+5v 到+15v。

虽然很多处理器中都会集成UART控制器,但处理器产生的信号一般都是TTL信号并不是符合RS232标准的信号,所以一般我们还需要在处理器外部去添加电路或者电平转换芯片(例如232芯片)对信号的电平进行转换。(如下图所示)

3. 增强抗干扰能力,增大通信距离

选用该电气标准的目的在于提高抗干扰能力,增大通信距离, 其传送距离一般可达15m。

嵌入式Linux学习(1)——通信总线协议简介_第10张图片

在RS232电平和TTL电平中间添加电平相互转换的232芯片 

 2.1.1 RS232协议存在的问题

1. 需要额外增加电平转换芯片

RS232接口的信号电平值较高,易损坏接口电路的芯片,又因为与TTL电平不兼容,所以需要使用电平转换芯片才能与TTL电路连接 。

2. 通信速度较低 ,易产生共模干扰,抗噪声干扰性弱  

3. 传输距离较短

最长只有15m。

 针对抗干扰和传输距离问题,后面又引入了RS485。

2.2 RS485

RS485标准由电信行业协会和电子工业联盟定义,使用该标准的通信网络能在远距离条件下以及电子噪声大的环境下有效传输信号; 该标准允许连接多个收发器,即具有多站能力,这样可以利用单一的RS485接口方便地建立起一个设备网络,RS232和UART是只能点对点传输的。

嵌入式Linux学习(1)——通信总线协议简介_第11张图片

从接线上来看是A对A,B对B,并不像UART和RS232那样TX对RX。 

嵌入式Linux学习(1)——通信总线协议简介_第12张图片

2.2.1 差分信号 

RS485能够有效地“减少噪声信号的干扰,延长通信距离”,最重要的就是它采取了差分信号进行数据传输。

RS485标准规定采用差分信号进行数据传输,两线间的电压差为+2v到+6v表示逻辑“1”,两线间的电压差为-2v到-6v表示逻辑“0”;

RS485的通信距离可以达到1500m;

RS485接口信号的电平比RS232降低了,所以不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便地与TTL电路连接。

差分的过程大概如下:利用差分信号进行数据传输的话是需要两根线的,以下图为例,接收方接收到红绿线的电平信号后进行相减,如果差值为“+2v~+6v”表示发送方发送的是“1”,差值为“-2v~-6v”表示发送方发送的是“0”。当产生干扰的时候,红绿线收到的干扰是一样的,两者互作参考得出来的相对差是没变的,所以最后得到的“0”和“1”也是没变的。

 嵌入式Linux学习(1)——通信总线协议简介_第13张图片

RS485一般是采用两线制,多采用屏蔽双绞线传输,在同一总线上可以同时存在多个节点,这种接线方式为总线式拓扑结构,在同一总线上最多可以挂接32个结点。(RS422是使用4线制的,可以全双工)。

嵌入式Linux学习(1)——通信总线协议简介_第14张图片

UART是全双工的,RS485虽说是基于UART的,但是因为采用两线制,即数据的发送和接收都要使用这对差分信号线,发送和接收不能同时进行,所以RS485是半双工的工作方式。RS485编程时也需要加以处理,比如收发不能同时进行,主从通信等。

一般处理器产生的都是TTL信号,因此和RS232一样,RS485和处理器间也需要电平转换芯片(例如MAX485),将TTL信号转为RS485的差分信号。

2.2.2 RS485优势

1. 电平信号

接口的信号电平值较低,不易损坏接口电路的芯片,且与TTL电平兼容,可方便地与TTL电路连接

2. 通信

通信速度快,可达10Mbps;抗噪声干扰性强;传输距离较远,可达1200m左右。

3. 可实现多节点组网

三. IIC

嵌入式Linux学习(1)——通信总线协议简介_第15张图片

嵌入式Linux学习(1)——通信总线协议简介_第16张图片

1. IIC总线是一种多主机总线,连接在IIC总线上的器件分为主机和从机,同一时刻只能有一个主机,当总线上有多个主机同时启用总线时,IIC也具备冲突检测和仲裁的功能来防止错误产生;

2. 主机有权发起和结束一次通信,而从机只能被主机呼叫;

3. 每个连接到IIC总线上的器件都有一个唯一的地址(7bit),且每个器件(例如下图中的单片机A,单片机B,日历时钟等)都可以作为主机也可以作为从机,总线上的器件增加和删除不影响其他器件正常工作;

4. IIC总线在通信时总线上发送数据的器件为发送器,接收数据的器件为接收器

嵌入式Linux学习(1)——通信总线协议简介_第17张图片

3.1 通信过程

1. 主机发送起始信号启用总线;  

2. 主机发送一个字节数据指明从机地址和后续字节的传送方向;

   高7位用来指明主机想要通信的从机地址,最低位用来指明方向,看是主机给从机发数据还是从机给主机发送数据。 

3. 被寻址的从机发送应答信号回应主机;

  

4. 发送器发送一个字节数据;  

   发送器可以是主机,也可以是从机,由步骤2中的传送方向字段决定。

5. 接收器发送应答信号回应发送器  … … (循环步骤4、5);  

n. 通信完成后主机发送停止信号释放总线。

与UART不同,IIC一次通信是可以发送多个字节的,但是不能改变通信方向。

如果要改变通信方向,可以重新来一次“起始->...->停止...起始->...->停止”或者是“起始->...->起始->...停止”

3.2 IIC总线寻址

1. IIC总线上传送的数据是广义的,既包括地址,又包括真正的数据 ;

2. 主机在发送起始信号后必须先发送一个字节的数据,该数据的高7位为从机地址,最低位表示后续字节的传送方向,'0'表示主机发送数据,'1'表示主机接收数据;

3. 总线上所有的从机接收到该字节数据后都将这7位地址与自己的地址进行比较,如果相同,则认为自己被主机寻址,然后再根据第8位将自己定为发送器或接收器

3.3 IIC总线信号 

从上述的IIC通信过程可知,需要关注起始与停止信号/发送与应答。

3.3.1 起始与停止信号

嵌入式Linux学习(1)——通信总线协议简介_第18张图片

1. 空闲

空闲状态下,SCL和SDA都是高电平。

2. 起始信号

SCL为高电平时,SDA由高变低表示起始信号。

3. 终止信号

SCL为高电平时,SDA由低变高表示停止信号。

起始信号和停止信号都是由主机发出,起始信号产生后总线处于占用状态,在停止信号产生前,其他设备都是不能用的。停止信号产生后总线处于空闲状态。

3.3.2 同步信号

嵌入式Linux学习(1)——通信总线协议简介_第19张图片

1. 发送器发送数据

当时钟线SCL为低电平时,发送器向数据线上发送一位数据,在此期间数据线上的信号允许发生变化。例如发送器要发送0,就在SCL为低电平期间将SDA的变为低电平。

2. 接收器接收数据

当时钟线SCL为高电平时,接收器从数据线上读取一位数据,在此期间数据线上的信号不允许发生变化,必须保持稳定。

3. 发送器和接收器都接在同一个SCL总线上,即共用SCL

发送器是一位一位的写,接收器是一位一位的读,因此IIC读写一次(一个字节)得循环8次。

3.3.3 字节传送与应答/结束

嵌入式Linux学习(1)——通信总线协议简介_第20张图片

上图是“以主机为发送器,从机为接收器”为例的时序图。

1. 发送器发送数据

与UART不同,IIC每次发送的数据必须是8位,数据传送时,先传送最高位,后传送低位,而且只能是在SCL处于低电平的时候发送数据。

2. 接收器应答

发送器发送完一个字节数据后,SCL会再次变为高电平,这时候接收器可以选择发送1位应答来回应发送器,当然接收器也可以选择不应答。

接收器使用低电平表示应答,如果持续使用高电平则表示不应答。

3. 一个字节的数据发送完成

接收器可以选择不应答或者是发送器发送停止信号来表示一个字节的数据已经发送完成。

收发器的读写是1位1位的,根据SCL写1位读1位,等读写到8位的时候就表示一轮读写结束了,在信号上需要通过 应答/不应答、停止信号来告知。

由上述时序可知一次收发共有9个SCL的高电平。

3.4 IIC典型时序

上一小节站在发送器和接收器的角度介绍了收发信号时序,这一小节站在主从机的角度来看下IIC的收发信号时序。

后面三张图中的SCL一直在工作,只是没有画出来。 

阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送;A表示应答, \overline{A}表示非应答,S表示起始信号,P表示终止信号。

1. 主机向从机发送数据

 (1) 主机发送起始信号S;

 (2) 主机发送第一个字节的数据用来寻址,0表示是主机发送数据;

 (3) 匹配到地址的从机会进行响应A;

 (4)  主机继续一个字节一轮地循环发送数据;

 (5) 从机可以通过应答A来表示这一个字节已经读完,也可以不应答直到SCL的时序变化,既然从机都不应答了主机也不会再发送数据了;;

 (6) 主机发送停止信号P。

2. 从机向主机发送数据

嵌入式Linux学习(1)——通信总线协议简介_第21张图片

 (1) 主机发送起始信号S;

 (2) 主机发送第一个字节的数据用来寻址,1表示是从机发送数据;

 (3) 匹配到地址的从机会进行响应A;

 (4)  从机继续一个字节一轮地循环发送数据;

 (5) 主机可以通过应答A来表示这一个字节已经读完,也可以不应答直到SCL的时序变化,既然主机都不应答了从机也不会再发送数据了;

 (6) 主机发送停止信号P。

3 主机先向从机发送数据,然后从机再向主机发送数据

 (1) 主机发送起始信号S;

 (2) 主机发送第一个字节的数据用来寻址,0表示是主机发送数据;

 (3) 匹配到地址的从机会进行响应A;

 (4)  从机继续一个字节一轮地循环发送数据;

 (5) 主机可以通过应答A来表示这一个字节已经读完,也可以不应答直到SCL的时序变化,既然主机都不应答了从机也不会再发送数据了;

 (6) 主机不发送停止信号P,而是直接发送起始信号S,然后直接开始寻址以及后来的操作。

3.5 主从机的选择

(TODO) 在代码编程阶段介绍。

四. SPI

嵌入式Linux学习(1)——通信总线协议简介_第22张图片

1. SPI是串行通信的,因此会考虑先发高位还是先发低位的问题,SPI是“先发高位,后发低位”。

2. SPI至少有如下4根线:

(1) MOSI和MISO这两根数据线,保证SPI是全双工的。

(2) SCLK时钟线保证同步。

(3) CS片选线来寻址,保证Master和哪个Slave通信。Master根据接的Slave可能有多根CS片选线,而Slave一般只有1个CS线。

4.1 寻址方式

嵌入式Linux学习(1)——通信总线协议简介_第23张图片

主设备要和某个从设备进行通信时主设备需要先向对应从设备的片选线上发送使能信号来表示选中该从设备,至于是高电平还是低电平表示使能是根据从机而定的。

4.2 通信过程

嵌入式Linux学习(1)——通信总线协议简介_第24张图片

1. SPI进行数据传输是没有起始信号和结束信号的,接收器也不需要应答(所以发送器也无法保证对方是否有收到);

2. SPI总线在进行数据传送时,先传送高位,后传送低位。数据线为高电平表示逻辑‘1’,低电平表示逻辑‘0’;一个字节传送完成后无需应答即可开始下一个字节的传送;

3. SPI总线采用同步方式工作,在一个时钟周期的上升沿下降沿时发送器向数据线上发送数据,在紧接着的下降沿或上升沿时接收器从数据线上读取数据,完成一位数据传送,八个时钟周期即可完成一个字节数据的传送

4.2.1 极性和相位

1. 极性(CPOL,Clock Polarity)用来表示SCLK空闲时的状态,通俗点理解:   

    (1) CPOL=0:SCLK为低电平表示空闲     

    (2) CPOL=1:SCLK为高电平表示空闲    

2. 相位(CPHA,Clock Phase)用来表示采样时刻:

    (1) CPHA=0:表示在每个周期的第一个时钟沿采样

    (2) CPHA=1:表示在每个周期的第二个时钟沿采样

由于数据必须是先发送和读取,采样即读取。

极性(CPOL)和相位(CPHA)两两组合,则SPI总线有四种不同的工作模式。

1. CPOL = 0,  CPHA = 0

CPOL = 0 说明低电平表示SCLK空闲,CPHA = 0 说明数据采样是在第1个边沿,SCLK要产生边沿则需要由低电平跳变为高电平。
设SCLK在进入非空闲状态就直接拉高,则一开始就是直接产生了第1个边沿,也就是这时候要开始采集数据了,可是这时候是没有谁去写数据的,由数据必须先写后读可知,这种假设是不合理的。

嵌入式Linux学习(1)——通信总线协议简介_第25张图片

因此由此推理可知,SCLK在进入非空闲状态的时候是先持续低电平的,在这个低电平阶段先发数据,然后等到变平产生时钟沿的时候再采集数据。即数据的采样是在上升沿,数据发送是在下降沿

嵌入式Linux学习(1)——通信总线协议简介_第26张图片

含义:低电平表示SCLK空闲,在一个时钟周期的下降沿的时候发送1位数据,在同一个时钟周期的上升沿的时候读取1位数据。

 2. CPOL = 0,  CPHA = 1

含义:低电平表示SCLK空闲,在一个时钟周期的上升沿的时候发送1位数据,在同一个时钟周期的下降沿的时候读取1位数据。

CPOL=0 空闲时SCLK处于低电平;CPHA=1 数据的采集在第二个时钟沿,所以数据的发送在第一个时钟沿。由于SCLK开始时是低电平,因此直接变到高电平即可产生时钟沿,进而可知数据发送是在上升沿,数据采样是在下降沿。

嵌入式Linux学习(1)——通信总线协议简介_第27张图片

3. CPOL = 1,  CPHA = 0

含义:高电平表示SCLK空闲,在一个时钟周期的上升沿的时候发送1位数据,在同一个时钟周期的下降沿的时候读取1位数据。

嵌入式Linux学习(1)——通信总线协议简介_第28张图片

CPOL = 1 说明高电平表示SCLK空闲,CPHA = 0 说明数据采样是在第1个边沿,SCLK要产生边沿则需要由高电平跳变为低电平。
同“CPOL = 0,  CPHA = 0”来作假设理解:假设SCLK在进入非空闲状态就直接变低电平,则一开始就是直接产生了第1个边沿,也就是这时候要开始采集数据了,可是这时候是没有谁去写数据的,由数据必须先写后读可知,这种假设是不合理的。因此由此推理可知,SCLK在进入非空闲状态的时候是先持续高电平的,在这个高电平阶段先发数据,然后等到变平产生时钟沿的时候再采集数据。即如上图所示,数据的采样是在下降沿,数据发送是在上升沿

4. CPOL=1,CPHA=1

含义:高电平表示SCLK空闲,在一个时钟周期的下降沿的时候发送1位数据,在同一个时钟周期的上升沿的时候读取1位数据。

嵌入式Linux学习(1)——通信总线协议简介_第29张图片

CPOL = 1 说明高电平表示SCLK空闲,CPHA = 1 说明数据采样是在第2个边沿,SCLK要产生边沿则需要由高电平跳变为低电平。SCLK在进入非空闲状态就直接变低电平,则一开始就是直接产生了第1个边沿,这个时候就可以写数据了,等到再将电平由低电平拉高则可以产生第2个边沿来采集数据。即如上图所示,数据的发送是在下降沿,数据采集是在上升沿

极性和相位 含义
CPOL=0,CPHA=0

低电平表示SCLK空闲,在一个时钟周期的下降沿的时候发送1位数据,在同一个时钟周期的上升沿的时候采集1位数据。

CPOL=0,CPHA=1

低电平表示SCLK空闲,在一个时钟周期的上升沿的时候发送1位数据,在同一个时钟周期的下降沿的时候采集1位数据。

CPOL=1,CPHA=0

高电平表示SCLK空闲,在一个时钟周期的上升沿的时候发送1位数据,在同一个时钟周期的下降沿的时候采集1位数据。

CPOL=1,CPHA=1 高电平表示SCLK空闲,在一个时钟周期的下降沿的时候发送1位数据,在同一个时钟周期的上升沿的时候采集1位数据。
主机的极性和相位 一般根据从设备来配置的

4.3 IIC vs SPI

 相同点    

1.均采用串行、同步的方式    

2.均采用TTL电平,传输距离和应用场景类似    

3.均采用主从方式工作  

不同点    

1.IIC为半双工,SPI为全双工    

2.IIC有应答机制,SPI无应答机制    

3.IIC通过向总线广播从机地址来寻址,SPI通过向对应从机发送使能信号来寻址    

4.IIC的时钟极性和时钟相位固定,SPI的时钟极性和时钟相位可调

五. 小结

上述几种总线通信基本都是在解决如下几个问题:

1. 什么时候发送什么时候接收?

2. 先发高位还是先发低位? 

3. 处理发出的是TTL信号,如何知道一个电平信号代表多少个1和0?

可以围绕上述3个问题完善下表。

UART RS232 RS485 IIC SPI
接线方式

串行/并行

串行:先发送低位,再发送高位 串行先发送高位,再发送低位
发送数据的位数 5~8位 只能是8位
数据线根数 2根 1根
双工方式 全双工 半双工

你可能感兴趣的:(嵌入式Linux,嵌入式,通信总线)