STM32CubeMX第三篇之串口实验
发布日期:2021-05-14 11:31:27 浏览次数:23 分类:精选文章

本文共 7643 字,大约阅读时间需要 25 分钟。

文章目录

前言

本文主要介绍 串口实验 的通过STM32CUBE形式和直接编程模式的不同。

本文可以参考博客<>。

两种方式实验的效果完全相同:

  • 在程序启动时,会发送信息 hello,zhy!
  • 在程序运行时,LED等闪烁。
  • 向串口1 发送数据,其会返回相同的数据。

该实验源代码下载

本文主要参考资料:

  • 正点原子.STM32F429开发指南-HAL库版本_V1.1

STM32CUBE配置

关于LED灯的配置部分,可以参考博客<>。本文不再重复介绍。

配置串口

  1. 配置Pinout。本实验使用的是PA9和PA10。首先配置为串口功能,如下图所示:

在这里插入图片描述

  1. 配置configuration。在此处经常需要配置GPIO,NVIC,RCC,USART等。本例程主要演示USART,如下所示:

在这里插入图片描述

配置串口的参数。
在这里插入图片描述
配置串口的中断
在这里插入图片描述
配置串口的GPIO
在这里插入图片描述
配置完成后,点击确定。

  1. 配置中断。

在这里插入图片描述

在这里插入图片描述

最后,可以按照之前博客<>中介绍的方法生成代码。此处不再介绍。

代码分析与修改

1. 添加代码

添加三部分代码:

  1. 对列相关
  2. 延时相关
  3. 系统相关
    在这里插入图片描述

其中,前两个部分与博客<>中介绍的完全相同。因为系统初始化还有串口部分都可以自动生成,所以,对系统相关的文件需要修改如下:

头文件与上述博客内容也是一致,如上所示:

/**  ******************************************************************************  * @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 */  }}

该函数被HAL_UART_MspInit()函数调用。主要设置了串口相关的GPIO设置方法,以及串口对应的中断。

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 */}

与本实验有关的串口中断服务函数原有定义为上文。但是,为了执行效率,不需要这么复杂。结合博客<>中的案例,将该函数修改为:

/*** @brief This function handles USART1 global interrupt.*/void USART1_IRQHandler(void){       /* USER CODE BEGIN USART1_IRQn 0 */    /* USER CODE END USART1_IRQn 0 */    if ((USART1->SR & USART_SR_RXNE) && (USART1->CR1 & USART_CR1_RXNEIE)) //当接收中断置位且有中断标记    {           InQueue(&queueRx, USART1->DR); //将接收的内容放入队列,读取寄存器,自动清除中断标记位    }    /* 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 */}

主程序和原来大致一致。

实验结果

在这里插入图片描述

上一篇:STM32F429第十五篇之串口实验详解二
下一篇:STM32F429第十四篇之串口实验详解

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月08日 21时13分26秒