定时器理解
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了定时器理解相关的知识,希望对你有一定的参考价值。
一、定时器分类
1.1、通用定时器
TIM2~TIM5是一个向上/向下计数的定时器。
功能:可以定时、输出比较、输入捕捉、每个定时器有四个外部IO。
1.2、基本定时器
TIM6、TIM7 是一个16位的只能向上计数的定时器,没有外部IO口只能定时。
1.3、高级定时器
TIM1和TIM8
16位向上/向下计数的定时器
功能:输出比较、输入捕捉、三相电机互补输出信号、每个定时器有8个外部IO
二、定时器相关概念
2.1、内部时钟
定时器时钟:TIMxCLK
内部时钟:INTCLK
定时器时钟TIMxCLK即内部时钟CK_INT,经过APB1预分频后提供
如果预分频系数为1,则频率不变,否则频率*2
库函数中APB1的预分频系数是2,即PCLK1=36M,即定时器2~7的时钟频率(CK_INT)为72M
1MHz = 1000KHz = 1000 000 Hz
- CLK :AHB总线时钟,由系统时钟SYSCLK 分频得到,一般不分频等于系统时钟,HCLK是高速外设时钟,是给外部设备的,比如内存,flash
- PCLK1:低速APB时钟(PCLK1)
- PCLK2:高速APB时钟(PCLK2)
自定义所需的时钟(例)
- 库函数默认配置系统时钟为72M。
- SYSCLOCK(系统时钟)=HCLK(AHB总线时钟) 库函数的配置 AHB预分频器1分频。
- APB1预分频器8分频 得PCLK1的时钟,72/8=9M,即PCLK 1(APB1外设时钟)=9M
- TIM2~TIM7的时钟(TIMxCLK):由于APB1分频器此处为8分频,因此TIM2~TIM7的时钟频率*2,TIMxCLK =2PCLK1=18M
RCC_PCLK1Config(RCC_HCLK_Div8);
RCC_PCLK2Config(RCC_HCLK_Div8);
定时器TIM2~TIM7的时钟频率为:18M,即内部时钟频率=定时器时钟频率=18M
假定
// CNT计数器计数周期
TIM_TimeBaseStructure.TIM_Period =1000;
// 指定用于除TIM时钟的预分器值
TIM_TimeBaseStructure.TIM_Prescaler = 9-1;
CK_CNT(计数器时钟 )= 内部时钟/内部时钟预分频器的值+1 = 18/9 = 2MHz
CNT计数周期:1000 计数器计数到1000时,如果使能定时器中断,会产生中断溢出(更新)
CNT计数频率:f=1/T = 1/1000
中断时间=period*(prescaler+1)/TIMxCLK = 1000*9000 000 /18000 000 =500微妙
2.2、 计数器时钟(CNT)
CNT是一个16位的计数器,只能向上计数,计数值为:0xFFFF(65535),
当计数器达到自动重装载寄存器的时,产生中断事件,并清零重新计数。
CK_CNT(计数器时钟)=内部时钟(CK_INT)/(TIM_Prescaler+1)
2.3、自动重装载寄存器
/*
Specifies the period value to be loaded into the active
Auto-Reload Register at the next update event.
This parameter must be a number between 0x0000 and 0xFFFF.
*/
TIM_TimeBaseInitStructure.TIM_Period=6000;
自动重装载寄存器ARR是一个16位的寄存器,这里装载着计数器能计数的最大值,当计数到这个值时,如果使能了中断,定时器就会产生溢出中断。
2.5、定时时间计算
定时器的定时时间 =定时器中断周期*中断次数
计数器在CK_CNT在内部时钟的驱动下,计一个数的时间是CK_CLK的倒数
计一个数的时间 = 1/(TIMxCLK/(PSC+1)) 即 psc+1 / TIMxCLK
产生一次中断的时间:1/(分频系数*计数周期)
中断服务函数中定义一个变量T,用于记录中断次数。则定时时间 = 1/CK_CLK*(ARR+1)*T
三、代码
3.1、初始化函数
void TIM3Init(u16 per,u16 psc)
{
// 一、使能时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM4时钟
// 二、初始化定时器参数,包含自动重装载的值,分频系数,计数方式
TIM_TimeBaseInitStructure.TIM_Period=per; // 自动装载值 定时周期
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; // 分频系数 定时器预分频率
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 一分频 时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; // 设置向上计数模式 计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); // 初始化定时器3
// 三、设置定时器中断类型,并使能
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //开启定时器中断
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
// 四、设定定时器中断优先级,使能定时器中断通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; // 定时器中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
// 五、开启定时器
TIM_Cmd(TIM3,ENABLE); //使能定时器
}
3.2、中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)) // TIM3更新(溢出)中断是否产生
{
// 更新中断 中需要执行的操作
}
// Clears the TIMx's interrupt pending bits.
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
设计一个1s的定时器中断
// 定时器产生中断的时间 = (预分频系+1数)*(CNT计数周期)/INT定时器时钟
void TIM3Init(1000,72000-1);
72000 000Hz /72MHz = 1s
以上是关于定时器理解的主要内容,如果未能解决你的问题,请参考以下文章