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

news2024/11/25 21:31:38

一、UART通信协议

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

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

        【2】串行通信和并行通信区别,串行通信是指设备之间通过一根数据信号线,地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式,同一时刻只能传输一位(bit)数据;并行通讯:是指使用 8 根或更多(2^{n})的数据线进行传输的通讯方式,可以同一时刻传输多个数据位的数据(有多少根线就可以一次传输多少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寄存器设计中断的配置: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。

        注: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到串口缓冲区域,再进而触发用户实现串口回调函数调用及存储数据到用户定义缓存的过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<Linux线程互斥与死锁>——《Linux》

目录 1. Linux线程互斥 进程线程间的互斥相关背景概念 互斥量mutex 互斥量的接口 初始化互斥量 销毁互斥量 互斥量加锁和解锁 互斥量实现原理探究 可重入VS线程安全 概念 常见的线程不安全的情况 常见的线程安全的情况 常见不可重入的情况 常见可重入的情况 可重…

K. Lonely Numbers(线性筛 + 差分)

Problem - 1423K - Codeforces 在数字世界中&#xff0c;如果两个不同的数字有很多共同点&#xff0c;而且每个数字都有独特的好处&#xff0c;那么它们就是朋友。 更确切地说&#xff0c;如果gcd(a,b), agcd(a,b), bgcd(a,b)能组成一个三角形的边&#xff0c;那么两个不同的数…

六、应用层(四)电子邮件

目录 4.1 电子邮件系统的组成结构 4.2 简单邮件传输协议&#xff08;SMTP&#xff09; 4.3 电子邮件格式 4.4 多用途网际邮件扩充&#xff08;MIME&#xff09; 4.5 邮局协议&#xff08;POP3&#xff09;和因特网报文存取协议&#xff08;IMAP&#xff09; 4.6 基…

小黑下午第一场面试被鸽,一切遇见随缘,继续第二场的leetcode之旅:654. 最大二叉树

小黑代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def constructMaximumBinaryTree(self, nums: Li…

SAP UI5 应用里 FlexBox 控件的设计原理

sap.m.FlexBox 控件为 flexible box layout 构建容器。VBox 控件为垂直的框布局(vertical flexible box layout)构建容器。 VBox 是一种使用的控件&#xff0c;因为它只是一个定制化的 FlexBox 控件。 VBox 包含 items 聚合&#xff0c;从 FlexBox 继承而来。 HBox 控件为水平…

字符串函数

注意&#xff1a;MySQL中&#xff0c;字符串的位置是从1开始的。 ASCII(S) 返回字符串S中的第一个字符的ASCII码值. 与第一个字符后面的其他字符无关。 SELECTASCII(Abcdfsf) FROM DUAL;CHAR_LENGTH(s) 返回字符串s的字符数。作用与CHARACTER_LENGTH(s)相同。 SELECTCHAR_LEN…

生信基础知识

1.生物数据库分类 &#xff08;1&#xff09;核酸数据库&#xff08;2&#xff09;蛋白质数据库&#xff08;3&#xff09;专用数据库 核酸数据库分为一级核酸数据库和二级核酸数据库 蛋白质数据库分为一级蛋白质数据库和二级蛋白质数据库 一级蛋白质数据库又分为蛋白质序列…

【Redis】应用问题解决

一、缓存击穿 1、什么叫缓存击穿 系统中某个查询次数很多的热点key&#xff0c;在某个时刻过期&#xff0c;而此时又正好有大量并发请求查询这个key&#xff0c;但是缓存的重建还没有完成&#xff0c;这样&#xff0c;就会有大量请求涌向后端数据库&#xff0c;使得其压力骤增…

爱了,阿里P9开源分享内部Java核心开发手册(2022版)覆盖P5到P8

这个世界唯一不变的就是变化&#xff0c; IT圈子不外如是。计算机领域一直在改变&#xff0c;从基础框架到计算设备&#xff0c;还有几乎每天都涌现出的新技术。因此&#xff0c;作为一名程序开发人员&#xff0c;我们要通过不断的学习来提高自己的技能。 所以持续学习的脚步自…

基于C++11实现的阻塞队列(BlockQueue)

思路&#xff1a; 生产者消费者模型如图&#xff0c;多个生产者线程和多个消费者线程共享同一固定大小的缓冲区&#xff0c;它们的生产和消费符合以下规则&#xff1a; 生产者不会在缓冲区满的时候继续向缓冲区放入数据&#xff0c;而消费者也不会在缓冲区空的时候&#xff0c…

AQS源码解读

retrantlock&#xff1a; A、B、C3个线程&#xff0c;假设A线程lock()时候拿到了锁&#xff0c;state被A设置成了1。 static final class NonfairSync extends Sync {private static final long serialVersionUID 7316153563782823691L;/*** Performs lock. Try immediate b…

喜欢写笔记的博主为什么要使用猿如意?

&#x1f525;&#x1f525;&#x1f525;猿如意&#x1f525;&#x1f525;&#x1f525; 喜欢写笔记的博主为什么要使用猿如意&#xff1f; markdown笔记 测 评 分 享 猿如意实战测评猿如意传送门什么是猿如意&#xff1f;猿如意使用感受markdown笔记实战测评总结猿如意传…

数据结构---红包分配算法

红包分配算法错误解法二倍均值法JAVA实现线段切割法确定每一条子线段的长度JAVA实现问题如下&#xff1a; 所有人抢到的金额之和要等于红包金额&#xff0c;不能多也不能少。每个人至少抢到1分钱。要保证红包拆分的金额尽可能分布均衡&#xff0c;不要出现两极分化太严重的情况…

【C函数】函数详解

函数前言一、函数是什么二、C语言中函数的分类&#xff08;一&#xff09;库函数1.printf类2.strcpy类3.math类4.概念5.小知识6.总结&#xff08;二&#xff09;自定义函数1.概念2.函数的组成3.例子1&#xff08;求出两个数中的最大值&#xff09;4.例子2&#xff08;交换两个整…

mac释放“其他”内存空间的解决方法

官方解释Mac设备储存空间中的“其他”数据包含这不可移除的移动资源&#xff0c;例如&#xff0c;Siri 语音、字体、词典、不可移除的日志和缓存、聚焦索引以及系统数据如钥匙串和 CloudKit 数据库、系统无法删除缓存的文件等之外&#xff0c;还包含了一些无法识别的文件。当“…

ROS2 基础概念 节点

ROS2 基础概念 节点1. Nodes2. 重映射3. 环境设置3.1. ROS_DOMAIN_ID3.2. ROS_LOCALHOST_ONLY1. Nodes 每个节点应负责单个模块用途&#xff08;例如&#xff0c;一个节点用于控制车轮电机&#xff0c;一个用于控制激光测距仪等&#xff09; 可以通过话题、服务、操作或参数向…

C++-----模板

举个例子&#xff0c;如果要你交换两个数值&#xff0c;你会怎么做呢&#xff1f; ————你肯定会说&#xff0c;那就写一个Swap交换函数吧&#xff01; 没错&#xff01;Swap函数确实可以实现交换&#xff0c;但如果我想让你同时进行不能类型的数值呢&#xff0c;比如floa…

F - Permutation Distance(去绝对值数据结构)[AtCoder Beginner Contest 283]

题目如下&#xff1a; 题目链接 题解 or 思路&#xff1a; 去掉绝对值后 有 2242 \times 2 4224 中情况 虚线括起来的是需要维护的&#xff0c;其他直接枚举就行! 对于 pi<pjp_i < p_jpi​<pj​ 的情况&#xff0c;设我们维护的式子为 xxx 那我们每次枚举查找的范围…

hadoop生产调优之HDFS—集群压测

在企业中非常关心每天从 Java 后台拉取过来的数据&#xff0c;需要多久能上传到集群&#xff1f;消费者关心多久能从 HDFS 上拉取需要的数据&#xff1f; 为了搞清楚 HDFS 的读写性能&#xff0c;生产环境上非常需要对集群进行压测。 HDFS 的读写性能主要受网络和磁盘影响比较大…

【matplotlib】3-绘制统计图形

文章目录绘制统计图形1.柱状图1.1 应用场景--定性数据的分布展示1.2 绘制原理2.条形图3.堆积图3.1 堆积柱状图3.2 堆积条形图4.分块图4.1 多数据并列柱状图4.2 多数据平行条形图5.参数探索6.堆积折线图、间断条形图和阶梯图6.1 用函数stackplot()绘制堆积折线图6.2 用函数broke…