前几节我们已经搭建好环境并验证了环境可以正常使用。那么接下来就来使用STM32CubeMX图形化工具配置定时器、串口、输入输出等功能,实现按键、LED的控制和串口输出字符串灯功能。
一,简单介绍下硬件接口
1,从图上看,我们使用USART1作为输出口,使用了PB14和PB15,连接到Arduino接口的CN9上。PB14是发送引脚,PB15是接收引脚。
2,LED灯由PA5控制,高电平时,灯亮。低电平时,灯灭。
2,用户按键,PC13作为按键输入信号。
3,主控芯片使用STM32H503RBT6,使用的是Arm Cortex-M33内核MCU ,有128-Kbyte Flash和 32-Kbyte RAM, CPU主频250 MHz。使用的芯片封装是LQFP 64 。
二,STM32CubeMX配置
知道了硬件接口,我们就开始使用STM32CubeMX新建工程对硬件接口进行配置。
1,GPIO配置
配置按键PC13为输入引脚,PA5为输出引脚。PC13配置中断模式,配置为GPIO_EXITI13模式。根据原理图常态是低电平,按下是高电平,所以配置为上升沿触发。
配置中断使能EXTI Line13
这里需要说明一下,这里优先级配置越低,优先级越高,也就是0是最高优先级。所有需要把System tick timer优先级配置为0。其他优先级就不能配置为0,因为HAL_Delay这个延时函数会用到Systick定时器中断,他的优先级是0,如果某个外部中断抢占优先级也为0,执行外部中断时调用了HAL_Delay,则Systick中断无法抢占,函数HAL_Delay的执行将会陷入死循环。
PA5配置为输出模式,默认输出低电平。
2,串口配置
首先使能USART1,配置为异步模式。在parameter settings中配置波特率灯常规参数。
我们只是使用串口作为调试接口使用,输出信息,所以其他不需要配置,在配置GPIO即可。
3,时钟配置参照上一节。
4,定时器配置
我们使用基础定时的定时中断功能。我这里使用TIM6,TIM6是一个16位的定时器。
激活TIM6。
从时钟配置知道,定时器挂在APB总线上,频率是250MHz。
定时器周期为1秒溢出中断一次,那么配置如下
使能中断。
这里配置不了优先级,需要在NVIC中配置,配置中断优先级为1.
5,配置项目管理
使用MDK-ARM集成环境。
6,生产代码
7,使用MDK打开工程
三,用户软件
实现功能包括:
A) 实现1秒定时器,LED灯在定时器中断实现1秒闪烁;
B) 用户按键一次,LED灯闪烁速度变快;
C) 串口输出调试信息,初始化输出及按键时输出;
1,实现TIM6连续定时模式,周期为1秒,中断方式实现LED翻转。
在STM32CubeMX生产的代码中已经实现了相关配置的初始化。
在stm32h5xx_it.c实现了TIM6中断入口函数:
extern TIM_HandleTypeDef htim6;
HAL_TIM_IRQHandler是所有定时器都使用这个入口函数,所有函数实现了比较全的功能,我们这里就是使用定时器计数溢出功能,即下图指示位置:
我直接在time6中断函数入口地方添加led灯翻转程序。
HAL_GPIO_TogglePin(USER_LED_GPIO_Port, USER_LED_Pin);
还需要正在main函数中初始化的地方加上基础定时器以中断模式启动。
HAL_TIM_Base_Start_IT(&htim6);
此时编译、下载,运行。看到了led开始以1秒周期闪烁了。
2,按键中断程序实现,按一次led闪烁速度加快一倍,达到三次,按一次三所速度减慢一次,达到三次后开始加快……如此循环。
我们在GPIO的初始化函数MX_GPIO_Init中可以看到对按键及中断进行了初始化。
在stm32h5xx_it.c实现了EXTI Line13的入口函数EXTI13_IRQHandler。
在函数中已经实现了中断回调函数,这里我将自己重新实现中断回调函数。
我将只在中断中实现按键计数和按键标志。
在main函数while(1)中实现按键处理,
if(button_is_exists == 1) { button_is_exists=0; switch(g_count) { case 1: MX_TIM6_ReInit(5000);// 500ms break; case 2: MX_TIM6_ReInit(2500); //250ms break; case 3: MX_TIM6_ReInit(1250); //125ms break; case 4: MX_TIM6_ReInit(2500); //250ms break; case 5: MX_TIM6_ReInit(5000);// 500ms break; case 6: MX_TIM6_ReInit(10000);// 500ms g_count=0; break; default: break; } }
编译、下载、运行。按键可以控制led灯闪烁频率了。
3,printf通过串口打印信息
首先要实现串口printf打印,需要添加重定向函数,我添加在main文件中。
增加头文件#include <stdio.h>
重定向函数:
int fputc(int ch, struct __FILE *f) { /* e.g. write a character to the USART */ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; }
我使用的是MDK,需要把Use MicroLIB勾选上,才能调用系统库。
然后再初始化串口之后添加
printf("Hello EEPW & DigiKey! Hello STM32H503!\r\n");
我再在按键处理中增加一些printf输出信息;
if(button_is_exists == 1) { button_is_exists=0; switch(g_count) { case 1: period = 5000;// 500ms break; case 2: period = 2500;//250ms break; case 3: period = 1250;//125ms break; case 4: period = 2500;//250ms break; case 5: period = 5000;// 500ms break; case 6: period = 10000;// 500ms g_count=0; break; default: break; } MX_TIM6_ReInit(period); printf("The current button count is %d,The LED blinking cycle is %d\r\n",g_count,period); }
然后编译、下载、运行。结果如下
到这里整个实验就完成了,整体达到了预期效果。录一个短视频看一下效果。
https://v.youku.com/v_show/id_XNjM5MDE1NDkyOA==.html