STM32 HAL UART 框架初体验

简介: STM32开发平台,时至今日发展的已经相当成熟了,尤其对于外围硬件接口的抽象封装库,即HAL。好多基于STM32开发的工程师,习惯于直接操作外围接口相关的寄存器来完成所谓的驱动开发,其实,ST公司早就为大家准备好了对于这些外围接口的驱动框架,我们只需要直接拿来就可以使用。

背景


STM32开发平台,时至今日发展的已经相当成熟了,尤其对于外围硬件接口的抽象封装库,即HAL。好多基于STM32开发的工程师,习惯于直接操作外围接口相关的寄存器来完成所谓的驱动开发,其实,ST公司早就为大家准备好了对于这些外围接口的驱动框架,我们只需要直接拿来就可以使用。


可是以前,基于STM32平台开发时,存在一个问题就是,变换MCU型号时,需要在新老MCU之间移植驱动程序,移植过程中可能出现很多莫名其妙的问题,导致浪费了很多宝贵的开发时间,如何避免这种问题呢?其实,ST早就为大家考虑到了这一点,其开发了STM32CubeMX工具,基于该工具,我们可以轻松的完成各种外围接口的配置工作,而且最为神奇的就是,配置完成之后,该工具会自动生成工程代码,我们基于此,就可以直接进行开发了,免去了很多不必要的硬件寄存器配置工作。当然,对于特殊需求,我们还是需要去手动配置一些硬件寄存器,但是,这项工作大部分时间是不需要的。


既然,ST公司为我们提供了这么好用的工具,我们为什么不用起来呢?下面就基于UART的配置过程,来逐步的讲解一下,如何基于STM32CubeMX、Kiel和STM32 HAL来配置生成一个可用的开发环境。


开发步骤


配置环境


工欲善其事,必先利其器。首先第一步就是安装STM32CubeMX环境,关于STM32CubeMX环境的安装,网上有好多写的特别棒的文中,这里引用一篇ybhuangfugui的博客,在此感谢ybhuangfugui的无私贡献。大家可以阅读该文章完成STM32CubeMX环境的安装。


在这里说一句,STM32CubeMX提供所有STM32家族的MCU芯片的初始配置抽象,并提供了HAL,封装、抽象了关于底层硬件的配置、使用过程,这是一把双刃剑,有利有弊:利是它增强了STM32不同MCU之间的兼容性,大大加快了初始开发进度,其提供的HAL为开发者提供了统一的开发接口,这样节省了宝贵开发时间。同时,基于其提供的配套的中间件(RTOS、TCP/IP、FS等),开发者可以快速的完成更高级需求的环境定制,这对于开发者来说是不小的福音;弊是,STM32 MCU毕竟是比较低级的硬件开发平台,其开发过程中涉及到大量的底层硬件操作,如果我们想彻底理解这些基础的硬件操作原理的话,可能还是需要从最为原始的硬件寄存器配置开始。


不过,个人感觉STM32CubeMX利大于弊,就像通用操作系统,其屏蔽了所有的硬件相关的操作,为开发者抽象出了进程、内存管理、文件系统、网络等等,易于开发、理解的开发接口,也是正是操作系统的逐步成熟,才最终促使了后来的计算机一次又一次的革命。我想,对于MCU来说,其过程是类似的。如今,已经进入了物联网时代,各种各样的的硬件开发平台层出不穷,各种层次的开发者都涌入到了这一开发领域。试想对于一个原来从事于Web开发的人员来说,其不可能从头去理解底层的硬件知识,其需要的就是一个快速、高效的配置工具,完成原始开发环境的搭建。这时,STM32CubeMX就可以提供很大的帮助。


相信,STM32CubeMX未来肯定会发展的更为智能,任何一个有志于基于该平台开发的开发者,都会被其强度的功能所折服的,零基础的开发人员也能够快速上手该平台。我想,这可能也是STM32CubeMX未来的目标吧。


最后说明一下,本文所使用的STM32CubeMX的版本是:5.5.0。温馨提示,不同版本的操作步骤也能不太一样,所以建议使用相同的版本进行配置。


开始配置


首先,我们需要确定我们所使用的STM32的MCU具体型号,然后,打开STM32CubeMX,创建一个新的工程。


网络异常,图片无法展示
|


我们选择第一个“ACCESSTO MCU SELECTOR”,开始创建一个工程。我们选择的MCU是STM32L010K8,安装如下图的步骤创建工程。


网络异常,图片无法展示
|


  1. 选择MCU型号


  1. 查看MCU型号信息


  1. 创建项目


然后,选择Project Manager项目,配置本项目的一些信息。


网络异常,图片无法展示
|


接下来,我们进行Pinout & Configuration配置,这里面会涉及到MCU提供的所有外围硬件的相关配置。本文主要关注的是UART的配置过程,STM32L010K8提供一个UART2和LPUART,我们选择的配置项为UART2。


UART2的基本配置步骤如下,


网络异常,图片无法展示
|


  1. 选择UART2配置项。


  1. 选择UART2的工作模式,这里选择的是Asynchronous。


  1. 配置UART2的参数,参数分为Basic Parameters、Advanced Paramters、Advanced Features几类。


  • 基本参数配置就是波特率、字长、校验方式、停止位;
  • 高级参数配置就是数据传输方向、采集相关的配置;
  • 高级特性配置:就是UART2提供的一些比较高级的功能,比如,自适应波特率、Overrun等。


我们选择UART2的中断方式处理数据的传输模式,所以,需要进一步配置NVIC。配置步骤如下:


网络异常,图片无法展示
|


  1. 点击System Core中的NVIC配置。


  1. 使能USART2中断,并配置中断抢占优先级为0。


还有就是需要确定UART2使用GPIO引脚,配置方式如下:


网络异常,图片无法展示
|


这里使用的是PA2和PA3。


最后,配置SysClock,我们最终选择的系统主时钟频率为16MHz。


网络异常,图片无法展示
|


完成上述配置之后,点击GENERATE CODE完成项目代码的生成。


网络异常,图片无法展示
|


HAL


项目代码生成之后,我们使用Kiel打开,如下图:

网络异常,图片无法展示
|


下面是main中的芯片初始化代码:


int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}


我们看到,STM32CubeMX自动生成了关于HAL、系统时钟、UART2的初始化代码。下面看一下UART2的初始化代码:


static void MX_USART2_UART_Init(void)
{
  /* USER CODE BEGIN USART2_Init 0 */
  /* USER CODE END USART2_Init 0 */
  /* USER CODE BEGIN USART2_Init 1 */
  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
  /* USER CODE END USART2_Init 2 */
}


stm32l0xx_it.c中定义了UART2的中断处理函数,代码如下:


void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  /* USER CODE END USART2_IRQn 1 */
}


该中断处理函数用来处理所有与UART2相关的中断事件。那如何才能开启UART2的数据发送和接收呢?这就需要HAL中关于UART2数据发送接收的接口函数:


HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);


当我们需要已中断的方式接收数据时,就调用HAL_UART_Receive_IT函数,其中第一个参数是UART的描述符,pData保存数据的缓存区,Size是缓存区的大小。注意,调用完该接口之后,UART2开始已中断的方式接收数据,数据的大小为Size,当接收了Size个字节的数据之后,UART2就不会再接收数据。若想再次接收数据,需要再一次调用HAL_UART_Receive_IT函数。一个比较好的实现就是,在重新覆盖实现下面的函数,


`__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)`


该函数会在数据接收完之后被调用,然后我们在函数中,可以将数据拷贝走,然后再次调用HAL_UART_Receive_IT。


对于数据的发送,处理过程与接收类似,所不同的就是发送的接口函数为:

HAL_UART_Transmit_IT,该发送完成之后的回调函数是:


__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)


好了,至此我们基本完成了基于STM32CubeMX的UART的配置过程,可以看到基于此种方式,我们基本上不会触碰到硬件寄存器的配置过程,所要做的就是基于HAL框架提供的接口完成APP的开发。这也许就是STM32CubeMX的魅力所在吧,简单,高效,可移植性强。 UART_TxCpltCallback(UART_HandleTypeDef *huart)


好了,至此我们基本完成了基于STM32CubeMX的UART的配置过程,可以看到基于此种方式,我们基本上不会触碰到硬件寄存器的配置过程,所要做的就是基于HAL框架提供的接口完成APP的开发。这也许就是STM32CubeMX的魅力所在吧,简单,高效,可移植性强。



相关文章
|
5月前
【STM32】基于HAL库的360度编码器、摇杆代码编写
【STM32】基于HAL库的360度编码器、摇杆代码编写
|
5月前
|
传感器 算法
【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪
【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪
195 0
|
3月前
stm32f407探索者开发板(十六)——串行通信原理讲解-UART
stm32f407探索者开发板(十六)——串行通信原理讲解-UART
140 0
|
4月前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
418 2
|
4月前
|
开发者
【经典案例】使用HAL库配置STM32F407的SPI外设
在嵌入式系统开发中,STM32F407是一款广泛应用的微控制器,而SPI(Serial Peripheral Interface)是一种常用的通信接口。本文将详细介绍如何使用STM32的硬件抽象层(HAL)库配置STM32F407的SPI外设,并提供完整的代码示例。
306 1
|
3月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
104 0
|
5月前
|
缓存 网络协议 算法
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
|
5月前
|
存储 传感器
【STM32基础 CubeMX】uart串口通信
【STM32基础 CubeMX】uart串口通信
302 0
|
存储 芯片 内存技术
STM32F0单片机快速入门十 用 SPI HAL 库读写W25Q128
STM32F0单片机快速入门十 用 SPI HAL 库读写W25Q128
STM32F0单片机快速入门七 串口(UART)操作从轮询到中断
STM32F0单片机快速入门七 串口(UART)操作从轮询到中断
STM32F0单片机快速入门七 串口(UART)操作从轮询到中断