|版权声明:本文为博主原创文章,转载请注明出处。https://blog.csdn.net/NeverImagine_/article/details/95517664

  目前ST官方有提供两种库文件,一种是标准库,一种是HAL库,在HAL库问世之前,标准库一直被嵌入式工程师广泛使用,由于标准库的资源都是开源的,几乎所有应用网上都可以找到demo,所以无论是老工程师还是初学者都十分推崇。然而近几年开始,ST官方大力推行使用HAL库,其优势是操作方便,所有底层都封装好,用户在开发时只需调用其生成的API即可。同时,HAL库可以通过ST官方提供的STM32CubeMX图形软件生成,用户可根据不同的应用进行相应的配置,Cube可以根据用户的配置自动生成底层代码,用户只需根据需求开发自己的功能函数即可。
  笔者入坑软件的时候是从标准库开始学习的,最近开始学习使用HAL库,HAL库十分冗长但功能强大(很多使用标准库需要自己完成的操作,例如简单的操作GPIO的输出,HAL库都已经封装成了现成的函数,只是初学者找起来比较麻烦。。),熟悉了HAL库的套路之后,开发就变的容易多了。笔者也是刚整明白基于HAL库的串口打印程序,在此记录。

一、使用STM32CubeMX进行引脚的相关配置
  本实验为了实现两个按键的串口打印程序,在按下PA0按键时上位机显示“1”,按下PC13按键时上位机显示“2”。
  这里只是为实现串口打印的功能,所以只需配置一个串口即可,但为了直观,本文还配置了一三个输出口两个输入口,作为不同的状态显示。配置如图一:

               图一、本实验的引脚配置
  其中:在本实验中,对于PA0和PC13两个按键来说,配置成输入模式和外部中断模式在功能上是一样的,在应用中需要根据输入的紧要程度进行判断是否设置成中断模式。
  这里需要注意打开串口中断,如图二所示:

               图二、打开串口中断
  配置完成之后点击右上角GENERATE CODE生成代码,注意生成代码时根目录的文件夹名称不能出现中文,否则会提示错误。

二、代码分析
生成的代码目录如图三:

          图三、生成的代码目录(点击编译后左边会出现“+”)
  在这里,所有底层代码都已经根据配置生成好了,例如gpio.c文件中:

void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOH, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);/*Configure GPIO pin : PC13 */GPIO_InitStruct.Pin = GPIO_PIN_13;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/*Configure GPIO pin : PA0 */GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pins : PH10 PH11 PH12 */GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);/* EXTI interrupt init*/HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 2);HAL_NVIC_EnableIRQ(EXTI0_IRQn);HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 1);HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);}

  在uart.c文件中:

UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{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;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO Configuration    PA9     ------> USART1_TXPA10     ------> 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);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}

  功能配置都已妥当,不用再手动配置,接下来就是写实现PC端串口打印功能的代码。
  ① 在main.c文件中添加stdio.h头文件,因为代码中用到的数据类型定义(如uint8_t uint16_t等数据类型都是在stdio.h头文件里定义的)。

/* USER CODE BEGIN Includes */#include "stm32f4xx_hal_gpio.h"
#include <stdint.h>/* USER CODE END Includes */

  添加stm32f4xx_hal_gpio.h是因为代码中有使用stm32f4xx_hal_gpio.h头文件里读取和写入GPIO状态的函数。
  ② 定义两个数组:

  uint8_t aTxStartMessages1[] = "1";uint8_t aTxStartMessages2[] = "2";

  ③ 在中断函数(中断函数在stm32f4xx_it.c中)找到void EXTI15_10_IRQHandler(void)函数和void EXTI0_IRQHandler(void)函数,一步一步进入,最后找到HAL_GPIO_EXTI_Callback(GPIO_Pin)函数,会发现这两个中断入口最后进入的回调函数是同一个,即HAL_GPIO_EXTI_Callback(GPIO_Pin)函数,所以在回调函数中需要进行一个条件判断,注意,回调函数是弱定义函数,函数前有一个_weak的标识符,说明此函数可以被用户重新定义,将HAL_GPIO_EXTI_Callback(GPIO_Pin)函数复制到main.c文件下方,重新定义如下所示:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET){HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_10);HAL_UART_Transmit(&huart1,(uint8_t *)aTxStartMessages1,sizeof(aTxStartMessages1),0xFFFF);//(uint8_t*)aTxStartMessages2为字符串地址,sizeof(aTxStartMessages1)表示字符串长度为数组aTxStartMessages1的长度,0xFFFF为超时时间}if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET){HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_11 | GPIO_PIN_12);HAL_UART_Transmit(&huart1,(uint8_t *)aTxStartMessages2,sizeof(aTxStartMessages2),0xFFFF);//(uint8_t*)aTxStartMessages2为字符串地址,sizeof(aTxStartMessages2)表示字符串长度为数组aTxStartMessages2的长度,0xFFFF为超时时间}}

  此段代码的含义是:如果PA0按下,PH10状态翻转,同时单片机将长度为aTxStartMessages1数组长度的数据发送到(uint8_t *)aTxStartMessages1指针指向的地址中。如果PC13按下,PH11、PH12状态翻转,同时单片机将长度为aTxStartMessages2数组长度的数据发送到(uint8_t *)aTxStartMessages2指针指向的地址中。
  需要注意的是,这两个指针指向的为同一地址,每次收到一个数据的时候,之前的数据会被覆盖。
  整个过程可以理解成,每按下一次按键,单片机产生一个数据保存在一个长度为1的数组里,再将这个数组的数据发送到另一个接收数据的地址中,单片机再读取接收地址中的数据在上位机中显示出来。
  流程图如下:

发送
待发送数据
接收地址
数据长度是否达到设定值
发送数据到缓存区并读取

  ④ 最后打开串口调试助手,通过USB转串口工具将开发板连电脑,串口调试助手界面设置好波特率等参数(需与程序中的配置一致,否则串口会发送数据失败)开发板上电之后,按下按键PA0,上位机中显示1,按下PC13,上位机显示2。

  本次实验笔者走了很多弯路,几乎可以说沿着HAL库里关于串口的每一个函数都看了一遍,才搞明白串口打印的流程,故在此记录,提醒自己也提醒读者,在编程时要首先搞清楚各个功能模块的工作流程,画出流程图,根据流程图进行编程,这样思路清晰且方便快捷,不易出错,就算出错也便于查错,在搞清楚流程之前就开始编程可能在功能开发完成之前自己已经看不懂自己的代码了。

如有错误欢迎指正,以上。

STM32软件学习笔记(一)基于HAL库的STM32F429单片机串口打印程序相关推荐

  1. 学习笔记四.基于HAL库的stm32f103硬件读写EEPROM(CUBEMX)

    基于cubemx的stm32f103硬件读写EEPROM 今天介绍一种可擦除存储器. EEPROM (Electrically Erasable Programmable read only memo ...

  2. STM32CUBEMX入门学习笔记3:HAL库以及STM32CUBE相关资料

    STM32CUBEMX入门学习笔记3:HAL库以及STM32CUBE相关资料 微雪课堂:http://www.waveshare.net/study/article-629-1.html 之前的正点原 ...

  3. STM32学习笔记-SMT32使用HAL库UART中断方式使用

    目录 1.引言 2.配置 3.流程 1.引言 近来需要使用蓝牙模块,再了解到蓝牙模块等无线模块许多使用串口透传,便决定在研究一下串口UART 的使用方法. 由于用的板子种类每次都不一样,有F103 有 ...

  4. Apm飞控学习笔记之添加我的设备或单片机串口通信-Cxm

    目录 PX4/APM/飞控的学习笔记前言-Cxm_chen_taifu的博客-CSDN博客开始了 开始了终于有时间可以学习飞控了此文章是用来当目录,我会持续更新我的学习之旅,希望能对各位有所帮助如果有 ...

  5. 基于HAL库创建Keil工程模板

    [百问网]物联网学习笔记 Keil创建HAL库工程模板步骤: 1. 创建相关文件夹: 2. 复制CMSIS和HAL库; 3. 创建"main.c/h"和"stm32f1x ...

  6. STM32F407学习笔记(1)基于hal库,CubeMX以及keil5的基本使用。

    前言:自己是大二的一名通信工程专业的小菜鸡,在实验室培训了四次之后,我们目前使用是stm32f407zgt6这块单片机.在为明年的电赛国赛准备着.实验室目前使用的工具是cubemax和keil这两款软 ...

  7. 正点原子STM32(基于HAL库)0

    目录 开发环境搭建与使用 常用开发工具简介 MDK 安装 仿真器驱动安装 CH340 USB 虚拟串口驱动安装 使用MDK5 编译例程 使用串口下载程序 使用DAP 下载与调试程序 使用DAP 下载程 ...

  8. STM32外挂FLASH模拟U盘(基于HAL库)

    STM32外挂FLASH模拟U盘(基于HAL库) 1.背景 1.1这篇文章能给你带来什么 1.2根据你要解决的问题,精确快速跳转到相应位置 1.3我在做完这个后还有不明白的地方,希望能有大触解答困惑 ...

  9. STM32控制步进电机:基于HAL库定时器中断的闭环步进电机驱动+精准控制脉冲数

    STM32控制步进电机:基于HAL库定时器中断的闭环步进电机驱动+精准控制脉冲数 一.步进电机闭环驱动器 二.CubeMx配置 1.Clock Configuration 2.脉冲端 定时器配置 3. ...

最新文章

  1. asp.net实现图片在线上传并在线裁剪
  2. 英伟达宣布全面支持ARM高性能计算,三周打造全球排名第22超算
  3. qt能使用logback_SpringBoot 中使用 LogBack 配置
  4. 内网通 去广告_新高一攻略|让我们一起跟升学e网通名师看看如何学好高中化学...
  5. 抽象类、抽象方法与代码块
  6. 天涯明月刀开发_《天涯明月刀OL腾讯旗下 北极光工作室的 厄运魔咒:“做什么凉什么”》...
  7. python的多线程应用前景_什么是线程(多线程),Python多线程的好处
  8. 4599 的 iPhone 11,拼多多如何从「真香」到「更香」
  9. [运维笔记] PowerShell (模块).模块清单
  10. python数据类型汇总_python知识汇总(数据类型和字符串)
  11. hd_Lanswitch Web System
  12. 计算机在旅游管理方面的应用,谈旅游管理信息系统的设计与应用
  13. 单片机各种通信协议详解
  14. LoadRunner教程(19)-LoadRunner 性能图表分析
  15. lol手游修改服务器,英雄联盟官方修改大区的方法
  16. html文件内容重叠,html – CSS:页脚重叠内容,其他故障
  17. 百度推广——搜索营销新视角(百度官方出品,俞敏洪、吴晓波、徐雷力荐!)
  18. 小学的四则运算(输入结果)
  19. 网络模拟和分析工具--Mahimahi的安装教程
  20. MySQL系统库之mysql

热门文章

  1. CA6140机床法兰盘(代号831004)课程设计——说明书 CAD图纸 工艺卡 过程卡……
  2. 模糊数学学习笔记 5:模糊聚类
  3. 如何获得查新检索报告?
  4. R语言矩阵特征值分解(谱分解)和奇异值分解(SVD)特征向量分析有价证券数据
  5. 微信H5页面前端开发,大多数人都会遇到的几个兼容性坑(转载)
  6. word 参考文献 交叉引用 自动更新
  7. 游戏设计-《游戏改变世界》-思维导图
  8. 电商ERP系统——商品SKU与库存设计
  9. 3.Python数据结构与算法分析课后习题(第二版)__chapter3
  10. 从cas-overlay-template安装apereo cas 6.1.x并连接CAS客户端