一、定时器基本介绍
1、定时器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),8个通用定时器(TIM2、TIM3、TIM4、TIM5、TIM9、TIM10、TIM11、TIM12)和2个基本定时器(TIM6、TIM7)
这三种定时器的区别如下:
即:高级定时器具有捕获/比较通道和互补输出,通用定时器只有捕获/比较通道,基本定时器没有以上两者。
本次实验主要采用基础定时器,本次实验是基于STM32f103zet6。
二、基本定时器
基本定时器(TIM6、TIM7)是挂载在APB1总线上的,它们功能相同,是16位的只能向上计数的定时器,只能用于定时。
基本定时器的工作过程:时钟信号通过控制器成为CK_PSC进入预分频器,预分频器对CK_PSC信号进行分频,然后进入计数器开始计数,自动重装载寄存器会储存用户设置的最大值,当计数器的值和这个最大值相等时生成UEV事件中断。
三、HAL程序
实现功能
定时器六采用连续定时模式,定时周期为500ms,以中断的方式启动TIM6 ,在事件回调函数中使LED2的输出反转
定时器7采用单次定时模式,定时周期为5秒,按下按键s1使LED3点亮,同时启动定时器7,,在事件回调函数中使LED3的输出反转
要实现这些功能需要的主要外设:定时器6和7,两个LED灯,一个按键。
CubeMX配置
实验要使用LED灯和按键,可以直接在KEY_LED的.ioc文件上配置,如果没有这个文件问题也不大,这个配置非常简单,这里不再赘述。
定时器6和7的配置如下图:
这两个定时器配置基本一致,主要区别在Mode一栏的One Pulse Mode 这个选项定时器7需要勾选(定时器7采用的单次定时模式),Prescaler配置分频数,在本次实验中,时钟频率配置为72MHz,这里设置为7200-1(因为从0开始计数),Counter Period 为计数周期,这里定时器6设置为5000,即为计数500ms。
主要设置完成,可以生成代码了。
代码实现部分
现在我们生成好了代码,还得实现中断函数,因为当计数器溢出后最终会调用HAL_TIM_PeriodElapsedCallback()函数,HAL中有这个的弱函数,所以即使没有实现这个函数,编译器也不会报错,但是实验现象不正确,所以我们应该先在tim.c文件中实现这个函数的重写:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM6)
{
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
}
if (htim->Instance == TIM7)
{
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
}
}
最后我们就只需要完成主函数的书写即可:
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
HAL_TIM_Base_Start_IT(&htim6);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_SET)
{
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
HAL_TIM_Base_Start_IT(&htim7);
HAL_Delay(300);
}
/* USER CODE BEGIN 3 */
}
这里的按键触发可能现象会不明显,这是因为按键触发有抖动,我这里使用了延时函数进行消抖,效果不是很好,最好可以采用外部中断配合延时检测,这样才能完全消除抖动问题(关于外部中断消抖可以看看我之前的文章).