学习笔记:STM32 定时器使能与计数值清零

文章讲述了如何用按键控制小灯亮灭,使用定时器时遇到的问题是enable/disable操作不自动清零计数,导致多次按键后小灯熄灭时间缩短。解决办法是每次点亮后使用TIM_SetCounter(TIM3,0)清零计数值。
摘要由CSDN通过智能技术生成

任务:使用按键控制小灯亮灭。如果小灯点亮时间达10s,自动熄灭。


思路:拆分成按键点灯+定时器控制。按键点灯非常简单不再赘述,在使用定时器时遇到了点小问题:首先想到的是使用enable和disable控制定时器,即:if查询小灯状态,在亮时enable定时器,在灭时disable定时器。具体如下:(控制TIM3)

TIM_Cmd(TIM3,ENABLE);
TIM_Cmd(TIM3,DISABLE);


问题:在第一次点亮小灯后,功能正常(即10s后小灯自然熄灭),但如果多次按下按钮,最后一次点亮小灯后,小灯熄灭的时间明显不足10s。


原因:若小灯亮,定时器被enable,进行计数,按下按钮,小灯熄灭,定时器被disable。虽然此时计数停止,但定时器中的计数值(存放在TIMx 计数器 (TIMx_CNT)) 中并没有被清零,再次点亮时实际的计数是在上一次的计数基础之上进行的,导致小灯自然熄灭的时间少于设定值10s,具体少多少取决于之前计数总数(即上n次小灯从亮到熄灭的时间之和)。


解决:不再使用enable和disable,使用
TIM_SetCounter(TIM3,0);

在每次点亮后清零计数值即可重新计数10s。


总结:enable和disable不对计数值进行清零,需要清零时使用

TIM_SetCounter(TIM3,0);

STM32F103C8T6上实现这个功能,你需要使用基本的定时器配置以及GPIO控制LED。这里提供一个基于 TIM1 定时器中断的例子,同时结合 EXTI 中断捕获按键事件。 首先,包括必要的头文件: ```c #include "stm32f10x.h" #include "stm32f10x_tim.h" #include "stm32f10x_exti.h" ``` 然后设置TIM1定时器为PWM模式,并设置定时器计数: ```c void TIM_Configuration(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM1, ENABLE); TIM_TimeBaseInitTypeDef.TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 999; // 需要调整为0.5s闪烁,假设系统时钟频率是72MHz,则0.5s等于3600000/72M * 2^16 = 999 TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 7200000) - 1; // 根据实际时钟频率调整 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_COUNTERMODE_UP; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, ENABLE); } ``` 创建延时函数用于处理闪烁间隔: ```c static void delay(uint32_t time_in_ms) { while(time_in_ms--) { __WFI(); } } ``` 按键中断配置: ```c void EXTI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // 如果按键连接到GPIOA,需要开启对应外设时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 按键pin GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_Line_0; // 对应按键的EXTI线 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 当按键按下时触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); } void EXTI_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line_0) != RESET) { // 检查是否按键按下 EXTI_ClearITPendingBit(EXTI_Line_0); // 清除中断标志 // 开始新一轮闪烁周期 } } ``` 主循环中处理定时器中断和按键中断: ```c int main(void) { // 初始化硬件 TIM_Configuration(); EXTI_Init(); while (1) { if (TIM_GetITStatus(TIM1, TIM_IT_Update)) { // 判断是否有定时器中断 TIM_ClearFlag(TIM1, TIM_FLAG_Update); // 清除中断标志 if (!flash_flag) { // 初始状态 GPIO_SetBits(GPIOA, GPIO_Pin_1); // LED点亮 flash_flag = 1; // 调用延时函数等待5s delay(5000); GPIO_ResetBits(GPIOA, GPIO_Pin_1); // LED熄灭 } else { // 等待0.5s闪烁 delay(500); } } if (button_pressed()) { // 检查按键是否按下 // 恢复初始状态并重新开始闪烁 flash_flag = 0; GPIO_ResetBits(GPIOA, GPIO_Pin_1); } } } ``` 记得在`main()`函数内添加对应的按钮检测函数`button_pressed()`和GPIO相关的宏定义等其他初始化代码,这取决于你的具体硬件配置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值