目录
[1. 设计目的](#1. 设计目的)
[4. 配置TIM6](#4. 配置TIM6)
[5. 配置TIM7](#5. 配置TIM7)
本文旨在叙述ST单片机STM32G474RCT6的基础定时器的中断的实现方法。
一、硬件板及MCU定时器资源
1.开发板
本文使用的硬件板是ST的开发板NUCLEO-G474RE,板上MCU型号为STM32G474RET6。并按照资源提示设计制造了扩展IO板,有需要此扩展板的留言联系我。
2.定时器资源
ST单片机STM32G474RCT6的定时器资源请参考作者的其他文章:细说MCU定时器中断的实现方法_mcu定时和中断-CSDN博客 https://wenchm.blog.csdn.net/article/details/139627554https://wenchm.blog.csdn.net/article/details/139627554
ST单片机STM32G474RCT6 有两个基础定时器TIM6和TIM7。本文就操作TIM6和TIM7,以此论述基础定时器计数器周期满溢后的UEV事件中断的实现方法。
三、项目的设计目的及复用的资源
1. 设计目的
- TIM6设置为连续定时模式,定时周期为500ms,以中断方式启动TIM6,在UEV事件中断回调函数里使LED1输出翻转。
- TIM7设置为单次定时模式,定时周期为2000ms,按下KeyRight键之后使LED2点亮, 并以中断方式启动TIM7,在UEV事件中断回调函数里使LED2输出翻转。
2.复用其它项目的资源
本项目复用作者写的其他文章的项目资源:细说工程师如何编写有使用价值的单片机程序(以GPIO为例)-CSDN博客 https://wenchm.blog.csdn.net/article/details/140957258https://wenchm.blog.csdn.net/article/details/140957258
本项目复用参考项目的KEY_LED文件夹下的keyled.c和keyled.h文件。在项目中添加KEY_LED目录和文件,及添加文件路径的方法均与参考文件一致。
四、建立工程
1.配置GPIO
- 配置PB11、PB12,GPIO OUTPUT,默认High Level,PP,PullUp,High Speed,标识为LED1,LED2;
- 配置PA0,EXTI0,PP,标识为:KeyRight;
2.配置时钟源和Debug
打开System Core中的RCC,高速时钟(HSE)选择Crystal/ eramic Resonator,使用片外时钟晶体作为HSE的时钟源。在SYS中将Debug设置Serial Wire。
3.配置系统时钟
将系统时钟(SYSCLK)频率配置为170 MHz。
4. 配置TIM6
配置定时器TIM6,勾选Activated复选框,以启用TIM6。 TIM6工作于连续定时模式,不选择One Pulse Mode复选框。
Prescaler预分频器值设置为16999;Counter Mode基础定时器只有递增模式(Up);Counter Period计数周期,也就是自重载寄存器(AutoReload Register)的值,设置为4999。那么产生UEV事件时,共计时5000个时钟周期;auto reloadpreload,启用自重载寄存器TIM6_ARR的预装载功能;其它参数选择默认;
在时钟树中设置了APB1定时器时钟频率为170MHz,设置预分频器值为16999,所以进入计数器的时钟频率为170*10^6/(1+16999)=10000Hz。计数周期设置为4999,所以TIM6定时器每(1+4999)*(1/10000)=500ms产生一次计数溢出,也就是产生一次UEV事件。若UEV事件的中断使能控制位被置1,且TIM6的全局中断已打开,则TIM6每500ms就会产生一次硬件中断。
5. 配置TIM7
配置定时器TIM7,勾选Activated复选框,以启用TIM7。 TIM7工作于单次定时模式,所以,选择One Pulse Mode复选框。
Prescaler预分频器值设置为16999;Counter Mode基础定时器只有递增模式(Up);Counter Period计数周期,也就是自重载寄存器(AutoReload Register)的值,设置为19999。那么产生UEV事件时,共计时20000个时钟周期;auto reloadpreload,启用自重载寄存器TIM7_ARR的预装载功能;其它参数选择默认;
在时钟树中设置了APB1定时器时钟频率为170MHz,设置预分频器值为16999,所以进入计数器的时钟频率为170*10^6/(1+16999)=10000Hz。计数周期设置为19999,所以TIM7定时器每(1+19999)*(1/10000)=2000ms产生一次计数溢出,也就是产生一次UEV事件。若UEV事件的中断使能控制位被置1,且TIM6的全局中断已打开,则TIM7每2000ms就会产生一次硬件中断。因为设置了TIM7为单次中断的工作模式,所以TIM7只会在第一次UEV事件发生时产生中断。其它情景,及时自动装载了计数器周期数,也不会产生新的中断事件。
6.配置NVIC
配置Time base的抢占式优先级为0;配置TIM6和TIM7定时器中断抢占式优先级为1。
五、修改代码
上述工程配置文件完成后,自动生成代码,除了下面的文件需要手动添加外。
1.修改include
cpp
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "keyled.h"
/* USER CODE END Includes */
2.初始化
cpp
/* USER CODE BEGIN 2 */
LED1_OFF();
LED2_OFF(); //默认灯是灭的
HAL_TIM_Base_Start_IT(&htim6);//以中断方式启动TIM6
/* USER CODE END 2 */
3.修改main方法
cpp
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
KEYS curKey = ScanPressedKey(KEY_WAIT_ALWAYS);
if (curKey == KEY_RIGHT)
{
LED2_ON(); //点亮LED2
HAL_TIM_Base_Start_IT(&htim7); //以中断方式启动TIM7
HAL_Delay(300); //消除按键后抖动的影响
}
}
/* USER CODE END 3 */
4.重写定时器中断回调函数
cpp
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM6) //TIM6定时周期500ms,使LED1翻转
HAL_GPIO_TogglePin (LED1_GPIO_Port,LED1_Pin);
else if (htim->Instance == TIM7) //TIM7定时周期2000ms,单脉冲模式,使LED2翻转
HAL_GPIO_TogglePin (LED2_GPIO_Port,LED2_Pin);
}
/* USER CODE END 4 */
六、观察运行结果
下载到开发板并加以测试,运行时会发现 LED1周期性闪烁,这是因为TIM6是连续定时模式,每500ms中断一次。按下KeyRight键后LED2点亮,持续约2000ms后LED2熄灭并且不会再度亮起,TIM7只中断了一次,因为TIM7是单次定时模式。再次按下KeyRight键后LED2常亮不再熄灭,再次佐证了TIM7是单次定时模式。