STM32串口初始化与使用详解(基于HAL库编程)

本文详细介绍了STM32单片机中串口的基本概念、初始化步骤和使用方法,包括同步/异步模式的选择、串口初始化函数、MSP层的初始化以及串口收发函数的原理和应用。通过实例展示了如何使用HAL库进行串口配置,重点解析了HAL_UART_Init()函数的工作逻辑,并对比了阻塞和非阻塞发送模式的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

串口简介

USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收发送器
即串口。是一个高度灵活的收发模块,它可以做到与上位机,或者其他MCU进行通信,实现上位机,其他MCU间的相互控制

STM32单片机芯片内部集成了多个串口。

一般而言,我们使用串口都使用异步收发模式。同步收发模式在外设和代码上的处理较为复杂,而且对时钟的要求严格,MCU的频率较PC频率低得多,所以没很大的必要使用同步模式。而同步通信的目的就是为了加快通信速率,但在使用上有些不尽如人意。以我用过的串口模块(外设)来说,基本上都是异步收发的串口模块(外设)。如ESP8266,其他一些蓝牙模块。

以STM32F4为例,该芯片集成了4个同步异步串口(USART1,USART2,USART3,USART6),2个异步串口(UART4,UART5),同步异步串口可以初始化为同步模式,也可以初始化为异步模式,而异步串口仅能初始化为异步模式。

若要将同步异步串口初始化为同步模式,则调用同步模式的串口初始化函数,否则调用异步模式串口初始化函数来初始化串口。

串口初始化具体步骤

这里我们先介绍初始化串口要用到的函数

相关HAL库函数 具体功能
HAL_UART_Init 顾名思义,异步串口初始化函数,初始化串口时我们调用的函数。所在源文件:stm32f4xx_hal_uart.c
HAL_UART_DeInit 取消对某异步串口的初始化
HAL_UART_MspInit 串口MSP初始化
HAL_UART_MspDeInit 取消MSP初始化

这是MSP初始化函数的声明,可以发现,在void关键字之前有一个weak关键字

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)

这个关键字告诉编译器,这个定义是弱定义,若在编译时,有一处函数定义不含此关键字,则所有该函数的调用都指向那一个非weak型的函数定义。这个操作叫函数重定向。因为在系统头文件里,MSP层是没有声明的,MSP层是具体对应每一个MCU的物理状态,系统文件不会声明也不能声明,但在单片机做上电初始化时,有一些函数又必须调用,所以系统文件采取了这种用户可以重定向的写法。我们在初始化串口时,需要自己写一个MSPInit,而且不含weak。函数声明如下:

	void HAL_UART_MspInit(UART_HandleTypeDef *huart)

我们要初始化串口,就要定义一个属于自己的MSP函数,并且系统会自动的把所有的MSP调用都指向我们定义的这个MSP函数

以下为系统定义的MSP函数,可见,内部几乎没什么内容,唯一一个函数调用是使该串口变为UNUSED(不使用)

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
   
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_MspInit could be implemented in the user file
   */
}

取消MSP使能函数的声明如下,可见在内部代码中的该函数也为弱定义,内部代码也十分简单,此处不做赘述

__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)

具体初始化过程(以CUBEMX生成的空项目为例):

使用串口第一步。添加串口同步异步源文件到项目中。(stm32f4xx_hal_usart.c,stm32f4xx_hal_uart.c)若只使用异步模式,应该不需要添加同步异步模式的头文件进入项目,但一方面是为了方便,一方面是为了少出一点事情,还是将它加进项目吧)
点击箭头指向的品字型

点击stm32f4xx_HAL_Driver
点击Add Files
点击Add Files
返回项目文件夹层级,可见有如上几个文件夹。点击Drivers
返回项目文件夹层级,可见有如上几个文件夹。点击Drivers

点击HAL_Driver,下一栏点src,从中找到stm32f4xx_hal_usart.c和stm32f4xx_hal_uart.c,点击Add加入项目。文件即加入了我们的项目

文件加入我们的项目后,我们仅仅引用了源文件,而头文件的引用,进入main.h中,打开stm32f4xx_hal.h,找到stm32f4xx_hal_conf.h

可以发现头文件的模块使能宏定义被注释掉了,把注释去掉即可。
这样一来所有的准备工作都做好了,我们开始着手初始化串口吧

串口初始化函数

void Usart1Init(int baudRate)
{
   
	UART1_Handle.Instance = USART1;							//串口句柄1与串口1对应
	UART1_Handle.Init.BaudRate = baudRate;					//初始化波特率为输入波特率
	UART1_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;		//无硬件控制流
	UART1_Handle.Init.Mode = UART_MODE_TX_RX;				//串口异步收发模式
	UART1_Handle.Init.OverSampling = UART_OVERSAMPLING_16;	//默认过采样16倍
	UART1_Handle.Init.Parity = UART_PARITY_NONE;			//默认无校验位
	UART1_Handle.Init.StopBits = UART_STOPBITS_1;			//默认1位停止位
	UART1_Handle.Init.WordLength = UART_WORDLENGTH_8B;		//8bit数据位
	if (HAL_UART_Init(&UART1_Handle) != HAL_OK)
  {
   
    Error_Handler();
  }
}

其中UART1_Handle为UART_HandleTypeDef类型的结构体
结构体内容如下:

typedef struct __UART_HandleTypeDef
{
   
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */
  UART_InitTypeDef              Init;             /*!< UART communication parameters      */
  uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
  __IO uint16_t                 TxXferCount;      /*!< UART Tx Transfer Counter           */
  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
  __IO uint16_t                 RxXferCount;      /*!< UART Rx Transfer Counter           */
  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */
  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
  HAL_LockTypeDef               Lock;             /*!< Locking object                     */
  __IO HAL_UART_StateTypeDef    gState;           /*!< UART state information related to global Handle management
                                                       and also related to Tx operations.
                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */
  __IO HAL_UART_StateTypeDef    RxState;          /*!< UART state information related to Rx operations.
                                                       This parameter can be a value of @ref HAL_UART_StateTypeDef */

  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
  void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart);        /*!< UART Tx Half Complete Callback        */
  void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart);            /*!< UART Tx Complete Callback             */
  void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart)<
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值