一、UART通信协议

UART通用异步收发器(Universal Asynchronous Receiver and Transmitter)是STM32 上常用的串行通信外设,可以灵活地与外部设备进行全双工数据交换,需要注意区别:

【1】USART-通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter),UART是在USART上裁减了同步通信(时钟同步)的串行通信。

【2】串行通信和并行通信区别,串行通信是指设备之间通过一根数据信号线,地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式,同一时刻只能传输一位(bit)数据;并行通讯:是指使用 8 根或更多()的数据线进行传输的通讯方式,可以同一时刻传输多个数据位的数据(有多少根线就可以一次传输多少bit数据)。

串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、校验信息(由我们自己设置)、停止信号。而每帧数据由二进制(0、1组成)转换为TTL电平对外发送,TTL电平中逻辑1采用2.4~5V电平标识,逻辑0采用0~0.5V电平标识。

串口通讯协议由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致(一样的起始位 数据 校验位 停止位)才能正常收发数据。

以传输一个字节数(8bit)为例,数据传输格式如下:

【1】数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示:

1个停止位:停止位位数的默认值。

2个停止位:可用于常规USART模式、单线模式以及调制解调器模式。

0.5个停止位:在智能卡模式下接收数据时使用。

1.5个停止位:在智能卡模式下发送和接收数据时使用。

【2】起始位和校验位中间的数据内容为真正需要传输的有效内容。

【3】奇偶校验位,指的是停止位前一bit的采用0或1值来标识偶校验还是奇校验。

偶校验,校验位值为0时,要求起始位和校验位中间的数据内容包含'1'的个数为偶数个。

奇校验,校验位值为1时,要求起始位和校验位中间的数据内容包含'1'的个数为奇数个。

注:奇偶校验位也是不严禁的,如果起始位和校验位中间的数据内容出现多次错误,例如先发送一个奇校验的01001100的数据,但是接收方得到01111100的奇校验数据,认为是正确的,但其实是出错了,这种情况是存在的,但概率会很少,毕竟单字节数发送,同时出现两个以上数据位错误的概率是极少的。通常我们在实际使用UART通信时,都不设置奇偶检验。

二、UART数据收发原理

从数据转换层面上来说,UART数据收发主要涉及的几个寄存器,数据寄存器(Data Register)、控制寄存器(Control Register)、状态寄存器(Status Register)、波特率寄存器(BaudRate Register ),在HLA底层实现数据收发过程如下图。

2.1 数据寄存器UART_DR

数据寄存器UART_DR,包含了发送和接收数据,通常由两个寄存器组成,一个用于发送的TDR,一个接收数据用的RDR,两个寄存器均具有读写功能,UART_DR寄存器与控制器寄存器(UART_CR)通信。在STM32-HAL库中关于UART通信实现驱动在stm32*_hal_uart.c文件中,UART数据从缓存区转换到DR寄存器是有UART的注册函数UART_TxISR_8BIT或UART_RxISR_8BIT实现的。

而注册函数UART_TxISR_8BIT调用是由更上层的HAL发送函数HAL_UART_Transmit*来传递的,接收类似。

数据发送寄存器UART_TDR和数据接收寄存器UART_RDR在HLA库中是16bit宽度的存储区域。

2.2 控制寄存器UART_CR

控制寄存器UART_CR,由三个32bit宽度的数据组成(CR1、CR2、CR3),共96bit数据,每个BIT都具有明确定义。UART_CR会一次从UART_TDR读取8数据位宽度的数据,即一个字节数据,然后按位转换成TTL电平发送。

控制寄存器CR1、CR2、CR3的定义在stm32-HAL驱动实现中,是根据芯片型号不同,各个字段定义有所区别,因此CR1、CR2、CR3的每个bit定义存放在CMSIS(微控制器软件接口标准)和芯片序列相关的头文件内,例如stm32l496xx.h。

关于CR1、CR2、CR3的每个bit定义及相关数值含义可以在上述描述的头文件中查看,例如stm32l496xx.h的定义如下。

/******************  Bit definition for USART_CR1 register  *******************/
#define USART_CR1_UE_Pos              (0U)
#define USART_CR1_UE_Msk              (0x1UL << USART_CR1_UE_Pos)              /*!< 0x00000001 */
#define USART_CR1_UE                  USART_CR1_UE_Msk                         /*!< USART Enable */
#define USART_CR1_UESM_Pos            (1U)
#define USART_CR1_UESM_Msk            (0x1UL << USART_CR1_UESM_Pos)            /*!< 0x00000002 */
#define USART_CR1_UESM                USART_CR1_UESM_Msk                       /*!< USART Enable in STOP Mode */
#define USART_CR1_RE_Pos              (2U)
#define USART_CR1_RE_Msk              (0x1UL << USART_CR1_RE_Pos)              /*!< 0x00000004 */
#define USART_CR1_RE                  USART_CR1_RE_Msk                         /*!< Receiver Enable */
#define USART_CR1_TE_Pos              (3U)
#define USART_CR1_TE_Msk              (0x1UL << USART_CR1_TE_Pos)              /*!< 0x00000008 */
#define USART_CR1_TE                  USART_CR1_TE_Msk                         /*!< Transmitter Enable */
#define USART_CR1_IDLEIE_Pos          (4U)
#define USART_CR1_IDLEIE_Msk          (0x1UL << USART_CR1_IDLEIE_Pos)          /*!< 0x00000010 */
#define USART_CR1_IDLEIE              USART_CR1_IDLEIE_Msk                     /*!< IDLE Interrupt Enable */
#define USART_CR1_RXNEIE_Pos          (5U)
#define USART_CR1_RXNEIE_Msk          (0x1UL << USART_CR1_RXNEIE_Pos)          /*!< 0x00000020 */
#define USART_CR1_RXNEIE              USART_CR1_RXNEIE_Msk                     /*!< RXNE Interrupt Enable */
#define USART_CR1_TCIE_Pos            (6U)
#define USART_CR1_TCIE_Msk            (0x1UL << USART_CR1_TCIE_Pos)            /*!< 0x00000040 */
#define USART_CR1_TCIE                USART_CR1_TCIE_Msk                       /*!< Transmission Complete Interrupt Enable */
#define USART_CR1_TXEIE_Pos           (7U)
#define USART_CR1_TXEIE_Msk           (0x1UL << USART_CR1_TXEIE_Pos)           /*!< 0x00000080 */
#define USART_CR1_TXEIE               USART_CR1_TXEIE_Msk                      /*!< TXE Interrupt Enable */
#define USART_CR1_PEIE_Pos            (8U)
#define USART_CR1_PEIE_Msk            (0x1UL << USART_CR1_PEIE_Pos)            /*!< 0x00000100 */
#define USART_CR1_PEIE                USART_CR1_PEIE_Msk                       /*!< PE Interrupt Enable */
#define USART_CR1_PS_Pos              (9U)
#define USART_CR1_PS_Msk              (0x1UL << USART_CR1_PS_Pos)              /*!< 0x00000200 */
#define USART_CR1_PS                  USART_CR1_PS_Msk                         /*!< Parity Selection */
#define USART_CR1_PCE_Pos             (10U)
#define USART_CR1_PCE_Msk             (0x1UL << USART_CR1_PCE_Pos)             /*!< 0x00000400 */
#define USART_CR1_PCE                 USART_CR1_PCE_Msk                        /*!< Parity Control Enable */
#define USART_CR1_WAKE_Pos            (11U)
#define USART_CR1_WAKE_Msk            (0x1UL << USART_CR1_WAKE_Pos)            /*!< 0x00000800 */
#define USART_CR1_WAKE                USART_CR1_WAKE_Msk                       /*!< Receiver Wakeup method */
#define USART_CR1_M_Pos               (12U)
#define USART_CR1_M_Msk               (0x10001UL << USART_CR1_M_Pos)           /*!< 0x10001000 */
#define USART_CR1_M                   USART_CR1_M_Msk                          /*!< Word length */
#define USART_CR1_M0_Pos              (12U)
#define USART_CR1_M0_Msk              (0x1UL << USART_CR1_M0_Pos)              /*!< 0x00001000 */
#define USART_CR1_M0                  USART_CR1_M0_Msk                         /*!< Word length - Bit 0 */
#define USART_CR1_MME_Pos             (13U)
#define USART_CR1_MME_Msk             (0x1UL << USART_CR1_MME_Pos)             /*!< 0x00002000 */
#define USART_CR1_MME                 USART_CR1_MME_Msk                        /*!< Mute Mode Enable */
#define USART_CR1_CMIE_Pos            (14U)
#define USART_CR1_CMIE_Msk            (0x1UL << USART_CR1_CMIE_Pos)            /*!< 0x00004000 */
#define USART_CR1_CMIE                USART_CR1_CMIE_Msk                       /*!< Character match interrupt enable */
#define USART_CR1_OVER8_Pos           (15U)
#define USART_CR1_OVER8_Msk           (0x1UL << USART_CR1_OVER8_Pos)           /*!< 0x00008000 */
#define USART_CR1_OVER8               USART_CR1_OVER8_Msk                      /*!< Oversampling by 8-bit or 16-bit mode */
#define USART_CR1_DEDT_Pos            (16U)
#define USART_CR1_DEDT_Msk            (0x1FUL << USART_CR1_DEDT_Pos)           /*!< 0x001F0000 */
#define USART_CR1_DEDT                USART_CR1_DEDT_Msk                       /*!< DEDT[4:0] bits (Driver Enable Deassertion Time) */
#define USART_CR1_DEDT_0              (0x01UL << USART_CR1_DEDT_Pos)           /*!< 0x00010000 */
#define USART_CR1_DEDT_1              (0x02UL << USART_CR1_DEDT_Pos)           /*!< 0x00020000 */
#define USART_CR1_DEDT_2              (0x04UL << USART_CR1_DEDT_Pos)           /*!< 0x00040000 */
#define USART_CR1_DEDT_3              (0x08UL << USART_CR1_DEDT_Pos)           /*!< 0x00080000 */
#define USART_CR1_DEDT_4              (0x10UL << USART_CR1_DEDT_Pos)           /*!< 0x00100000 */
#define USART_CR1_DEAT_Pos            (21U)
#define USART_CR1_DEAT_Msk            (0x1FUL << USART_CR1_DEAT_Pos)           /*!< 0x03E00000 */
#define USART_CR1_DEAT                USART_CR1_DEAT_Msk                       /*!< DEAT[4:0] bits (Driver Enable Assertion Time) */
#define USART_CR1_DEAT_0              (0x01UL << USART_CR1_DEAT_Pos)           /*!< 0x00200000 */
#define USART_CR1_DEAT_1              (0x02UL << USART_CR1_DEAT_Pos)           /*!< 0x00400000 */
#define USART_CR1_DEAT_2              (0x04UL << USART_CR1_DEAT_Pos)           /*!< 0x00800000 */
#define USART_CR1_DEAT_3              (0x08UL << USART_CR1_DEAT_Pos)           /*!< 0x01000000 */
#define USART_CR1_DEAT_4              (0x10UL << USART_CR1_DEAT_Pos)           /*!< 0x02000000 */
#define USART_CR1_RTOIE_Pos           (26U)
#define USART_CR1_RTOIE_Msk           (0x1UL << USART_CR1_RTOIE_Pos)           /*!< 0x04000000 */
#define USART_CR1_RTOIE               USART_CR1_RTOIE_Msk                      /*!< Receive Time Out interrupt enable */
#define USART_CR1_EOBIE_Pos           (27U)
#define USART_CR1_EOBIE_Msk           (0x1UL << USART_CR1_EOBIE_Pos)           /*!< 0x08000000 */
#define USART_CR1_EOBIE               USART_CR1_EOBIE_Msk                      /*!< End of Block interrupt enable */
#define USART_CR1_M1_Pos              (28U)
#define USART_CR1_M1_Msk              (0x1UL << USART_CR1_M1_Pos)              /*!< 0x10000000 */
#define USART_CR1_M1                  USART_CR1_M1_Msk                         /*!< Word length - Bit 1 *//******************  Bit definition for USART_CR2 register  *******************/
#define USART_CR2_ADDM7_Pos           (4U)
#define USART_CR2_ADDM7_Msk           (0x1UL << USART_CR2_ADDM7_Pos)           /*!< 0x00000010 */
#define USART_CR2_ADDM7               USART_CR2_ADDM7_Msk                      /*!< 7-bit or 4-bit Address Detection */
#define USART_CR2_LBDL_Pos            (5U)
#define USART_CR2_LBDL_Msk            (0x1UL << USART_CR2_LBDL_Pos)            /*!< 0x00000020 */
#define USART_CR2_LBDL                USART_CR2_LBDL_Msk                       /*!< LIN Break Detection Length */
#define USART_CR2_LBDIE_Pos           (6U)
#define USART_CR2_LBDIE_Msk           (0x1UL << USART_CR2_LBDIE_Pos)           /*!< 0x00000040 */
#define USART_CR2_LBDIE               USART_CR2_LBDIE_Msk                      /*!< LIN Break Detection Interrupt Enable */
#define USART_CR2_LBCL_Pos            (8U)
#define USART_CR2_LBCL_Msk            (0x1UL << USART_CR2_LBCL_Pos)            /*!< 0x00000100 */
#define USART_CR2_LBCL                USART_CR2_LBCL_Msk                       /*!< Last Bit Clock pulse */
#define USART_CR2_CPHA_Pos            (9U)
#define USART_CR2_CPHA_Msk            (0x1UL << USART_CR2_CPHA_Pos)            /*!< 0x00000200 */
#define USART_CR2_CPHA                USART_CR2_CPHA_Msk                       /*!< Clock Phase */
#define USART_CR2_CPOL_Pos            (10U)
#define USART_CR2_CPOL_Msk            (0x1UL << USART_CR2_CPOL_Pos)            /*!< 0x00000400 */
#define USART_CR2_CPOL                USART_CR2_CPOL_Msk                       /*!< Clock Polarity */
#define USART_CR2_CLKEN_Pos           (11U)
#define USART_CR2_CLKEN_Msk           (0x1UL << USART_CR2_CLKEN_Pos)           /*!< 0x00000800 */
#define USART_CR2_CLKEN               USART_CR2_CLKEN_Msk                      /*!< Clock Enable */
#define USART_CR2_STOP_Pos            (12U)
#define USART_CR2_STOP_Msk            (0x3UL << USART_CR2_STOP_Pos)            /*!< 0x00003000 */
#define USART_CR2_STOP                USART_CR2_STOP_Msk                       /*!< STOP[1:0] bits (STOP bits) */
#define USART_CR2_STOP_0              (0x1UL << USART_CR2_STOP_Pos)            /*!< 0x00001000 */
#define USART_CR2_STOP_1              (0x2UL << USART_CR2_STOP_Pos)            /*!< 0x00002000 */
#define USART_CR2_LINEN_Pos           (14U)
#define USART_CR2_LINEN_Msk           (0x1UL << USART_CR2_LINEN_Pos)           /*!< 0x00004000 */
#define USART_CR2_LINEN               USART_CR2_LINEN_Msk                      /*!< LIN mode enable */
#define USART_CR2_SWAP_Pos            (15U)
#define USART_CR2_SWAP_Msk            (0x1UL << USART_CR2_SWAP_Pos)            /*!< 0x00008000 */
#define USART_CR2_SWAP                USART_CR2_SWAP_Msk                       /*!< SWAP TX/RX pins */
#define USART_CR2_RXINV_Pos           (16U)
#define USART_CR2_RXINV_Msk           (0x1UL << USART_CR2_RXINV_Pos)           /*!< 0x00010000 */
#define USART_CR2_RXINV               USART_CR2_RXINV_Msk                      /*!< RX pin active level inversion */
#define USART_CR2_TXINV_Pos           (17U)
#define USART_CR2_TXINV_Msk           (0x1UL << USART_CR2_TXINV_Pos)           /*!< 0x00020000 */
#define USART_CR2_TXINV               USART_CR2_TXINV_Msk                      /*!< TX pin active level inversion */
#define USART_CR2_DATAINV_Pos         (18U)
#define USART_CR2_DATAINV_Msk         (0x1UL << USART_CR2_DATAINV_Pos)         /*!< 0x00040000 */
#define USART_CR2_DATAINV             USART_CR2_DATAINV_Msk                    /*!< Binary data inversion */
#define USART_CR2_MSBFIRST_Pos        (19U)
#define USART_CR2_MSBFIRST_Msk        (0x1UL << USART_CR2_MSBFIRST_Pos)        /*!< 0x00080000 */
#define USART_CR2_MSBFIRST            USART_CR2_MSBFIRST_Msk                   /*!< Most Significant Bit First */
#define USART_CR2_ABREN_Pos           (20U)
#define USART_CR2_ABREN_Msk           (0x1UL << USART_CR2_ABREN_Pos)           /*!< 0x00100000 */
#define USART_CR2_ABREN               USART_CR2_ABREN_Msk                      /*!< Auto Baud-Rate Enable*/
#define USART_CR2_ABRMODE_Pos         (21U)
#define USART_CR2_ABRMODE_Msk         (0x3UL << USART_CR2_ABRMODE_Pos)         /*!< 0x00600000 */
#define USART_CR2_ABRMODE             USART_CR2_ABRMODE_Msk                    /*!< ABRMOD[1:0] bits (Auto Baud-Rate Mode) */
#define USART_CR2_ABRMODE_0           (0x1UL << USART_CR2_ABRMODE_Pos)         /*!< 0x00200000 */
#define USART_CR2_ABRMODE_1           (0x2UL << USART_CR2_ABRMODE_Pos)         /*!< 0x00400000 */
#define USART_CR2_RTOEN_Pos           (23U)
#define USART_CR2_RTOEN_Msk           (0x1UL << USART_CR2_RTOEN_Pos)           /*!< 0x00800000 */
#define USART_CR2_RTOEN               USART_CR2_RTOEN_Msk                      /*!< Receiver Time-Out enable */
#define USART_CR2_ADD_Pos             (24U)
#define USART_CR2_ADD_Msk             (0xFFUL << USART_CR2_ADD_Pos)            /*!< 0xFF000000 */
#define USART_CR2_ADD                 USART_CR2_ADD_Msk                        /*!< Address of the USART node *//******************  Bit definition for USART_CR3 register  *******************/
#define USART_CR3_EIE_Pos             (0U)
#define USART_CR3_EIE_Msk             (0x1UL << USART_CR3_EIE_Pos)             /*!< 0x00000001 */
#define USART_CR3_EIE                 USART_CR3_EIE_Msk                        /*!< Error Interrupt Enable */
#define USART_CR3_IREN_Pos            (1U)
#define USART_CR3_IREN_Msk            (0x1UL << USART_CR3_IREN_Pos)            /*!< 0x00000002 */
#define USART_CR3_IREN                USART_CR3_IREN_Msk                       /*!< IrDA mode Enable */
#define USART_CR3_IRLP_Pos            (2U)
#define USART_CR3_IRLP_Msk            (0x1UL << USART_CR3_IRLP_Pos)            /*!< 0x00000004 */
#define USART_CR3_IRLP                USART_CR3_IRLP_Msk                       /*!< IrDA Low-Power */
#define USART_CR3_HDSEL_Pos           (3U)
#define USART_CR3_HDSEL_Msk           (0x1UL << USART_CR3_HDSEL_Pos)           /*!< 0x00000008 */
#define USART_CR3_HDSEL               USART_CR3_HDSEL_Msk                      /*!< Half-Duplex Selection */
#define USART_CR3_NACK_Pos            (4U)
#define USART_CR3_NACK_Msk            (0x1UL << USART_CR3_NACK_Pos)            /*!< 0x00000010 */
#define USART_CR3_NACK                USART_CR3_NACK_Msk                       /*!< SmartCard NACK enable */
#define USART_CR3_SCEN_Pos            (5U)
#define USART_CR3_SCEN_Msk            (0x1UL << USART_CR3_SCEN_Pos)            /*!< 0x00000020 */
#define USART_CR3_SCEN                USART_CR3_SCEN_Msk                       /*!< SmartCard mode enable */
#define USART_CR3_DMAR_Pos            (6U)
#define USART_CR3_DMAR_Msk            (0x1UL << USART_CR3_DMAR_Pos)            /*!< 0x00000040 */
#define USART_CR3_DMAR                USART_CR3_DMAR_Msk                       /*!< DMA Enable Receiver */
#define USART_CR3_DMAT_Pos            (7U)
#define USART_CR3_DMAT_Msk            (0x1UL << USART_CR3_DMAT_Pos)            /*!< 0x00000080 */
#define USART_CR3_DMAT                USART_CR3_DMAT_Msk                       /*!< DMA Enable Transmitter */
#define USART_CR3_RTSE_Pos            (8U)
#define USART_CR3_RTSE_Msk            (0x1UL << USART_CR3_RTSE_Pos)            /*!< 0x00000100 */
#define USART_CR3_RTSE                USART_CR3_RTSE_Msk                       /*!< RTS Enable */
#define USART_CR3_CTSE_Pos            (9U)
#define USART_CR3_CTSE_Msk            (0x1UL << USART_CR3_CTSE_Pos)            /*!< 0x00000200 */
#define USART_CR3_CTSE                USART_CR3_CTSE_Msk                       /*!< CTS Enable */
#define USART_CR3_CTSIE_Pos           (10U)
#define USART_CR3_CTSIE_Msk           (0x1UL << USART_CR3_CTSIE_Pos)           /*!< 0x00000400 */
#define USART_CR3_CTSIE               USART_CR3_CTSIE_Msk                      /*!< CTS Interrupt Enable */
#define USART_CR3_ONEBIT_Pos          (11U)
#define USART_CR3_ONEBIT_Msk          (0x1UL << USART_CR3_ONEBIT_Pos)          /*!< 0x00000800 */
#define USART_CR3_ONEBIT              USART_CR3_ONEBIT_Msk                     /*!< One sample bit method enable */
#define USART_CR3_OVRDIS_Pos          (12U)
#define USART_CR3_OVRDIS_Msk          (0x1UL << USART_CR3_OVRDIS_Pos)          /*!< 0x00001000 */
#define USART_CR3_OVRDIS              USART_CR3_OVRDIS_Msk                     /*!< Overrun Disable */
#define USART_CR3_DDRE_Pos            (13U)
#define USART_CR3_DDRE_Msk            (0x1UL << USART_CR3_DDRE_Pos)            /*!< 0x00002000 */
#define USART_CR3_DDRE                USART_CR3_DDRE_Msk                       /*!< DMA Disable on Reception Error */
#define USART_CR3_DEM_Pos             (14U)
#define USART_CR3_DEM_Msk             (0x1UL << USART_CR3_DEM_Pos)             /*!< 0x00004000 */
#define USART_CR3_DEM                 USART_CR3_DEM_Msk                        /*!< Driver Enable Mode */
#define USART_CR3_DEP_Pos             (15U)
#define USART_CR3_DEP_Msk             (0x1UL << USART_CR3_DEP_Pos)             /*!< 0x00008000 */
#define USART_CR3_DEP                 USART_CR3_DEP_Msk                        /*!< Driver Enable Polarity Selection */
#define USART_CR3_SCARCNT_Pos         (17U)
#define USART_CR3_SCARCNT_Msk         (0x7UL << USART_CR3_SCARCNT_Pos)         /*!< 0x000E0000 */
#define USART_CR3_SCARCNT             USART_CR3_SCARCNT_Msk                    /*!< SCARCNT[2:0] bits (SmartCard Auto-Retry Count) */
#define USART_CR3_SCARCNT_0           (0x1UL << USART_CR3_SCARCNT_Pos)         /*!< 0x00020000 */
#define USART_CR3_SCARCNT_1           (0x2UL << USART_CR3_SCARCNT_Pos)         /*!< 0x00040000 */
#define USART_CR3_SCARCNT_2           (0x4UL << USART_CR3_SCARCNT_Pos)         /*!< 0x00080000 */
#define USART_CR3_WUS_Pos             (20U)
#define USART_CR3_WUS_Msk             (0x3UL << USART_CR3_WUS_Pos)             /*!< 0x00300000 */
#define USART_CR3_WUS                 USART_CR3_WUS_Msk                        /*!< WUS[1:0] bits (Wake UP Interrupt Flag Selection) */
#define USART_CR3_WUS_0               (0x1UL << USART_CR3_WUS_Pos)             /*!< 0x00100000 */
#define USART_CR3_WUS_1               (0x2UL << USART_CR3_WUS_Pos)             /*!< 0x00200000 */
#define USART_CR3_WUFIE_Pos           (22U)
#define USART_CR3_WUFIE_Msk           (0x1UL << USART_CR3_WUFIE_Pos)           /*!< 0x00400000 */
#define USART_CR3_WUFIE               USART_CR3_WUFIE_Msk                      /*!< Wake Up Interrupt Enable */
#define USART_CR3_UCESM_Pos           (23U)
#define USART_CR3_UCESM_Msk           (0x1UL << USART_CR3_UCESM_Pos)           /*!< 0x02000000 */
#define USART_CR3_UCESM               USART_CR3_UCESM_Msk                      /*!< USART Clock enable in Stop mode */
#define USART_CR3_TCBGTIE_Pos         (24U)
#define USART_CR3_TCBGTIE_Msk         (0x1UL << USART_CR3_TCBGTIE_Pos)         /*!< 0x01000000 */
#define USART_CR3_TCBGTIE             USART_CR3_TCBGTIE_Msk                    /*!< Transmission Complete Before Guard Time Interrupt Enable */

这里只说CR1、CR2、CR3主要的标识位。

【1】在CR1中:

1)UE位(0位)定义UART使能;

2)UESM位(1位)定义使能是否开启STOP模式;

3)RE位(2位)定义数据接收使能;

4)TE位(3位)定义数据发送使能;

5)M位(10位)定义数据字长度,0是一个起始位、8个数据位、n个停止位,1则表示一个起始位、9个数据位、n个停止位;

6)PCE位(12位)定义是否开启硬件检验控制使能奇偶校验,0是禁止校验控制,1是开启校验控制。

【2】在CR2中,STOP位(12、13位)标注停止位,就是前面所述的:

00-1个停止位:停止位位数的默认值。

01-0.5个停止位:在智能卡模式下接收数据时使用。

10-2个停止位:可用于常规USART模式、单线模式以及调制解调器模式。

11-1.5个停止位:在智能卡模式下发送和接收数据时使用。

【3】在CR3中,DMAR位(6bit)使能DMA接收,而DMAT位(7位)使能DMA发送。

2.3 波特率寄存器BRR

波特率寄存器BRR若是一个16位的存储空间用于存放分频除法因子UARTDIV,低4位存储小数部分,高12位存储整数部分。假设UART的时钟经过多次分频,总分频数是div,最终输出频率是fpclk,则波特率br=fpclk/(div*UARTDIV)。这个UARTDIV在cubeMX是不用做配置的,而是在配置了波特率、时钟分频及时钟频率后,生成输出代码时,在UART初始化时,自动根据波特率和时钟参数计算出UARTDIV写入到BRR寄存器。

如果BRR寄存器是32bit的存储空间,一般就是低8位存储小数部分,高24位存储整数部分。现版本的HLA库里面,目前采用的就是32bit的存储空间,即uint32_t UART_BRR。

现例如fpclk=80MHz,波特率br=115200,分频div=1(PCLK1到最终频率输出涉过程涉及的分频器),如下图所示

则UARTDIV = 80000000÷(115200*1)=694.44。整数部分直接写入高位部分,694=0X2B6,而小数部分是8个数据位存储的,相当于从整数借1(8bit,最大值是二进制11111111=0XFF)划分为256份,那么小数部分乘256再转16进制就是要填写的小数部分。0.444*256=113.64≈114=0X72。最终合并整数部分和小数部分,向BRR写入数据是0X2B672。

然后按上述配置,在测试调试中,查看串口BRR寄存器数值,也是0X2B672。

2.4 中断寄存器IR

如果开启了中断功能,还会涉及到中断寄存器IR使用,在控制寄存器CR、状态寄存器SR都会与其产生交互。中断寄存器IR又包含中断状态寄存器ISR、中断清除寄存器ICR。收发控制器会依据控制寄存器(CR1、CR2、CR3)配置的信息,诸如发送完成中断TCIE、发送清零中断TXEIE等中断事件与中断寄存器打交道。

下面列出CR寄存器设计中断使能(Interrupt Enable)的配置:TXEIE(发送数据寄存器为空)、TCIE(发送完成)、IDLEIE(空闲线路)、RXNEIE(读取数据已准备或过载)、PEIE(奇偶校验错误)、CMIE(字符匹配)、RTOIE(超时)、EOBIE(块接收结束)、LBDIE(断路)、CTSIE(CTS标记)、WUFIE(唤醒)、EIE(各异常)等。

2.5 其他寄存器

UART串口通信还包含预分频寄存器、接收超时寄存器、请求寄存器等,在HLA库中体现为约定数据位宽度大小的存储区域。

/*** @brief Universal Synchronous Asynchronous Receiver Transmitter*/typedef struct
{__IO uint32_t CR1;         /*!< USART Control register 1,                 Address offset: 0x00 */__IO uint32_t CR2;         /*!< USART Control register 2,                 Address offset: 0x04 */__IO uint32_t CR3;         /*!< USART Control register 3,                 Address offset: 0x08 */__IO uint32_t BRR;         /*!< USART Baud rate register,                 Address offset: 0x0C */__IO uint16_t GTPR;        /*!< USART Guard time and prescaler register,  Address offset: 0x10 */uint16_t  RESERVED2;       /*!< Reserved, 0x12                                                 */__IO uint32_t RTOR;        /*!< USART Receiver Time Out register,         Address offset: 0x14 */__IO uint16_t RQR;         /*!< USART Request register,                   Address offset: 0x18 */uint16_t  RESERVED3;       /*!< Reserved, 0x1A                                                 */__IO uint32_t ISR;         /*!< USART Interrupt and status register,      Address offset: 0x1C */__IO uint32_t ICR;         /*!< USART Interrupt flag Clear register,      Address offset: 0x20 */__IO uint16_t RDR;         /*!< USART Receive Data register,              Address offset: 0x24 */uint16_t  RESERVED4;       /*!< Reserved, 0x26                                                 */__IO uint16_t TDR;         /*!< USART Transmit Data register,             Address offset: 0x28 */uint16_t  RESERVED5;       /*!< Reserved, 0x2A                                                 */
} USART_TypeDef;

三、UART配置及HAL实现

3.1 UART配置梳理

在cubeMX中配置UART主要就是在模式下拉框中开启相关模式,进行串行通信一般就是选择异步模式,其他模式针对特定场景使用。

可以根据需要开启RS232流控制支出或RS485流控制支持,主要就是针对STM32板与RS232或RS485做连接并配合外设设备开启硬件流控时使用。

针对UART的参数设置,主要就是设置串行通信的波特率、数据长度、校验位、停止位。如前面叙述的波特率和时钟频率计算出除法因子存储在BRR寄存器内。校验位、停止位的配置最终体现在控制寄存器CR中,数据长度同样也最终体现到控制寄存器CR中USART_CR1_M/M0。

3.2 UART初始化梳理

cubeMX生成输出代码时,如果配置了给外设生成独立的.h/.c源文件时,串口外设的源码头文件及源文件分别在Core的Inc和Src目录下,输出代码usart.c会为每个独立的串口外设生成初始化函数,将在cubeMX配置的串口参数写入到串口参数变量中,并调用HLA串口初始化函数HAL_UART_Init。如果不配置给外设生成独立的.h/.c源文件时,HAL_UART_Init一般生成在main.c源文件中。

注:HLA有4个UART相关初始化函数,HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()。分别对应UART asynchronous、UART Half duplex、UART LIN mode、 UART multiprocessor 模式,就是前面模式下拉框配置的模式。

在HAL_UART_Init函数中主要实现三个主要功能,底层硬件初始化,配置一般参数、配置高级参数。底层硬件初始化就是调用HAL_UART_MspInit实现引脚配置、时钟设置、中断等相关功能,HAL_UART_MspInit在HLA库中默认是弱函数,CubeMX会根据界面配置生成真正HAL_UART_MspInit函数覆盖原来的函数,同样放置在usart.c源码文件中。

配置一般参数UART_SetConfig、配置高级参数UART_AdvFeatureConfig则会将前面已经设置到串口参数里的变量进一步写入到各个寄存器中,并进行合理校验。其实HLA串口通信最终还是通过操作寄存器实现的,只是HLA库帮助开发者屏蔽调对串口相关寄存器的操作,只要调用上层HLA-API就可以。UART_SetConfig实现了对波特率、校验位、停止位以及其他参数等设置,该函数很大,更多细节请查看HLA源码阅读。

UART_AdvFeatureConfig实现了对串口高级特征设置,在CubeMX上配置的高级特征都能在该函数得到体现。

3.3 UART收发数据源码梳理

UART的HLA库的发送数据和接收数据的API分别是HAL_UART_Transmit*和HAL_UART_Receive*,以HAL_UART_Transmit_IT为例,先将需要发送的数据写入到串口的缓存中,就是相当于前面所述的从MCU或系统总线到发送数据存BUFF区域。

然后通过判定数据长度参数来调用不同注册函数,将上面存储在串口缓存区域的数据转移到发送数据寄存器TDR中。

数据从串口缓存区域到发送寄存器TDR,并会在数据转移完成后关闭TXEIE使能(发送数据寄存器为空数据位)和开启TCIE使能(发送完成中断数据位):

硬件层面上,串口的收发控制器会根据寄存器各个数据位数值变更作出数据发送、数据接收以及控制寄存器CR上各个数据位设值动作,实现从软数据到硬电平的转换及发送。

而在数据接收方面,类似发送机制,首选调用HAL_UART_Receive*函数开启,类似注册及等待回调。程序主要是判定到CR寄存器上接收数据相关的数据位变更,从而调用接收数据的回调函数开启接收,实现由接收数据寄存器RDR到串口缓冲区域,再进而触发用户实现串口回调函数调用及存储数据到用户定义缓存的过程。

cubeIDE开发, UART的CubeMX及HAL库实现原理及底层分析相关推荐

  1. stm32 IOT_基于STM32平台的cubeMX和HAL库详解

    课程简介: <朱有鹏老师单片机完全学习系列课程>总共5季,其中第1.2季是51单片机学习,第3.4.5季是STM32单片机与RTOS学习.整个课程时长约250小时,是一套零基础.全面系统. ...

  2. STM32F103以SPI 驱动128*128的TFT彩屏,LCD驱动为ST7735s,程序使用CubeMX的HAL库开发方式,另外也做了标准库的程序移植

    0.  关于本文: 其实我一直都比较懒,不喜欢写博客.但网上关于详细讲解SPI驱动LCD的文章比较少,虽然也能下载到一些案例程序,但对于初学者来说,如果不懂LCD驱动的原理,不懂如何对文字和图片取模, ...

  3. Cubemx与HAL库系列教程|系统时钟配置详解及源码分析

    STM32时钟系统简介 STM32种类繁多,时钟系统也不尽相同,但基本的还是大差不差,今日小飞哥就F1系列的MCU简单聊一聊STM32的时钟系统 1.时钟种类介绍: 先来看一看时钟树图,包含了整个系统 ...

  4. STM32F103C8T6 0.96寸 OLED显示屏 IIC(CubeMx生成 HAL库)

    STM32F103C8T6 0.96寸 OLED显示屏 IIC(CubeMx生成 HAL库 文章目录 STM32F103C8T6 0.96寸 OLED显示屏 IIC(CubeMx生成 HAL库 一.O ...

  5. uart串口通信_听说UART与STM32的HAL库更配哦

    摘要:HAL库(Hardware Abstraction Layer)是目前意法半导体公司主推的单片机开发方式,可以大大节省开发时间,实践来看,还是比较好用的.本文通过一个简单的UART收发程序,演示 ...

  6. STM32在CubeMX下HAl库编程MISO为何设置和MOSI相同

    首先看一下库函数编程下我们的操作: GPIO_Port.GPIO_Mode = GPIO_Mode_IN_FLOATING;//模式GPIO_Port.GPIO_Pin = GPIO_Pin_6; / ...

  7. STM32串口通信原理及HAL库代码stm32f1xx_hal_uart.c阅读分析

    原理性说明: //参考网址:https://blog.csdn.net/u010561799/article/details/89526266 在USART的发送端有2个寄存器,一个是程序可以看到的U ...

  8. 大疆开发板A型基于HAL库驱动M3508直流无刷电机及PID控制

    1.首先,我们先了解一下大疆开发板A型的资料,官方有提供 官网:RoboMaster 机甲大师赛 芯片型号STM32F427IIH6 2.了解M3508直流无刷电机的资料,官网有提供  3.于是我找到 ...

  9. STM32H750VBT6驱动程控增益放大模块PGA113——基于CubeMX的Hal库

    前言 高情已逐晓云空,不与梨花同梦. 最近,因为准备电赛的需要,需要用到程控增益放大模块(PGA113),也就是这篇博文的主角:破哥啊(谐音称呼),需要调通这位大哥,今天终于完成了驱动的程序代码.说起 ...

最新文章

  1. Java反射详细介绍
  2. Myeclipse 10 利用工具生成网络服务接口并调用
  3. 项目总结——机房收费系统合作版
  4. sql中count(0),count(1),count(),count(列名)
  5. 【Java】京东面试:说说MySQL的架构体系
  6. ffmpeg 推流同时录像命令_ffmpeg推流命令
  7. VS 2013 Chrome PPAPI 开发环境
  8. 从开发者到讲师的心路历程与必知必会 | 原力计划
  9. asp.net 获取IP地理位置的几个主要接口
  10. 小甲鱼python课后习题及答案
  11. 吊打面试官了解一下?2021年字节跳动春招面试题详解(附详细答案)
  12. OpenStack 虚机异常断电处理
  13. html5 自动刷新,javascript – 每5分钟自动刷新一次
  14. 运行jar包时报错:[mybatis-config.xml] cannot be opened because it does not exist
  15. 软件项目技术路线图_创建基本的项目路线图
  16. Windows Server 做CA给Centos 颁发证书
  17. 感恩节,《2012》,尖叫
  18. 苹果新贵 Swift 之前世今生
  19. 分解质因数分 (10分)
  20. 关于esxi6.5开启虚拟机提示文件被锁定,无法开机

热门文章

  1. 大象装企营销:16个月,血亏300万,投资人撤资,公司倒闭
  2. Kerberos双跳变通办法
  3. Git提交记住用户名和密码
  4. MySQL vs MariaDB
  5. iOS底层基础知识-文件目录结构
  6. C语言中的char用法
  7. O2O优惠券数据分析(一)
  8. python time模块以秒计时保留两位小数,格式化时间戳
  9. 高性能计算--HPCC--他人评述
  10. SAP英语专栏:第1篇