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

news/2024/5/19 15:28:38/文章来源:https://blog.csdn.net/py8105/article/details/128434109

一、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.luyixian.cn/news_show_240022.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

stm32f407VET6 系统学习 day04 DHT11 温湿度传感器

1.温湿度的一次完整的数据包括&#xff1a; 一次完整的数据传输为40bit,高位先出。 数据格式: 8bit湿度整数数据 8bit湿度小数数据 8bi温度整数数据 8bit温度小数数据 8bit校验&#xff08;校验和的值是前四个字节数据的和) 用户MCU发送一次开始信号后,DHT11从低功耗模式转…

UDP协议在Windows上使用示例

UDP(User Datagram Protocol&#xff0c;用户数据报协议)是无连接的&#xff0c;因此在两个进程通信前没有握手过程。UDP协议提供一种不可靠数据传送服务&#xff0c;也就是说&#xff0c;当进程将一个报文发送进UDP套接字时&#xff0c;UDP协议并不保证该报文将到达接收进程。…

为什么要使用 Compose 来开发 Android ?

1. Compose诞生背景 近年来&#xff0c;以React为代表的声明式UI开发思想席卷了整个前端开发领域。客户端与前端在产品形态上非常相似&#xff0c;也希望借鉴这种全新的开发思想来提升客户端UI的开发效率和体验。在这个大背景下&#xff0c;Android与iOS平台相继发布了自己的声…

node.js+uni计算机毕设项目互联网教育系统小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

Attetion is all you need论文阅读笔记

Attetion is all you need 参考&#xff1a;沐神&#xff08; 沐神_论文精讲_Attention is all you need&#xff09; 1、Abstract 主流的序列转录模型&#xff08;给一个序列生成另一个序列&#xff0c;比如机器翻译&#xff0c;给一句英文&#xff0c;生成一句中文&#x…

Biotin-PEG-MAL,Maleimide-PEG-Biotin,生物素聚乙二醇马来酰亚胺

英文名称&#xff1a;Biotin-PEG-MAL&#xff0c;Maleimide-PEG-Biotin 中文名称&#xff1a;生物素聚乙二醇马来酰亚胺 Biotin-PEG-Mal&#xff0c;聚乙二醇化生物素对亲和素或链霉亲和素有很高的亲和力。生物素/亲和素体系在生物分子检测和分离中有着广泛的应用。马来酰亚胺…

【状态估计】电力系统状态估计中的异常检测与分类(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

LeetCode 1739. 放置盒子:数学 思维

【LetMeFly】1739.放置盒子 力扣题目链接&#xff1a;https://leetcode.cn/problems/building-boxes/ 有一个立方体房间&#xff0c;其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子&#xff0c;每个盒子都是一个单位边长的立方体。放置规则如下&#xff1a; …

408 考研《操作系统》第三章第二节:基本分页存储管理、两级页表、基本分段存储管理方式、段页式管理方式

文章目录教程1. 基本分页存储管理的基本概念1.1 连续分配方式的缺点1.2 把“固定分区分配”改造为“非连续分配版本”1.3 什么是分页存储1.4 如何实现地址的转换&#xff1f;1.5 逻辑地址结构1.6 重要的数据结构——页表1.7 知识回顾与重要考点2. 基本地址变换机构2.1 例题2.2 …

单链表的头插法与尾插法

一、基本概念 二、头叉法 该方法从一个空链表开始&#xff0c;生成新结点&#xff0c;并将读取到的数据存放到新结点的数据域中&#xff0c;然后将新结点插入到当前链表的表头。采用头插法创建单链表时&#xff0c;读入数据的顺序与生成单链表的元素顺序是相反的。 LinkList L…

JavaScript操作BOM对象

BOM&#xff1a;浏览器对象模型 window代表浏览器窗口 >window.alert(1) undefined >window.innerHeight //浏览器内部高度 242 >window.innerWidth 1229 >window.outerHeight //浏览器外部高度 824 >window.outerWidth 1536 Navigator&#xff0c;封装了浏…

Kafka消息写入流程

Kafka消息写入流程 0,写入消息简要流程图 1,从示例开始 在Kafka中,Producer实例是线程安全的,通常一个Producer的进程只需要生成一个Producer实例. 这样比一个进程中生成多个Producer实例的效率反而会更高. 在Producer的配置中,可以配置Producer的每个batch的内存缓冲区的大小…

DAY5 Recommended system cold startup problem

推荐系统的冷启动问题 推荐系统冷启动概念 ⽤户冷启动&#xff1a;如何为新⽤户做个性化推荐物品冷启动&#xff1a;如何将新物品推荐给⽤户&#xff08;协同过滤&#xff09;系统冷启动&#xff1a;⽤户冷启动物品冷启动本质是推荐系统依赖历史数据&#xff0c;没有历史数据⽆…

【工作流Activiti7】6、Activiti 7 源码学习

1. 启动分析 源码版本是 7.1.0.M6 首先从 ProcessEngineAutoConfiguration 开始 ProcessEngineAutoConfiguration 是activiti-spring-boot-starter 7.1.0.M6自动配置的入口类&#xff0c;在这里主要看 SpringProcessEngineConfiguration 主要是配置了自动部署 最最最重要的…

Linux网络编程之epoll多路转接服务器

Linux网络编程之epoll多路转接服务器 一、epoll的基本概念 epoll是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率&#xff0c;因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待…

算法 | 如何通过Math.random()方法实现X平方或更多次方的概率?

前言 本文主要介绍Java中Math.random()方法以及该方法的简单应用。 每种语言都有随机方法&#xff0c;在Java中的随机方法有Math.random()方法、Random类。 Math.random Math.random()方法的返回值的是double类型&#xff0c;其返回值的范围为[0,1)&#xff0c;包含0&#…

KOOM线上APM监控最全剖析

APM&#xff0c;全称是Application Performance Management&#xff0c;也就是应用性能管理&#xff0c;这与我们平时写的业务可能并不相关&#xff0c;但是却承载着App线上稳定的责任。当一款App发布到线上之后&#xff0c;不同的用户有不同场景&#xff0c;一旦App出现了问题…

【nowcoder】笔试强训Day7

目录 一、选择题 二、编程题 2.1Fibonacci数列 2.2合法括号序列判断 一、选择题 1.JAVA属于&#xff08; &#xff09;。 A 操作系统 B 办公软件 C 数据库系统 D 计算机语言 计算机软件主要分为系统软件与应用软件两大类。系统软件主要包括操作系统、语言处理系统、数…

【Redis场景2】缓存更新策略(双写一致)

在业务初始阶段&#xff0c;流量很少的情况下&#xff0c;通过直接操作数据是可行的操作&#xff0c;但是随着业务量的增长&#xff0c;用户的访问量也随之增加&#xff0c;在该阶段自然需要使用一些手段(缓存)来减轻数据库的压力&#xff1b;所谓遇事不决&#xff0c;那就加一…

设计模式之结构型模式:适配器模式

前言 前面讲解完了设计模式中的创建性模式&#xff0c;本文开始讲解设计模式中的结构性模式之一&#xff1a;适配器模式。 一、适配器模式的是干什么的&#xff1f; A类想要使用B类中的某些方法&#xff0c;但是不能直接使用&#xff0c;需要一个中间类对B类进行处理后&…