温故知新(十)——UART


1 通信方式

一般而言,CPU与外部通信有两种通信方式:串行通信和并行通信。根据串行数据的时钟控制方式不同,串行通信可以分为:异步通信和同步通信。

1.1 串行通信

1.1.1 异步通信的特点

所谓异步通信,是指数据传送以单个字符(每帧信息)为一个单位,字符与字符间的传输是完全异步的(即不知道字符之间空了多少),而位与位之间的传输是同步的。

  1. 以字符为单位传送信息;
  2. 相邻两字符间的间隔是任意长;
  3. 单个字符中的比特位长度有限,所以需要的接收时钟和发送时钟只要相近就可以,虽然不需要同步时钟线,但是需要规定相同的传输速率,以及空闲位、起始位、校验位、结束位等
  4. 异步通信简明扼要的特点即:字符间异步,字符内部各位同步。

1.1.2 异步通信的数据格式

每个字符(每帧信息)由4个部分组成:

  1. 1位起始位,规定为低电平;
  2. 5~8位数据位,即要传送的有效信息;
  3. 1位奇偶校验位;
  4. 1~2位停止位,规定为高电平。

奇偶校验位有两种类型:偶校验位与奇校验位。如果一帧信息中的数据 1 的个数是奇数,那么偶校验位就置为 1,从而使得总的 1的个数是偶数,反之偶校验位置0;同样道理,如果一帧信息中的数据 1 的个数是偶数,那么奇校验位就置为 1,从而使得总的 1的个数是奇数,反之奇校验位置0。奇偶校验实际上是循环冗余校验的一个特例,通过多项式x+1得到1位CRC。

1.1.3 同步通信的特点

所谓同步通信,是指数据传送是以数据块(信息帧)为单位,字符与字符之间、字符内部的位与位之间都同步。

  1. 以数据块为单位传送信息;
  2. 在一个数据块(信息帧)内,字符与字符间无间隔;
  3. 因为一次传输的数据块中包含的数据较多,所以接收时钟与发送时钟需要严格同步,通常要有同步时钟。

1.1.4 同步通信的数据格式

同步串行通信的每个数据块(信息帧)由3个部分组成:

  1. 2个同步字符作为一个数据块的起始标志;
  2. n个连续数据;
  3. 2个字节循环冗余校验码(CRC);

循环冗余校验码(Cyclic Redundancy Check,CRC)是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。其基本原理:任意一个由二进制数据串都可以用对应长度的多项式组成。例如:“1010111”可以表示成多项式x6+x4+x2+x+1。
具体见3.2节分析。

1.2 并行通信

并行通信(Parallel communication)就是指数据的每一位同时在多根数据线上发送或者接收。可以以字或字节为单位并行进行。并行通信速度快,但用的通信线多、成本高,故不宜进行远距离通信。计算机或PLC各种内部总线往往是以并行方式传送数据的。


2 UART

UART(Universal Asynchronous Receiver/Transmitter),意为通用异步收发传输器,该总线双向通信,可以实现全双工传输和接收。UART包含TTL电平的串口和RS-232电平的串口,使用UART通信的双方设备都需要遵从UART协议。

UART是一种串行通信,属于异步通信,其不需要同步时钟,通信的接收端和发送端均采用通信两端约定传输速率(诸如9600bps,115200bps),而非时钟触发。例如数据传送速率为120位/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。

在嵌入式设计中,UART通常用于主机和嵌入式设备进行通信,一般可以独立成芯片,也可以内置到其他芯片或设备中。其中USART与UART非常相似,只不过前者可以同步通信,而后者只能异步通信。而UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位逐个传输。在UART通信协议中信号线上的状态定义为:高电平时代表‘1’,低电平时代表‘0’。

UART的数据传输格式

其中各位的意义如下:
空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。
起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。
数据位:起始位之后就是所要传输的数据,数据位构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位LSB,最后发送最高位MSB,低电平表示‘0’,高电平表示‘1’完成数据位的传输。
奇偶校验位:前面已经聊过,此处不再赘述。
停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备之间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟的机会。停止位个数越多,数据传输越稳定,但是数据传输速度也随之变慢。

对于常见的串口波特率为9600bps,1bit传输时间大约为104us,假设传送一个数据实际是10个比特(开始位-8个数据位-停止位),传输一个字节数据需要传输10bit,因此此时一个字节的传输速率为960bit/s。

优缺点
1)优点
只使用两条信号线;
不需要时钟信号;
有校验位进行错误检测;
2)缺点
传输速率比较低。

2.1 TTL电平

TTL是Transistor-Transistor Logic的简写,是一种电平逻辑,晶体管-晶体管逻辑。通常我们采用二进制来表示数据,为了表示二进制,需要用高低电平表示这些二进制数,3.3V/5V等价于逻辑“1”,0V等价于逻辑“0”。UART特指单片机的UART端口,使用的就是TTL电平。嵌入式里面说的串口,一般是指UART口,而TTL、RS-232、RS-485是指电平标准(电信号)。

2.1.1 标准TTL电平逻辑

输出电路:电压大于等于(≥)2.4V为逻辑1;电压小于等于(≤)0.8V为逻辑0;
输入电路:电压大于等于(≥)2.0V为逻辑1;电压小于等于(≤)1.2V为逻辑0;

2.1.2 CMOS电平

输出电路:电压大于等于(≥)0.9×Vcc为逻辑1;电压小于等于(≤)0.1×Vcc为逻辑0;
输入电路:电压大于等于(≥)0.7×Vcc为逻辑1;电压小于等于(≤)0.3×Vcc为逻辑0;

CMOS门电路由PMOS场效应管和NMOS场效应管以对称互补的形式组成。常用于大规模集成芯片设计。CMOS可以用来构成各种逻辑门电路,例如下图的CMOS非门电路:

当A端为高电平时,VT1 PMOS管截止,VT2 NMOS管导通,Y端输出为低电平,也即A=1,Y=0;
当A端为低电平时,VT2 NMOS管截止,VT1 PMOS管导通,Y端输出为高电平,也即A=0,Y=1。
CMOS非门的输出端与输出端之间电平总是相反,实际上,不管输入端为高电平还是低电平,VT1和VT2始终有一个处于截止状态,电源与地之间基本无电流通过,因此CMOS非门电路的功耗很低。

2.2 RS-232电平

RS-232接口符合美国电子工业联盟(EIA)制定的串行数据通信的接口标准,全双工。其中 RS 为英文 “Recomend Standard” 的缩写,中文翻译为“推荐标准”,232为标识号。原始编号全称是EIA-RS-232(简称232,RS232)。它被广泛用于计算机串行接口外设连接,连接电缆和机械、电气特性、信号功能及传送过程,其输出的电平称为 RS232 电平。

2.2.1 RS-232电平逻辑

RS-232不同于TTL的电平逻辑,为负逻辑,最简单的RS232通信由三条数据线组成,即 TxD、RxD 和GND。负12V代表高电平,即-15V ~ -3V为逻辑1,正12V代表低电平,即+3V ~ +15V为逻辑0,电压也有标准范围。这里的电平,是TXD线(或者RXD线)相对于 GND 的电压。

通过不同的电平转换器可以实现不同电平逻辑的转换。

2.3 RS-485

RS-485与RS-232一样都是串行通信标准,标准名称是TIA/EIA-485-A,属于半双工通信。该传输方式能在远距离条件以及大噪声的环境下实现可靠信号传输。这主要由于其为差分信号传输,因此也导致了两根线的RS485属于半双工传输,也不需要地线。其两根传输线一般定义为A和B,作为一对双绞线。

2.3.1 RS-485电平逻辑

逻辑“1”以两线间的电压差为+(2 ~ 6)V表示;
逻辑“0”以两线间的电压差为-(2 ~ 6)V表示
MCU由于电平限制,一般需要外接收发器(常见MAX485)实现485的电平逻辑。

一般而言,使用双绞线作为RS-485的连接线,双绞线差分特征阻抗(对于线缆可以理解为连续稳定传输状态时的瞬态阻抗)选用120Ω,假定信号从左往右传输时,阻抗都是连续的,但是当进入最后一个接收电路时,电缆阻抗变得很小甚至没有,这就导致阻抗不连续,会产生阻抗突变,信号的一部分能量就会按照原路径返回,如返回回去的信号由于容抗及感抗,就会产生相差(信号会在阻抗不连续的结点上产生反射)。反射回去的信号与原信号叠加在一起。这样就会造成通信发生错误,严重的时候,通信就无法正确进行。因此,RS-485应在总线电缆的开始和末端都需并接终接电阻,常选用120Ω(具体使用时,需要测双绞线特征阻抗,一般在100~140欧姆)。

在部分噪声严重的场合可以选择下图右边的处理方案,利用两个60Ω电阻以及220pF电容形成低通滤波器,将增加线路的抗噪声能力。

RS-485在多点网络拓扑结构下,可最大驱动32个站点,这一指标与MAX485自动收发器有关。
根据MAX485的手册来看,每个接收电路输入阻抗并非理想的高阻态,而是12kΩ(RS-485单位负载,EIA-485标准定义的)。
当最大连接32个设备时(包括发送站点的接收电路阻抗),所以在不考虑其他线路阻抗的情况下,对于发送电路而言相当于接了一个等效阻抗:RL=(12000Ω/32)||(120/2)≈51.7欧姆。而根据现有的485驱动器而言,其负载能力可以达到27Ω(Max485),光看这个数值是可以实现更大(>32)的节点数的。当然,这往往需要综合考虑最小驱动能力、电流等问题。通过提高接收电路的单位负载(unit load)可以提高总线节点个数的。例如1/4 unit load的芯片(接收器输入阻抗为48k欧姆)可以带128个节点。

2.3.2 RS-422

RS-422作为全双工收发接口,信号采用差分电平编码,需要两对双绞线现场布线,抗干扰性能也不错。与RS-485相比,其优势在于可以实现全双工,通信的效率更高,但在现场布线时需要两对双绞线,增加了一定的成本。
RS-422与RS-485一样,其最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s。(受收发器限制)

3 Modbus协议

对于传输一个字节(8位数据)时,使用串行通信不会有太大问题,但是一旦涉及到大数据量,远距离传输,就不易确定数据的起始以及数据的传输准确性。因此例如RS-485作为常用的传输协议,在传输大量数据时,常在有用数据前加上多个帧头,数据后加上帧尾,最后还要加上一个字(两个字节)校验码。
Modbus协议是一种总线协议,常用在工业上的简单协议,通讯物理接口可以选用串口(包括RS232和RS485),也可以选择以太网口。。
Modbus常可以分为以下几种:

  • Modbus-RTU
  • Modbus-ASCII
  • Modbus-TCP

以上三种中,个人接触最多的就是Modbus-RTU协议。
Modbus是一种主从式通信,总线上每次只有一个数据进行传输,即主机发送,从机应答。所以是可以一(主机)对多(从机),因此需要对从机进行地址分配,用来区别不同的从机。

3.1 Modbus-RTU协议

帧结构=地址+功能码+数据+校验码

  • 地址: 占用一个字节,范围0-255,其中有效范围是1-247,其他有特殊用途/保留,比如0是广播地址(广播地址主站向总线所有设备发出广播报文,所有从设备都不做应答)。
  • 功能码:占用一个字节,不同功能码对应不同功能,可以实现数据查询、修改等。
  • 数据:根据功能码不同,可以写入不同的数据,根据载荷要求数据量一般不超过252字节。
  • 校验:为了保证数据准确性,使用数据校验,从机在接收到数据后对其进行校验,与接收到的校验数据一致才会应答,反之,就不会应答。常用一般为CRC16,即两个字节的校验码。

Modbus的报文传输以字节为单位。其字节编码格式与串行异步通信一致,其中校验位如果选择无校验,则会使用2个停止位

3.2 CRC校验

标准CRC生成多项式如下表:

CRC-4x4+x+1
CRC-8x8+x5+x4+1
CRC-8x8+x2+x1+1
CRC-8x8+x6+x4+x3+x2+x1
CRC-12x12+x11+x3+x1+1
CRC-16x16+x15+x2+1
CRC-16-CCITTx16+x12+x5+1
…………

现选择最常用的CRC-16校验,说明其计算过程:

  1. 设置1个16位的寄存器为0xFFFF,令此寄存器为CRC寄存器;
  2. 把第一个8位二进制数据(既通讯信息帧的第一个字节,高8位填充0)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器,高八位数据不变;
  3. 把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;
  4. 如果移出位为0:重复第3步(再次右移一位);如果移出位为1,CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
  5. 重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
  6. 重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
  7. 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;
  8. 最后得到的CRC寄存器内容即为:CRC码。

其中
0x8005=1000 0000 0000 0101B(标准CRC-16多项式)
0xA001=1010 0000 0000 0001B
对比上述两个二进制高低位正好是完全相反的,CRC校验分为正向校验与反向校验。正向校验高位在左,反向校验低位在左,比如正向CRC校验的数据为0xAF5D=10101111 01011101B与0x8005异或时应该是0xAF5D^0x8005,而要使用0xA001与数据进行校验也应该使0xAF5D高低位换顺序为0xBAF5=1011 1010 1111 0101B。正向校验使用左移位,反向校验使用右移位,其实原理是一样的,得看校验的数据高低位顺序。
由于上述步骤使用的是反向校验,所以在第7步是交换了高低字节的顺序。

不过在实际应用中,查表法的使用更加广泛,具体的操作是,提前将8位数据存入一个16位寄存器,高八位填充0(分成0~255种情况)与0xA001进行了异或右移的处理,将最后高8位和低8位做成了单独的表格。由于常用的CRC校验表的数据计算时采用初始值为0,所以查表法中的数据存在差异。
代码如下:

unsigned short usDataLen(unsigned char *puchMsg1, unsigned short usDataLen1)
{
unsigned char uchCRCHi = 0xFF; /* CRC 的高字节初始化*/
unsigned char uchCRCLo = 0xFF; /* CRC 的低字节初始化*/
unsigned int uIndex ; /* CRC 查询表索引*/
while (usDataLen1--)/* 完成整个报文缓冲区*/
{
	uIndex = uchCRCLo ^(*(puchMsg1++)); /* 计算CRC */
	uchCRCLo = (unsigned char) (uchCRCHi ^ auchCRCHi[uIndex]);
	uchCRCHi = auchCRCLo[uIndex];
}

最后如果我们自己计算,一般采用与0x8005异或(左移)。具体步骤:

  1. 对要编码的8位数据左移到高16位,低16位进行补0;
  2. 将上述数据作为被除数,0x8005作为除数,两者做模2除;
  3. 得到16位余数即是第一个数据的CRC校验码;
  4. 由于还有第二个数据,需要重复上述操作,只是每次新得到的CRC校验码要替换被除数的低16位,以此完成迭代;
  5. 完成所有数据的计算后,得到最终的16位CRC校验码。

4 参考技术文档

各种通信协议整理
异步串行通讯和同步串行通讯区别
最详细易懂的CRC-16校验原理

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LEODWL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值