本文分两部分
1.图形操作步骤
2.自动生成代码结构分析
3.自动代码生成的坑

一:使用CubeMX 配STM32H743 串口模块LPUSART
1.使能调试口,以免使用SWD下载需要手动复位
在这里插入图片描述
2.配置 时钟树 ,基础配置。配置480MHz
在这里插入图片描述
3.配置串口模块
在这里插入图片描述
4.配置NVIC中断控制器
在这里插入图片描述
5.串口中断函数
在这里插入图片描述
6.Project 设置
在这里插入图片描述
设置项目名称和路径,IDE
在这里插入图片描述
7.生成代码
在这里插入图片描述

二。HAL库生成代码解析

1.1 main.c
在这里插入图片描述
用户自己增加的代码,必须放在 USER CODE相应的位置,负责再次使用CubeMX的时候会覆盖代码,导致重新添加代码。

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_LPUART1_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 */
	HAL_Delay(2500);
	HAL_UART_Transmit(&hlpuart1, "hello uart 1 \r\n", 13, 888);
  }

主函数包含三个头文件

#include "main.h"
#include "usart.h"
#include "gpio.h"

1.main.h 包含 “stm32h7xx_hal_conf.h” 该文件是HAL库的顶层配置文件。
a.HAL 库外围模块的开启
b.模块内部定义扩展接口的配置
一旦配置自己动包含HAL库模块的头文件,这部分是头文件的汇总。

2.usart.h
主函数中声明串口相关的函数。

3.gpio.h
主函数中关于GPIO的初始化函数声明。

2.1 设备结构体解析
CubeMX自动生成函数解析

UART_HandleTypeDef hlpuart1;

设备结构是HAL库函数的精髓所在

HAL库为模块定义的结构体,类似与面向对象的类,hlpuart1 为实体,实体通过外设访问初始地址完成实体化。
使用的是面向对象的思想。定义一个类,这个类表示串口设备,并定义方法和内部变量。
app通过

在这里插入图片描述

定义类概念的结构体是HAL库相比标准库的改变较大的地方。
应用层和底层之间就进行了解耦合操作。
应用层需要的 模块的句柄,然后调用句柄(实体)的方法

USART_TypeDef *Instance; 对应USART寄存器地址,实体所在。

Tx,RX 回调函数
void (*RxISR)(struct __UART_HandleTypeDef huart); /!< Function pointer on Rx IRQ handler */

void (*TxISR)(struct __UART_HandleTypeDef huart); /!< Function pointer on Tx IRQ handler */

tx rx buffer,数据计数器,数据长度指示器

const 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 */
状态寄存器回调函数

在这里插入图片描述

2.2 初始化函数
MX_LPUART1_UART_Init

串口实体初始化函数部分,常规参数初始化
在这里插入图片描述
HAL_UART_Init
对各种回调函数的指定。也就是函数和设备回调接口的设定。

/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);

GPIO和CLOCK的设定 和硬件具体布局相关,HAL库中并没有相关内容,而是放在usart.c中

2.3 中断处理函数

HAL库中断处理函数

void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */

  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */

  /* USER CODE END LPUART1_IRQn 1 */
}

HAL库的做法是规划好固定的框架,通过执行回调函数来处理中断。
在这里插入图片描述
框架写的非常负责。不过多叙述。

用户调加的代码需要在指定位置 例如
/* USER CODE BEGIN LPUART1_Init 2 */

/* USER CODE END LPUART1_Init 2 */

中断使能需要手动加入

__HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_RXNE);
很奇怪CubeMX 还需要手动的去使能中断。

3.自动代码生成的坑

ISR 函数写的非常复杂,控制起来并不能随心所欲,如果你想实现你的功能建议不使用自动生成的ISR函数。
里面大量的判断和分支,很难维护。毕竟嵌入式代码是深入定制的。

如果发现接收后ISR不会跳转那么很可以是中断没有使能。
如果发现接收一次后就不会在进ISR,那么就是自动生成ISR函数的坑了。

用CubeMX配置后如果发现不能跑起来怎么办,简单暴力的方法去查UART的状态寄存器。
和正常能跑得寄存器做对比,发现CubeMX哪些地方没有配置。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐