今天学习STM32 的通用定时器:TIMx (TIM2、TIM3、TIM4 和 TIM5)。
定时器比较复杂,功能繁多,这里我们就说最基本的计数功能。
1.定时器的时钟从哪里来?
定时器的时钟来源有 4 个:
1)内部时钟(CK_INT)
2)外部时钟模式 1:外部输入脚(TIx)
3)外部时钟模式 2:外部触发输入(ETR)
4)内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)
这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。我们的实验选择内部时钟。
注意:这里的 CK_INT时钟是从 APB1 倍频(*1或者*2)的来的:
如果 APB1 的时钟分频数设置为 1,那么就等于PCLK1;
如果 APB1 的时钟分频数设置不等于1,那么就等于PCLK1*2。
本实验中,APB1的预分频=2,所以TIMxCLK = PCLK1 * 2 = 36MHz * 2 = 72MHz.
看图就明白了。
2.两个关键的参数
1) PSC[15:0]:预分频器的值 (Prescaler value)
计数器的时钟频率CK_CNT等于F_CK_PSC /(PSC[15:0]+1)。
假设我们的PSC[15:0]取值是7199,那么F_timx = 72MHz / 7200 = 10KHz,T = 1/10000 s
2) ARR[15:0]: 自动重装载的值 (Auto reload value)
假设我们令其等于4999,如果设置了更新中断,那么中断的周期是 (4999+1)* 1/10000 s = 0.5s
3.代码怎么写?
//TIM3的初始化 //时钟是72M //arr : 自动重装载值 //psc: 预分频值 void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //外设时钟使能 //TIM3初始化 TIM_TimeBaseStructure.TIM_Period = arr; //自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频值 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //使能更新中断 //中断优先级配置 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM3, ENABLE); //开启时钟 }中断程序如下
//定时器3的中断服务程序 void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //发生了更新中断 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志 LED1=!LED1; //LED翻转 } }主函数如下
int main(void) { delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组 LED_Init(); //LED初始化 TIM3_Int_Init(4999,7199);//定时器3初始化 // T = 1/[72MHz/(7199+1)] * (4999+1) s = 0.5s while(1) { LED0=!LED0; delay_ms(200); } }
仿真结果: