赞
踩
一、原理
(1)STM32的通用定时器是一个通过可编程预分频器(Prescaler/PSC)驱动的16位自动重装主计数器(Counter Period/ARR)构成。可以对内部时钟或触发源以及外部时钟或触发源进行计数。
(2)通用定时器的基本工作原理:
首先,定时器时钟信号送入16位可编程预分频器,该预分频器系数为0~65535之间的任意数值。预分频器溢出后,会向16位的主计数器发出一个脉冲信号。
预分频器,本质上是一个加法计数器,预分频系数实际上就是加技术的溢出值。
(3)定时器发生中断时间的计算方法:
定时时间 =(Prescaler + 1)×(Counter Period + 1)× 1 / 定时器时钟频率
例:
时钟信号1KHz,Prescaler = 9,Counter Period = 999,定时时间=?
时钟信号是1KHz,时间就是1/1KHz = 1ms
经过预分频器,1*(9+1) = 10ms,即10ms 主计数器的计数加一,
主计数器要计数999+1个,所以总定时时间=10ms*1000 = 10S
二、定时时间的计算
PSC 和 ARR 都是16位的寄存器,所以取值都是从 0~65535,在此基础上,加 1 之后才是实际的分频值和计数值。
计数器计数频率:CK_CNT = CK_PSC / (PSC+1)
计一个数的时间 :t = 1 / CK_CNT
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR+1)
定时周期:T = 1 / CK_CNT_OV
三、时基初始化结构体详解
typedef struct
{
uint16_t TIM_Prescaler; // 预分频值
uint16_t TIM_CounterMode; // 计数模式,基本定时器只能向上计数
uint32_t TIM_period; // 自动重装载值
uint16_t TIM_ClockDivison; // 外部输入时钟分频因子,基本定时器没有
uint8_t TIM_RepetitionCounter; // 重复计数器,基本定时器没有,高级定时器专用
} TIM_TimeBaseInitTypeDef;
虽然时基初始化结构体有 5 个成员,但对于基本定时器只需设置其中两个就可以。
四、举例
在这里我们以基本定时器 TIM6 为例,实现定时 1s 。
配置定时器相关内容
void Timer_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟, 即内部时钟 CK_INT=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
// 自动重装载寄存器的值 (计数值)
TIM_TimeBaseStructure.TIM_Period = 10000 - 1;
// 预分频数为 7200-1,则驱动计数器的时钟 CK_CNT = CK_INT / 7200 = 10KHz
TIM_TimeBaseStructure.TIM_Prescaler= 7200 - 1;
// 时钟分频因子 ,基本定时器没有,不用管
//TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
//TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,基本定时器没有,不用管
//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器时基单元
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
// 使能定时器中断
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
// 使能定时器
TIM_Cmd(TIM6, ENABLE);
}
配置 NVIC
void Timer_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 配置 NVIC 为优先级组 1
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; // 选择对应的中断号
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
NVIC_Init(&NVIC_InitStructure);
}
编写中断服务程序
void TIM6_IRQHandler(void)
{
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) // 检测中断标志位
{
// 处理中断事件...
TIM_ClearITPendingBit(TIM6, TIM_IT_Update); // 清除中断标志位
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。