UART协议介绍

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,通常称作UART)
是一种串行异步收发协议,应用十分广泛。UART工作原理是将数据的二进制位一位一位的进行传输。在UART通讯协议中信号线上的状态位高电平代表’1’低电平代表’0’。当然两个设备使用UART串口通讯时,必须先约定好传输速率和一些数据位。

硬件连接

关键词:

1. UART为串行异步协议

2. TTL 、RS232、RS485是一种逻辑电平表示方式。

3. 帧格式:1位空闲位,5~9位的数据位,1位校验位, 1 ~ 2位的停止位

异步和同步的解释

解释1:

  1. 异步就是发送信息后,发送者发送信息后,就不再管,发送者并不管接收者在不在线 ----------发短信就是异步
  2. 同步就是发送者与接收者同步交流,一方退出,另一方也随之中断通信--------------如打电话。

解释2:

  1. 有时钟信号的是同步
  2. 没有时钟信息的是异步

串行与并行的区别

1. 并行传输:

字符编码的各位(比特)同时传输。
特点:
(1)传输速度快:一位(比特)时间内可传输一个字符,并行口传输8位数据一次送出.;
(2)通信成本高:每位传输要求一个单独的信道支持;因此如果一个字符包含8个二进制位,则并行传输要求8个独立的信道的支持;
(3)不支持长距离传输:由于信道之间的电容感应,远距离传输时,可靠性较低。
(4)针脚:针脚多
(5)用途:多用作打印机、扫描仪等接口

2 .串行传输:

将组成字符的各位串行地发往线路。
特点:
(1)传输速度较低,一次一位,串行口传输方式为数据排成一行、一位一位送出接收也一样;
(2)通信成本也较低,只需一个信道。
(3)支持长距离传输,目前计算机网络中所用的传输方式均为串行传输。
(4)针脚:针脚少
(5)用途:只用作控制接口
方式: 串行传输有两种传输方式:
(1)同步传输
(2)异步传输

电气标准:

TTL 、RS232、RS485是一种逻辑电平表示方式。

  1. TTL:全双工(逻辑1:2.4v-5v 逻辑0:0v-0.5v
  2. RS232:电子工业协会制定的异步传输标准接口,全双工(逻辑1:-15v–5v 逻辑0:+3v-+15v
  3. RS485:为了长距离传输采用差分方式传输,半双工(逻辑1:+2v-+6v 逻辑0:-6v–2v),电平指AB两线间的电压差。

TTL电平

1.TTL用于2个MCU的连接图

在这里插入图片描述

2.TTL’0’与‘1’的表示

在这里插入图片描述

RS232电平

由于TTL的抗干扰能力较弱,通讯距离短,因此引入RS232逻辑电平。RS232适用于本地设备间通信,传输距离一般不超过20m。RS232采取不平衡传输方式。只允许一对一通信。

1.MCU与PC通信连接图

在这里插入图片描述

2.RS232’0’与‘1’的表示

在这里插入图片描述

RS485电平

RS485采样差分传输,传输距离为几十米到几千米,一对多通信,总线上允许多达128个收发器。

1.连接方式

在这里插入图片描述

2.‘0’与‘1’表示

在这里插入图片描述

软件通信协议

UART作为异步串口通信协议的一种,工作原理是将数据的字节一位接一位地传输。协议如下:

在这里插入图片描述

空闲位:

UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平

起始位:

开始进行数据传输时发送方要先发出一个低电平’0’来表示传输字符的开始。因为空闲位一直是高电平所以开始第一次通讯时先发送一个明显区别于空闲状态的信号即为低电平。

数据位:

起始位之后就是要传输的数据,数据可以是5,6,7,8,9位,构成一个字符,一般都是8位。先发送最低位最后发送最高位。

奇偶校验位:

数据位传送完成后,要进行奇偶校验,校验位其实是调整个数,串口校验分几种方式:
1.无校验(no parity)
2.奇校验(odd parity):如果数据位中’1’的数目是偶数,则校验位为’1’,如果’1’的数目是奇数,校验位为’0’。
3.偶校验(even parity):如果数据为中’1’的数目是偶数,则校验位为’0’,如果为奇数,校验位为’1’。
4.mark parity:校验位始终为1
5.space parity:校验位始终为0

停止位:

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

波特率:

在这里插入图片描述

数据传输速率使用波特率来表示,单位bps(bits per
second),常见的波特率9600bps,115200bps等等,其他标准的波特率是1200,2400,4800,19200,38400,57600。举个例子,如果串口波特率设置为9600bps,那么传输一个比特需要的时间是1/9600≈104.2us。

以9600
8N1(9600波特率,8个数据位,没有校验位,1位停止位)为例,这是目前最常用的串口配置,现在我们传输’O’'K’两个ASCII值,'O’的ASCII为79,对应的二进制数据为01001111
,'K’对应的二进制数据为01001011 ,传输的格式数据如下图所示:

在这里插入图片描述

串口波特率为9600,1bit传输时间大约为104us,传送一个数据实际是10个比特(开始位,8个数据位,停止位),一个bytes传输速率实际为9600*8/10=7680bps。

原文链接:https://blog.csdn.net/sternlycore/article/details/85244515

自定义串口通信协议

1. 过于简单的通信协议引发的问题

比如:多个设备连接在一条总线(比如485)上,怎么判断传输给谁?(没有设备信息)

还比如:处于一个干扰环境,你能保障传输数据正确吗?(没有校验信息)

再比如:我想传输多个不确定长度的数据,该怎么办?(没有长度信息)。

上面这一系列问题,相信做过自定义通信的朋友都了解。

所以,在通信协议里面要约定更多的“协议信息”,这样才能保证通信的完整。

2.通信协议常见内容

基于串口的通信协议通常不能太复杂,因为串口通信速率、抗干扰能力以及其他各方面原因,相对于TCP/IP这种通信协议,是一种很轻量级的通信协议。

所以,基于串口的通信,除了一些通用的通信协议(比如:Modubs、MAVLink)之外,很多时候,工程师都会根据自己项目情况,自定义通信协议。
在这里插入图片描述(这是一些常见的协议内容,可能不同情况,其协议内容不同)

a.帧头

帧头,就是一帧通信数据的开头。
有的通信协议帧头只有一个,有的有两个,比如:5A、A5作为帧头。

b.设备地址/类型

设备地址或者设备类型,通常是用于多种设备之间,为了方便区分不同设备。


这种情况,需要在协议或者附录中要描述各种设备类型信息,方便开发者编码查询。

当然,有些固定的两种设备之间通信,可能没有这个选项。

c.命令/指令

命令/指令比较常见,一般是不同的操作,用不同的命令来区分。
在这里插入图片描述

举例:温度:0x01;湿度:0x02;

d.命令类型/功能码

这个选项对命令进一步补充。比如:读、写操作。
在这里插入图片描述

举例:读Flash:0x01; 写Flash:0x02;

e.数据长度

数据长度这个选项,可能有的协议会把该选项提到前面设备地址位置,把命令这些信息算在“长度”里面。

这个主要是方便协议(接收)解析的时候,统计接收数据长度。
在这里插入图片描述

比如:有时候传输一个有效数据,有时候要传输多个有效数据,甚至传输一个数组的数据。这个时候,传输的一帧数据就是不定长数据,就必须要有【数据长度】来约束。

有的长度是一个字节,其范围:0x01 ~ 0xFF,有的可能要求一次性传输更多,就用两个字节表示,其范围0x0001 ~ 0xFFFFF。

当然,有的通信长度是固定的长度(比如固定只传输、温度、湿度这两个数据),其协议可能没有这个选项。

f.数据

数据就不用描述了,就是你传输的实实在在的数据,比如温度:25℃。

g.帧尾

有些协议可能没有帧尾,这个应该是可有可无的一个选项。

h.校验码

校验码是一个比较重要的内容,一般正规一点的通信协议都有这个选项,原因很简单,通信很容易受到干扰,或者其他原因,导致传输数据出错。

如果有校验码,就能比较有效避免数据传输出错的的情况。
在这里插入图片描述
校验码的方式有很多,校验和、CRC校验算是比较常见的,用于自定义协议中的校验方式。

还有一点,有的协议可能把校验码放在倒数第二,帧尾放在最后位置。

通信协议代码实现

自定义通信协议,代码实现的方式有很多种,怎么说呢,“条条大路通罗马”你只需要按照你协议要写实现代码就行。

当然,实现的同时,需要考虑你项目实际情况,比如通信数据比较多,要用消息队列(FIFO),还比如,如果协议复杂,最好封装结构体等。

下面分享一些以前用到的代码,可能没有描述更多细节,但一些思想可以借鉴。

1.用“结构体”代替“数组SendBuf”方式

结构体对数组更方便引用,也方便管理,所以,结构体方式相比数组buf更高级,也更实用。(当然,如果成员比较多,如果用临时变量方式也会导致占用过多堆栈的情况)

比如:

typedef struct
{
  uint8_t  Head1;                 //帧头1
  uint8_t  Head2;                 //帧头2
  uint8_t  Len;                   //长度
  uint8_t  Cmd;                   //命令
  uint8_t  Data[DGUS_DATA_LEN];   //数据
  uint16_t CRC16;                 //CRC校验 
}DGUS_PACKAGE_TypeDef;

2.消息数据接收

串口消息接收,通常串口中断接收的方式居多,当然,也有很少情况用轮询的方式接收数据。

a.常规中断接收

描述一种简单又常见的中断接收方式:

b.增加超时检测

接收数据有可能存在接收了一半,中断因为某种原因中断了,这时候,超时检测也很有必要。

比如:用多余的MCU定时器做一个超时计数的处理,接收到一个数据,开始计时,超过1ms没有接收到下一个数据,就丢掉这一包(前面接收的)数据。

static void DGUS_TimingAndUpdate(uint16_t Nms)
{
  sDGUSTiming_Nms_Num = Nms;
  TIM_SetCounter(DGUS_TIM, 0);                   //设置计数值为0
  TIM_Cmd(DGUS_TIM, ENABLE);                     //启动定时器
}
 
 
void DGUS_COM_IRQHandler(void)
{
  if((DGUS_COM->SR & USART_FLAG_RXNE) == USART_FLAG_RXNE)
  {
    DGUS_TimingAndUpdate(5);                     //更新定时(防止超时)
    DGUS_ISRHandler((uint8_t)USART_ReceiveData(DGUS_COM));
  }
}

参考链接:协议参考链接名词参考链接

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值