前言
本文主要介绍 串口实验 的通过STM32CUBE形式和直接编程模式的不同。
本文可以参考博客<STM32F429第十四篇之串口实验详解>。
两种方式实验的效果完全相同:
- 在程序启动时,会发送信息 hello,zhy!
- 在程序运行时,LED等闪烁。
- 向串口1 发送数据,其会返回相同的数据。
该实验源代码下载https://github.com/zhenhaiyang/STM32CUBE
本文主要参考资料:
- 正点原子.STM32F429开发指南-HAL库版本_V1.1
STM32CUBE配置
关于LED灯的配置部分,可以参考博客<STM32CubeMX第二篇之跑马灯>。本文不再重复介绍。
配置串口
- 配置Pinout。本实验使用的是PA9和PA10。首先配置为串口功能,如下图所示:
- 配置configuration。在此处经常需要配置GPIO,NVIC,RCC,USART等。本例程主要演示USART,如下所示:
配置串口的参数。
配置串口的中断
配置串口的GPIO
配置完成后,点击确定。
最后,可以按照之前博客<STM32CubeMX第二篇之跑马灯>中介绍的方法生成代码。此处不再介绍。
代码分析与修改
1. 添加代码
添加三部分代码:
- 对列相关
- 延时相关
- 系统相关

其中,前两个部分与博客<STM32F429第十五篇之串口实验详解二>中介绍的完全相同。因为系统初始化还有串口部分都可以自动生成,所以,对系统相关的文件需要修改如下:
头文件与上述博客内容也是一致,如上所示:
/**
******************************************************************************
* @file sys.h
* @author zhy
* @version 1.0
* @date 2021-01-22
* @brief 系统初始化相关的头文件
******************************************************************************
*/
#ifndef _SYS_H
#define _SYS_H
#include
/* 位带操作 */
typedef struct
{
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
unsigned int bit9 : 1;
unsigned int bit10 : 1;
unsigned int bit11 : 1;
unsigned int bit12 : 1;
unsigned int bit13 : 1;
unsigned int bit14 : 1;
unsigned int bit15 : 1;
unsigned int rsv : 16;
} BitBand __attribute__((bitband));
extern BitBand PAin;
extern BitBand PBin;
extern BitBand PCin;
extern BitBand PDin;
extern BitBand PEin;
extern BitBand PFin;
extern BitBand PGin;
extern BitBand PHin;
extern BitBand PIin;
extern BitBand PAout;
extern BitBand PBout;
extern BitBand PCout;
extern BitBand PDout;
extern BitBand PEout;
extern BitBand PFout;
extern BitBand PGout;
extern BitBand PHout;
extern BitBand PIout;
#endif
C文件
/**
******************************************************************************
* @file sys.c
* @author zhy
* @version 1.0
* @date 2021-01-22
* @brief 系统初始化相关,配置RCC时钟,中断分组
******************************************************************************
*/
#include "sys.h"
#include "stm32f4xx.h"
/* 全局变量 */
BitBand PAin __attribute__((at(GPIOA_BASE + 16)));
BitBand PBin __attribute__((at(GPIOB_BASE + 16)));
BitBand PCin __attribute__((at(GPIOC_BASE + 16)));
BitBand PDin __attribute__((at(GPIOD_BASE + 16)));
BitBand PEin __attribute__((at(GPIOE_BASE + 16)));
BitBand PFin __attribute__((at(GPIOF_BASE + 16)));
BitBand PGin __attribute__((at(GPIOG_BASE + 16)));
BitBand PHin __attribute__((at(GPIOH_BASE + 16)));
BitBand PIin __attribute__((at(GPIOI_BASE + 16)));
BitBand PAout __attribute__((at(GPIOA_BASE + 20)));
BitBand PBout __attribute__((at(GPIOB_BASE + 20)));
BitBand PCout __attribute__((at(GPIOC_BASE + 20)));
BitBand PDout __attribute__((at(GPIOD_BASE + 20)));
BitBand PEout __attribute__((at(GPIOE_BASE + 20)));
BitBand PFout __attribute__((at(GPIOF_BASE + 20)));
BitBand PGout __attribute__((at(GPIOG_BASE + 20)));
BitBand PHout __attribute__((at(GPIOH_BASE + 20)));
BitBand PIout __attribute__((at(GPIOI_BASE + 20)));
/**
* @brief 重构函数
* @note 在printf中自动调用
* @param {int} ch 发送的数据
* @param {FILE} *f 此处用不到
* @retval 当前发送值
*/
int fputc(int ch, FILE *f)
{
while ((USART1->SR & USART_SR_TXE) == 0)
; //判断是否发送完成
USART1->DR = (uint8_t)ch; //发送数据
return ch;
}
去掉了系统初始化相关内容,将printf相关内容加入其中,这样,附加的内容就添加完毕。
我们所有的配置生成的代码和需要修改的代码都在该文件夹中,如下图所示:

在本例程中,除了上述分析的自己添加的文档三个文档,STM32CUBE自动生成的代码有:
- stm32f4xx_hal_msp.c——底层初始化相关
- main.c——主程序
- stm32f4xx_it.c——中断响应相关
2.底层初始化
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
/* System interrupt init*/
/* MemoryManagement_IRQn interrupt configuration */
HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
/* BusFault_IRQn interrupt configuration */
HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
/* UsageFault_IRQn interrupt configuration */
HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
/* DebugMonitor_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
该函数被函数UAL_Init()函数最后调用。通过该函数设置了中断优先组为2。
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
3.中断服务函数
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
为了程序可以顺利执行还需要在该文档头部增加内容:

至此,中断服务部分修改完毕。
4. 主文档
一、添加头文件:
#include "stm32f4xx_hal.h"
#include "queue.h"
#include "sys.h"
#include "delay.h"
添加外部全局变量引用:
extern Queue QueueRx; 总体如下:

二、修改串口初始化
void MX_USART1_UART_Init(void)
{
UART_HandleTypeDef huart1; //将全局变量添加到此
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //开启接收中断
}
最后一行为我添加的使能接收中断。
至此程序完成。
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();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
InitQueue(&queueRx);
printf("hello, world!n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
uint8_t temp = 0;
/* USER CODE END WHILE */
while (DeQueue(&queueRx, &temp))
{
while ((USART1->SR & USART_SR_TXE) == 0)
;
USART1->DR = temp;
}
PBout.bit0=0;
PBout.bit1=1;
delay_ms(20);
PBout.bit0=1;
PBout.bit1=0;
delay_ms(20);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
主程序和原来大致一致。
实验结果

前言
本文主要介绍 串口实验 的通过STM32CUBE形式和直接编程模式的不同。
本文可以参考博客<STM32F429第十四篇之串口实验详解>。
两种方式实验的效果完全相同:
- 在程序启动时,会发送信息 hello,zhy!
- 在程序运行时,LED等闪烁。
- 向串口1 发送数据,其会返回相同的数据。
该实验源代码下载https://github.com/zhenhaiyang/STM32CUBE
本文主要参考资料:
- 正点原子.STM32F429开发指南-HAL库版本_V1.1
STM32CUBE配置
关于LED灯的配置部分,可以参考博客<STM32CubeMX第二篇之跑马灯>。本文不再重复介绍。
配置串口
- 配置Pinout。本实验使用的是PA9和PA10。首先配置为串口功能,如下图所示:
- 配置configuration。在此处经常需要配置GPIO,NVIC,RCC,USART等。本例程主要演示USART,如下所示:
配置串口的参数。
配置串口的中断
配置串口的GPIO
配置完成后,点击确定。
最后,可以按照之前博客<STM32CubeMX第二篇之跑马灯>中介绍的方法生成代码。此处不再介绍。
代码分析与修改
1. 添加代码
添加三部分代码:
- 对列相关
- 延时相关
- 系统相关

其中,前两个部分与博客<STM32F429第十五篇之串口实验详解二>中介绍的完全相同。因为系统初始化还有串口部分都可以自动生成,所以,对系统相关的文件需要修改如下:
头文件与上述博客内容也是一致,如上所示:
/**
******************************************************************************
* @file sys.h
* @author zhy
* @version 1.0
* @date 2021-01-22
* @brief 系统初始化相关的头文件
******************************************************************************
*/
#ifndef _SYS_H
#define _SYS_H
#include
/* 位带操作 */
typedef struct
{
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
unsigned int bit9 : 1;
unsigned int bit10 : 1;
unsigned int bit11 : 1;
unsigned int bit12 : 1;
unsigned int bit13 : 1;
unsigned int bit14 : 1;
unsigned int bit15 : 1;
unsigned int rsv : 16;
} BitBand __attribute__((bitband));
extern BitBand PAin;
extern BitBand PBin;
extern BitBand PCin;
extern BitBand PDin;
extern BitBand PEin;
extern BitBand PFin;
extern BitBand PGin;
extern BitBand PHin;
extern BitBand PIin;
extern BitBand PAout;
extern BitBand PBout;
extern BitBand PCout;
extern BitBand PDout;
extern BitBand PEout;
extern BitBand PFout;
extern BitBand PGout;
extern BitBand PHout;
extern BitBand PIout;
#endif
C文件
/**
******************************************************************************
* @file sys.c
* @author zhy
* @version 1.0
* @date 2021-01-22
* @brief 系统初始化相关,配置RCC时钟,中断分组
******************************************************************************
*/
#include "sys.h"
#include "stm32f4xx.h"
/* 全局变量 */
BitBand PAin __attribute__((at(GPIOA_BASE + 16)));
BitBand PBin __attribute__((at(GPIOB_BASE + 16)));
BitBand PCin __attribute__((at(GPIOC_BASE + 16)));
BitBand PDin __attribute__((at(GPIOD_BASE + 16)));
BitBand PEin __attribute__((at(GPIOE_BASE + 16)));
BitBand PFin __attribute__((at(GPIOF_BASE + 16)));
BitBand PGin __attribute__((at(GPIOG_BASE + 16)));
BitBand PHin __attribute__((at(GPIOH_BASE + 16)));
BitBand PIin __attribute__((at(GPIOI_BASE + 16)));
BitBand PAout __attribute__((at(GPIOA_BASE + 20)));
BitBand PBout __attribute__((at(GPIOB_BASE + 20)));
BitBand PCout __attribute__((at(GPIOC_BASE + 20)));
BitBand PDout __attribute__((at(GPIOD_BASE + 20)));
BitBand PEout __attribute__((at(GPIOE_BASE + 20)));
BitBand PFout __attribute__((at(GPIOF_BASE + 20)));
BitBand PGout __attribute__((at(GPIOG_BASE + 20)));
BitBand PHout __attribute__((at(GPIOH_BASE + 20)));
BitBand PIout __attribute__((at(GPIOI_BASE + 20)));
/**
* @brief 重构函数
* @note 在printf中自动调用
* @param {int} ch 发送的数据
* @param {FILE} *f 此处用不到
* @retval 当前发送值
*/
int fputc(int ch, FILE *f)
{
while ((USART1->SR & USART_SR_TXE) == 0)
; //判断是否发送完成
USART1->DR = (uint8_t)ch; //发送数据
return ch;
}
去掉了系统初始化相关内容,将printf相关内容加入其中,这样,附加的内容就添加完毕。
我们所有的配置生成的代码和需要修改的代码都在该文件夹中,如下图所示:

在本例程中,除了上述分析的自己添加的文档三个文档,STM32CUBE自动生成的代码有:
- stm32f4xx_hal_msp.c——底层初始化相关
- main.c——主程序
- stm32f4xx_it.c——中断响应相关
2.底层初始化
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
/* System interrupt init*/
/* MemoryManagement_IRQn interrupt configuration */
HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
/* BusFault_IRQn interrupt configuration */
HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
/* UsageFault_IRQn interrupt configuration */
HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
/* DebugMonitor_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
该函数被函数UAL_Init()函数最后调用。通过该函数设置了中断优先组为2。
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
3.中断服务函数
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
为了程序可以顺利执行还需要在该文档头部增加内容:

至此,中断服务部分修改完毕。
4. 主文档
一、添加头文件:
#include "stm32f4xx_hal.h"
#include "queue.h"
#include "sys.h"
#include "delay.h"
添加外部全局变量引用:
extern Queue QueueRx; 总体如下:

二、修改串口初始化
void MX_USART1_UART_Init(void)
{
UART_HandleTypeDef huart1; //将全局变量添加到此
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //开启接收中断
}
最后一行为我添加的使能接收中断。
至此程序完成。
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();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
InitQueue(&queueRx);
printf("hello, world!n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
uint8_t temp = 0;
/* USER CODE END WHILE */
while (DeQueue(&queueRx, &temp))
{
while ((USART1->SR & USART_SR_TXE) == 0)
;
USART1->DR = temp;
}
PBout.bit0=0;
PBout.bit1=1;
delay_ms(20);
PBout.bit0=1;
PBout.bit1=0;
delay_ms(20);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
主程序和原来大致一致。
实验结果

举报