串口

串口通信和并行通信

全双工、半双工和单工通信

单工通信:数据只能沿着一个方向传输

半单工通信:数据可以沿着两个反向传输,但需要分时进行

全双工通信:数据可以同时进行双向传输

同步通信和异步通信

同步通信:发送和接收双方按照预定的时钟节拍进行数据发送和接收,双方的操作严格同步。

异步通信:双方不需要按照严格的时钟同步,每个数据块之间通过特定的起始位和停止位进行分隔,接收方可以独立地识别每个数据块。

串口框图基本知识        

        在STM32产品手册518页中有详细的USART框图,对于初学者来说我整理了一个简图来进行学习。

        TX为发送引脚,RX为接收引脚,在收发寄存器中分为发送数据寄存器TDR,接收寄存器RDR。假如我需要发送数据则需要在数据寄存器TDR中写内容,那么TDR会将数据转运到发送一位寄存器中,之后就会将数据一位一位的移到GPIO中,GPIO为TX的复用引脚,就可以发送给其他设备;那么接收数据就是通过GPIO为RX的复用引脚,一位一位发送到接收移位寄存器中,再把数据转运到RDR后,编写程序把数据读取,这就是接收的流程。

        发送、接收移位寄存器都是由发送、接收控制器分别进行控制,而发送、接收控制器受波特率发生器所控制,波特率发生器的时钟频率来源于PCLK2/PCLK1

STM32的USART简介

Universal synchronous asynchronous receiver transmitter,通用同步异步收发器
Universal asynchronous receiver transmitter,通用异步收发器
1.    全双工通信:USART支持全双工通信,即数据可以在两个方向上同时传输(A→B且B→A)。这使得USART能够满足许多需要双向通信的应用场景。
2.    同步与异步传输:尽管USART的“S”代表同步,但在实际应用中,USART更常用于异步通信。然而,它也支持同步通信模式,只是这种模式通常用于兼容其他协议或特殊模式,并且两个USART设备不能通过同步模式进行直接通信。
3.    波特率发生器:USART自带波特率发生器,最高可达4.5Mbits/s,可以根据需要配置不同的波特率。
4.    硬件流控制:USART支持硬件流控制,通过特定的信号线(如RTS/CTS)实现数据的可靠传输。当接收端没有准备好接收数据时,可以通过RTS信号通知发送端暂停发送;当接收端准备好接收数据时,再通过CTS信号通知发送端恢复发送。

USART寄存器描述

状态寄存器(SR

        在10位当中,常用的是TE,RE,TXE,TC,RXNE。
TXE                 代表发送器为空(TDR发送完了)的时候置1;
TC                   代表全部发送完了(TDR和发送移位寄存器)置1;
RXNE              代表RDR寄存器中有数据时置1,你就可以读取RDR的数据;
IDLE                代表数据空闲(数据都收发完毕);
 

数据寄存器(DR)

        一共有9位,若配置中为8位则使用8位数据。
DR[8:0]:数据值 (Data value) 包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用(TDR),一个给接收 用(RDR),该寄存器兼具读和写的功能。

波特比率寄存器

DIV_Mantissa[11:0]USARTDIV的整数部分
12位定义了USART分频器除法因子(USARTDIV)的整数部分。
DIV_Fraction[3:0]USARTDIV的小数部分
4位定义了USART分频器除法因子(USARTDIV)的小数部分。

       如果想要配置115200的波特率需要通过各种各样的配平和DIV_Mantissa、DIV_Fraction配置成所需要的波特率。

控制寄存器1

        重点需要掌握RE、TE、IDLEIE、RXNEIE、TCIE、TXEIE;
TE、RE          就是对应发送、接收器波特率控制;
IDLEIE            若置1代表数据总线空闲会产生一个中断。
RXNEIE          若置1时,RDR寄存器有数据来就产生中断;
TCIE                是如果数据都发送完,置1就会产生中断;

TXEIE:发送缓冲区空中断使能 (TXE interrupt enable)
该位由软件设置或清除。
0:禁止产生中断;1:当USART_SR中的TXE为’1’时,产生USART中断。

控制寄存器2     

        主要关注STOP
STOP:停止位 (STOP bits)
2位用来设置停止位的位数
001个停止位;(常用)
010.5个停止位;
102个停止位;
111.5个停止位;
注:UART4UART5不能用0.5停止位和1.5停止位。

控制寄存器3

主要关注HDSEL
HDSEL:半双工选择 (Half-duplex selection)
选择单线半双工模式
0:不选择半双工模式;
1:选择半双工模式。

串口常见的库函数

       分为同步和异步 我们目前使用UART异步的使用。在stm32f1xx_hal_uart.c下的HAL_UART_Init()函数:

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)

        我们在这个句柄(UART_HandleTypeDef)跳转其定义查看,重点是有Instance这个实例,STM32芯片内部有多个相同类型的外设(比如3个串口:USART1、USART2、USART3)。Instance的作用就是告诉程序:"我现在要操作的是哪一个具体的串口"。

typedef struct __UART_HandleTypeDef
{
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */

  UART_InitTypeDef              Init;             /*!< UART communication parameters      */

  const uint8_t                 *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */

  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
...

        还有一个初始化的结构体,我们点 UART_InitTypeDef 查看定义,里面包含了我们的波特率(BaudRate)、字长、停止位、校验位、工作模式和剩下两目前还没有接触到,可以通过Init函数进行配置。

typedef struct
{
  uint32_t BaudRate;                  /*!< This member configures the UART communication baud rate.
                                           The baud rate is computed using the following formula:
                                           - IntegerDivider = ((PCLKx) / (16 * (huart->Init.BaudRate)))
                                           - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 16) + 0.5 */

  uint32_t WordLength;                /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref UART_Word_Length */

  uint32_t StopBits;                  /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref UART_Stop_Bits */

  uint32_t Parity;                    /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref UART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */

  uint32_t Mode;                      /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref UART_Mode */

  uint32_t HwFlowCtl;                 /*!< Specifies whether the hardware flow control mode is enabled or disabled.
                                           This parameter can be a value of @ref UART_Hardware_Flow_Control */

  uint32_t OverSampling;              /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).
                                           This parameter can be a value of @ref UART_Over_Sampling. This feature is only available
                                           on STM32F100xx family, so OverSampling parameter should always be set to 16. */
} UART_InitTypeDef;

        在stm32f1xx_hal_uart.c下的HAL_UART_MspInit()函数,有Init肯定有MSP的函数,因为 HAL_UART_Init():只处理与芯片型号无关的通用配置
(设置波特率、数据位等通信参数),这些参数对所有STM32芯片的USART都适用。

HAL_UART_MspInit():处理与芯片型号相关的硬件操作(初始化GPIO、时钟、中断)
(比如PA9是USART1_TX引脚,但在不同STM32型号上可能不同)。

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)

 在stm32f1xx_hal_uart.c下的HAL_UART_Transmit()发送函数和HAL_UART_Receive()接收函数

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

 在stm32f1xx_hal_uart.c下的HAL_UART_Transmit_IT()中断发送函数,HAL_UART_Receive_IT()中断接收函数,在众多的回调函数中,最常用的是接收完成函数HAL_UART_RxCpltCallback(),就是数据全部接收完成之后会调用这个回调函数。

//中断发送函数
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

//中断接收函数
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

//数据接收完成回调函数
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)

        总结:本文介绍了STM32 HAL库串口的基本使用方法,包括初始化配置、中断处理和数据收发。希望通过这篇笔记能帮你快速上手串口通信。如果有疑问或发现错误,欢迎在评论区留言讨论!

📜 下一篇预告
本文将介绍《STM32串口一个字符收发》,教你如何用串口实现简单数据收发,把知识点体现在实际的操作上,能更加有趣的稳固知识噢,点击关注不迷路~

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐