第27章 通用定时器-定时
第二十七章 通用定时器-定时
1. 硬件设计
TIM输入stm32内部资源无需硬件设计,led电路我们也已经分析过了
2. 软件设计
2.1 编程大纲
-
TIM相关参数宏定义
-
配置NVIC和TIM工作模式
-
中断服务函数
-
主函数测试
2.2 代码分析
2.2.1 TIM相关参数宏定义
#ifndef __GENERAL_TIM_H
#define __GENERAL_TIM_H
#include "stm32f10x.h"
#define TIMx TIM2
#define TIMx_Period 999
#define TIMx_Prescaler 71
#define TIM_IRQ TIM2_IRQn
#define TIM_IRQHandler TIM2_IRQHandler
void TIMx_Init(void);
#endif /* __GENERAL_TIM_H */
2.2.2 TIM初始化配置更新中断
#include "GeneralTim.h"
void TIMx_Init(void)
{
/* NVIC中断优先级设置 */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM MODE配置*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = TIMx_Period; // 定时器周期999
TIM_TimeBaseStructure.TIM_Prescaler = TIMx_Prescaler; // 定时器分频系数71
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频系数1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIMx, TIM_FLAG_Update);
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); // 使能计数器中断
TIM_Cmd(TIMx, ENABLE);
}
对定时器的配置简要说明如下:
- 定义结构体:定义用于定时器基础配置的结构体
TIM_TimeBaseInitTypeDef
。 - 开启时钟:启用定时器的时钟。这里假设
GENERAL_TIM_APBxClock_FUN
是一个宏或函数,用于使能定时器时钟。 - 自动重装载寄存器:设置定时器的自动重装载寄存器的值,这决定了定时器的溢出周期。
- 时钟预分频:设置时钟预分频数,影响定时器的计数频率。
- 时钟分频因子:设置时钟分频因子(未用到可以保持默认值)。
- 计数模式:设置计数模式为向上计数。
- 重复计数器:设置重复计数器的值(未用到可以保持默认值)。
- 初始化定时器:根据配置初始化定时器。
- 清除中断标志:清除定时器更新中断标志位,确保中断不会立即触发。
- 开启中断:启用定时器更新中断。
- 使能计数器:启动计数器,使定时器开始计数。
2.2.3 主函数测试及中断服务函数
// 通用定时器TIMx,x[2,3,4,5]定时应用
#include "stm32f10x.h"
#include "led.h"
#include "GENERALTim.h"
#include "usart.h"
uint32_t time = 0;
int main(void)
{
LED_Init();
USART_Config();
TIMx_Init();
while(1)
{
if(time == 1000) // 1000*1 = 1s
{
time = 0;
printf("这是一个由TIM2产生中断发出的句子哦\r\n");
LED1_TOGGLE();
}
}
}
void TIM_IRQHandler (void)
{
if(TIM_GetITStatus(TIMx, TIM_IT_Update) != RESET)
{
time++;
TIM_ClearITPendingBit(TIMx, TIM_FLAG_Update);
}
}
这个程序应该比较简单了,就是利用定时器进行定时,到达一秒后,定时器更新,LED状态取反
3. 小结
照例,我们还是来回顾一下基本流程,尽管这个实验很简单:
-
配置系统时钟
-
启用定时器时钟
-
配置定时器基础设置
-
使能定时器中断(如果需要)
-
启动定时器
#include "stm32f0xx.h" // 包含STM32F0系列的头文件
void TIM2_IRQHandler(void); // 定义定时器中断处理函数原型
void TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1. 启用TIM2时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 2. 配置TIM2的基础设置
TIM_TimeBaseStructure.TIM_Period = 7999; // 定时器周期
TIM_TimeBaseStructure.TIM_Prescaler = 999; // 时钟预分频
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
// 初始化定时器
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 3. 清除TIM2更新中断标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
// 4. 使能TIM2更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// 5. 配置定时器中断优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 6. 启动TIM2
TIM_Cmd(TIM2, ENABLE);
}
// 定时器中断处理函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
// 处理定时器中断
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 在这里执行你的定时任务
}
}
int main(void)
{
// 系统初始化代码
SystemInit();
// 配置TIM2
TIM2_Config();
while (1)
{
// 主循环中可以执行其他任务
}
}
2024.9.12 第一次修订,后期不再维护
2025.1..24 优化代码
本文作者:hazy1k
本文链接:https://www.cnblogs.com/hazy1k/p/18410478
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步