USART是什么
USART(Universal Synchronous/Asynchronous Receiver/Transmitter)是通用同步/异步串行接收/发送器的缩写。这种通讯协议发展历史非常遥远,它甚至在PC还未普及之前就已经大规模在工业领域进行推广(用于PLC等简单运算单元之间的通信)。详细可以见这位大佬的链接。
当然,我想大家肯定还听说过USART(RS232、RS422、RS485)等其中的一个或者其他名词。他们在通信逻辑方面和USART是一致的,但是他们的逻辑1和逻辑0的表达电平不同。
为了在工业领域使用,他们的电平都比单片机使用的TTL电平要高,如果直接通入单片机引脚,那么单片机会立即被击穿。但是在工业领域,这样的高电平协议有很好的抗干扰性。详细可见链接。
其余的有关串口的基础知识在网上也有很多了。本着不重复造轮子的原则,我这里就不再赘述了。本文主要是介绍如何在CubeMX上设置串口,以及如何在Keil5中使用代码以实现功能。最后用我新买的30块大洋的逻辑分析仪来看看具体波形,验证我们设置的内容。
CubeMX串口设置
打开CubeMX,准备一个工程,(此处可参考鄙人以前的博文)。当我们打开Connectivity一栏后,我们可以看到三大通讯协议IIC、SPI、USART协议都在此处。我们在芯片引脚图中选中我们需要的引脚,图中为PB6、PB7。强烈建议先选择Pin,打上大头针后,再启用左侧菜单栏中的功能,因为很多功能都有复用的引脚,直接启用功能可能会应用在我们不需要的引脚上。
在中间Mode一栏中有选择模式和硬件流控制(RS232)。其中RS232我没有用过,其中包含RTS和CTS两种功能,都是串口流控的功能。
Mode中的功能如下:
- Asynchronous(异步):最常用的功能,需要两线(双向单车道),TX和RX,一根用于发送一根用于接收。
- Synchronous(同步):比异步多一根CK(时钟线)。
- Single wire(单线):只是用一根线来发送和接收,只可用在半双工模式,不能同时发送和接收。
- 微处理器通信:多一个唤醒功能。
- IrDA:红外通信。
- LIN总线:低配版的CAN总线协议,用于单主多从通信领域、车用。
- Smartcard:智能卡,就是IC卡。
- Smartcard with card clock:高级的带时钟的智能卡。
在本文中,我们使用的是Asynchronous(异步)功能。我们可以看到下面的参数设置只有六项。最重要的就是波特率(Baud Rate),在串口通信中只有接收发送双方约定好相同的波特率,才能进行通信。有效位数(Word Length) 是规定了一次传输数据的大小,在这里我们可以看到它是包含(Parity)的。这是 校验位(Parity),是用于让接收方校验数据的。包含的校验方式有奇校验、偶校验和无校验。停止位(Stop) 也是双方约定的,开始必定由1位逻辑0开始,结束以1位还是2位逻辑1结束,需要双方约定,注:信号线上默认拉高(逻辑1)。下面的高级的选项分别是接收和发送功能选择和过采样位数。
还要说一下除了参数设置外其他的设置。NVIC设置中,我们可以启用全局中断来使用串口中断来收发数据。DMA设置中,我们可以将串口接收和发送的数据放在DMA中,让其自动存储和自动发送,这一部分内容可以在以后讲DMA的博文中看到具体的实验验证。GPIO设置是CubeMX帮我们默认设置好的,如果需要可以添加User_label。用户常量设置也可以按需设置,本文就用不到了。
Keil v5中初始化和发送
基本的初始化代码,CubeMX已经自动生成,并把它放到了我们不能修改的 /* USER CODE BEGIN 2 */上方,这里我们不需要修改。如果需要使用串口中断,我们还需要在下方初始化启用串口中断(别忘了在CubeMX中的NVIC中勾选USART1全局中断global interrupt)。
HAL_UART_Receive_IT(&huart1, &ReceveDATA, 1);
or
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
本文不介绍中断接收发送和DMA接收和发送。可能未来会在高级一点的笔记中总结,请查找其他博主的文章。
我们在主循环中添加一个按下按键进行发送的代码,如下:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_Delay(500);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
if(KEY4 == 0)
HAL_UART_Transmit(&huart1, data, 4, 20);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
当然不能忘了设置一个我们需要发送的信息数组。由于串口一次只能发送8bit的数据,所以发送char类型或者字符串数组作为实验是非常合适的。我们设置一个字符串数组为"CTRL",就是唱跳Rap🏀。其ASCII码分别是"C"=0x43、“T”=0x54、“R”=0x52、“L”=0x4C。一会儿我们用于验证。
uint8_t data[20]="CTRL";
这样当我们看到灯开始500ms闪烁的时候,按下按键便可以发送"CTRL"。
使用逻辑分析仪进行验证
网上很多的串口和其他种类的通信协议实验都是用电脑的USB转TTL和单片机进行通信。我想换一种方式来看看在物理层,这些协议到底是长什么样的,于是就买了一个逻辑分析仪来做之后的通信协议的实验。
验证基本参数(8bit+None校验位)
- 波特率:当波特率为115200时,也就是在1s内发送115200bit的数据内容,一个bit需要8.68us,其中包含起始位、数据位、校验位和终止位。当我们不设置校验位,终止位为1位逻辑1时,我们发送一个8位数据(1个字节)时需要10个bit,我们在一秒内只能发送11520byte的数据量。这4个字节我们用了40位的空间,其中39位(第40位终止位是逻辑1,和后面一样,所以这边只划了39位)总共用时338.5us,平均到一位是8.6795us,和波特率规定的基本一致。
- 数据位顺序:图中加点的部分为有效数字位,我们可以发现分析仪说数据表达完全正确,但是具体到用电平如何表示,我们发现了一些问题。比如"C"=0x43,上面的电平显示按照顺序为1100、0010,是0xC2,是错误的。通过观察,它是倒序的,先发送的是0x43的3的最低位1。1100是3(0011),0010是4(0100)。其余的"T"=0x54、“R”=0x52、“L”=0x4C同理。
8bit/9bit与包含校验位?
在参数设置中,我们发现有效数据位是包含校验位的,那就有疑问了。8bit+奇/偶校验位的情况数据位是否只有7bit了,9bit+无校验位的情况下是否可以发9bit的数据。带着这两个问题,我们要先看一下9bit+奇/偶校验位这种比较好理解的情况是什么样的。以下是奇/偶校验的规则。
奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为: 01101001,此时总共有 4 个“1”,为达到奇校验效果,校验位为“1”,最后传输的数据将是 8 位的有效数据加上 1 位的校验位总共 9 位。
偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据帧: 11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。
————————————————
版权声明:本文为CSDN博主「没霖好叫咩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Small_ash/article/details/118929631
- 9bit(含校验位)+偶校验位:
非常不幸,“CTRL"这四个字母全是3个1,所以偶校验位都是"1”。我们可以明显的发现在所有的终止位前还有个1,使其达到了17.25us(测量值)。如图。
- 8bit(含校验位)+偶校验位:
非常可惜,发送的有效数据位真的只有7位,这些数据的最高位,也就是在有效数据位的第8个,被改成了校验位。
但是有意思的是,字符串,也就是ASCII只有128个,他们的编码只需要七位数据,所以只要把接收器改成接收7bit数据位+奇/偶校验位。就可以完美翻译"CTRL"。如下图。
- 9bit(含校验位)+无校验位:
我们发现串口外设只发送了"C"和"R",跳过了它们之后的"T"和"L"。
其实他们把"T"和"L"的最低位(0)都放在第九位发出去了,我们可以用"Q"来验证以下,因为"Q"=0x51的最后一位是1。把字符串改成"CQRL"再试一次。
我们发现0x143的最高位发了1,验证了我的猜想。说明我们可以发送9位的数据,但是必须在八位的数组中用两个位置来做这个9位的数据。 - 总结
CubeMX搭配 | 实际用途 |
---|---|
8bit(含校验位)+奇/偶校验位 | 7bit数据+奇/偶校验位 |
8bit(含校验位)+无校验位 | 8bit数据+无校验位 |
9bit(含校验位)+奇/偶校验位 | 8bit数据+奇/偶校验位 |
9bit(含校验位)+无校验位 | 9bit数据+无校验位 |
总结
通过数据逻辑分析仪做实验,我们可以发现更多新的盲点,这样可以让我们对通信协议更加了解。也可以尝试用软件的方式去编写一个通讯协议,以代替不太好的硬件。说的就是你,IIC。在之后的IIC实验中,我们也可以看看STM32的硬件IIC和软件IIC的差别是什么。