STM32
直播中

张娟

7年用户 1993经验值
私信 关注
[问答]

分享一个不错的STM32CubeMX串口实验

分享一个不错的STM32CubeMX串口实验

回帖(1)

张强

2021-12-14 11:12:18
前言

本文主要介绍 串口实验 的通过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 */
}
主程序和原来大致一致。
实验结果



举报

更多回帖

发帖
×
20
完善资料,
赚取积分