这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【手势翻页笔】+成果帖+STM32CubeMX内外参数配置定时器、GPIO输入输

共3条 1/1 1 跳转至

【手势翻页笔】+成果帖+STM32CubeMX内外参数配置定时器、GPIO输入输出和串口输出

菜鸟
2024-04-21 17:44:05     打赏

前几节我们已经搭建好环境并验证了环境可以正常使用。那么接下来就来使用STM32CubeMX图形化工具配置定时器、串口、输入输出等功能,实现按键、LED的控制和串口输出字符串灯功能。

一,简单介绍下硬件接口

1,从图上看,我们使用USART1作为输出口,使用了PB14PB15,连接到Arduino接口的CN9上。PB14是发送引脚,PB15是接收引脚。

 图片28.png

2LED灯由PA5控制,高电平时,灯亮。低电平时,灯灭。

 图片29.png

2,用户按键,PC13作为按键输入信号。

图片30.png 

3,主控芯片使用STM32H503RBT6,使用的是Arm Cortex-M33内核MCU ,有128-Kbyte Flash32-Kbyte RAM, CPU主频250 MHz。使用的芯片封装是LQFP 64

二,STM32CubeMX配置

知道了硬件接口,我们就开始使用STM32CubeMX新建工程对硬件接口进行配置。

1,GPIO配置

配置按键PC13为输入引脚,PA5为输出引脚。PC13配置中断模式,配置为GPIO_EXITI13模式。根据原理图常态是低电平,按下是高电平,所以配置为上升沿触发。

图片31.png 

配置中断使能EXTI Line13

图片32.png 

这里需要说明一下,这里优先级配置越低,优先级越高,也就是0是最高优先级。所有需要把System tick timer优先级配置为0。其他优先级就不能配置为0,因为HAL_Delay这个延时函数会用到Systick定时器中断,他的优先级是0,如果某个外部中断抢占优先级也为0,执行外部中断时调用了HAL_Delay,则Systick中断无法抢占,函数HAL_Delay的执行将会陷入死循环。

PA5配置为输出模式,默认输出低电平。

   图片33.png

2,串口配置

首先使能USART1,配置为异步模式。在parameter settings中配置波特率灯常规参数。

图片34.png 

我们只是使用串口作为调试接口使用,输出信息,所以其他不需要配置,在配置GPIO即可。

 图片35.png

3,时钟配置参照上一节。

4,定时器配置

我们使用基础定时的定时中断功能。我这里使用TIM6TIM6是一个16位的定时器。

 图片36.png

激活TIM6

 图片37.png

从时钟配置知道,定时器挂在APB总线上,频率是250MHz

 图片38.png

定时器周期为1秒溢出中断一次,那么配置如下

 图片39.png

使能中断。

 图片40.png

这里配置不了优先级,需要在NVIC中配置,配置中断优先级为1.

 图片41.png

5,配置项目管理

使用MDK-ARM集成环境。

 图片42.png

6,生产代码

7,使用MDK打开工程

 图片43.png

 

三,用户软件

实现功能包括:

A) 实现1秒定时器,LED灯在定时器中断实现1秒闪烁;

B) 用户按键一次,LED灯闪烁速度变快;

C)  串口输出调试信息,初始化输出及按键时输出;

1,实现TIM6连续定时模式,周期为1秒,中断方式实现LED翻转。

STM32CubeMX生产的代码中已经实现了相关配置的初始化。

 图片44.png

stm32h5xx_it.c实现了TIM6中断入口函数:

extern TIM_HandleTypeDef htim6;

 图片45.png

HAL_TIM_IRQHandler是所有定时器都使用这个入口函数,所有函数实现了比较全的功能,我们这里就是使用定时器计数溢出功能,即下图指示位置:

 图片46.png

我直接在time6中断函数入口地方添加led灯翻转程序。

HAL_GPIO_TogglePin(USER_LED_GPIO_Port, USER_LED_Pin);

 图片47.png

还需要正在main函数中初始化的地方加上基础定时器以中断模式启动。

HAL_TIM_Base_Start_IT(&htim6);

此时编译、下载,运行。看到了led开始以1秒周期闪烁了。

 

2,按键中断程序实现,按一次led闪烁速度加快一倍,达到三次,按一次三所速度减慢一次,达到三次后开始加快……如此循环。

我们在GPIO的初始化函数MX_GPIO_Init中可以看到对按键及中断进行了初始化。

 图片48.png

stm32h5xx_it.c实现了EXTI Line13的入口函数EXTI13_IRQHandler

 图片49.png

在函数中已经实现了中断回调函数,这里我将自己重新实现中断回调函数。

 图片50.png

将只在中断中实现按键计数和按键标志。

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勾选上,才能调用系统库。

图片51.png 

然后再初始化串口之后添加

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);
}

然后编译、下载、运行。结果如下

图片52.png 

 

到这里整个实验就完成了,整体达到了预期效果。录一个短视频看一下效果。

https://v.youku.com/v_show/id_XNjM5MDE1NDkyOA==.html



菜鸟
2024-04-21 22:28:03     打赏
2楼

不错


高工
2024-04-22 09:06:30     打赏
3楼

谢谢分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]