最近在使用 STM32 的 UART 功能,在上网查找资料时,碰到有人设置 UART 1 位停止位但是实测却有 2 位停止位的情况,刚好手边有一块 STM32 的板子,就测试了一下,大概分析一下 STM32 UART 的通信过程。
关于 UART 的协议和 STM32 的 UART 设置可以参考下面的文章:
基于 STM32 之 UART 串口通信协议(一)详解
下面分几种情况对 STM32 UART 进行实测分析,UART 通信波特率为 115200bps。
1. STM32 UART 设置字长为 9bits
字长设置为 9bits,8 位数据位 + 1 位奇偶校验位,1 位停止位:
huart4.Instance = UART4; huart4.Init.BaudRate = 115200; huart4.Init.WordLength = UART_WORDLENGTH_9B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_EVEN; huart4.Init.Mode = UART_MODE_TX_RX; huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart4.Init.OverSampling = UART_OVERSAMPLING_16; huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
通过 TC 寄存器判断发送完毕标志位:
static int send_string_to_uart4(char * str) { while(*str != '\0') { while(!(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_TC) == 1)); HAL_UART_Transmit(&huart4,(unsigned char*)str++,1,10); } return 0; }
实测波形如下:
从波形上可以看出,S1 为起始位,8 位数据位,后面两个红色 1 为奇偶校验位和停止位,但是 1 位停止位实际有 1.5 个周期。
2. STM32 UART 设置字长为 8bits
字长设置为 8bits,即 8 位数据位,无奇偶校验位,1 位停止位:
huart6.Instance = USART6; huart6.Init.BaudRate = 115200; huart6.Init.WordLength = UART_WORDLENGTH_8B; huart6.Init.StopBits = UART_STOPBITS_1; huart6.Init.Parity = UART_PARITY_NONE; huart6.Init.Mode = UART_MODE_TX_RX; huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart6.Init.OverSampling = UART_OVERSAMPLING_16; huart6.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart6.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
通过 TC 寄存器判断发送完毕标志位:
static int send_string_to_usart6(char * str) { while(*str != '\0') { while(!(__HAL_UART_GET_FLAG(&huart6,UART_FLAG_TC) == 1)); HAL_UART_Transmit(&huart6,(unsigned char*)str++,1,10); } return 0; }
实测波形如下:
跟第一种情况相似,1 位停止位实测有 1.25 个周期。
3. 电脑串口发送数据实测
字长设置为 8bits,8 位数据位,无奇偶校验位,1 位停止位,实测波形如下:
可以看出电脑通过串口发送的数据,停止位只占了 1 个周期。
通过上述的对比测试,STM32 UART 的停止位略大于设置的位宽,可能有两个原因:TC 寄存器的判断机制存在延迟?库函数处理代码效率低?
“ STM32 使用 USART 设置停止位为 1,示波器实际测量是 2 位”建议判断 TXE 寄存器而非 TC 寄存器解决了这个问题。但是我这里实测后,仍是略大于设置的位宽。
4. 采用 DMA + UART 的方式(20200731 更新)
采用 DMA + UART 的方式解决串口传输停止位间隔多一点的问题,分别测试字长 9bits 和 8bits 的情况,测试波形如下:
可以看出,DMA + UART 这种方式下的串口通信,停止位只占了 1 个周期。