STM32定时器之四大功能之定时器中断
1.定时器定时中断
定时器中断的时钟源我们既可以选择内部时钟源,同时也可以选择外部时钟源。
我们选择RCC内部时钟作为时钟源,内部时钟经过预分频器进行分频,计数器进行自增,不断与自动重装寄存器进行比较,当CNT=ARR时,这时就会产生中断响应或者是事件响应,TIM会立即向NVIC发出中断申请,经NVIC裁决后,即立即中断主程序,使CPU执行TIM对应的中断程序。
简单来说定了一个闹钟,定时时间到了,我们该去处理某件事了!
1.1定时器中断步骤
(1)开启RCC时钟
//开启时钟TIM2的时钟线是APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
(2)选择时基单元的时钟源,选择内部时钟源
//配置时钟源,选择TIM2为内部时钟
TIM_InternalClockConfig(TIM2);
(3)配置时基单元
/时基单元初始化
TIM_TimeBaseInitTypeDef TIM_timBaseInitStructure;
TIM_timBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;//一分频
TIM_timBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
//定1s时间
TIM_timBaseInitStructure.TIM_Period=10000-1;//自动重装值计数
TIM_timBaseInitStructure.TIM_Prescaler=7200-1;//对72MHz进行7200次分频
TIM_timBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器是高级定时器才有的
TIM_TimeBaseInit(TIM2,&TIM_timBaseInitStructure);
(4)配置中断输出控制
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手动清除中断更新标志位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启定时器更新中断
(5)配置NVIC,在NVIC中,打开定时器中断的通道,并分配一个优先级
/*NVIC中断分组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC为分组2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//定时器2在NVIC中的通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);//开启定时器中断
}
1.2定时器中断主函数
没来一次定时器中断实现Num++。
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1,1,"Num:");
while(1)
{
OLED_ShowNum(1,5,Num,5);
}
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//更新中断标志位等于SET
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
1.3定时器外部时钟
在这个程序中,我们选择的时钟源位外部时钟
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
//开启时钟TIM2的时钟线是APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//开启GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_IniyStructure;
GPIO_IniyStructure.GPIO_Mode= GPIO_Mode_IPU;
GPIO_IniyStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_IniyStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_IniyStructure);
//配置时钟源,选择ETR外部时钟模式2,外部触发预分频器不分频,高电平有效,滤波器参数
TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
//外部触发预分频器不分频
//时基单元初始化
TIM_TimeBaseInitTypeDef TIM_timBaseInitStructure;
TIM_timBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;//一分频
TIM_timBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
TIM_timBaseInitStructure.TIM_Period=10-1;//自动重装值计数
TIM_timBaseInitStructure.TIM_Prescaler=1-1;//
TIM_timBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器是高级定时器才有的
TIM_TimeBaseInit(TIM2,&TIM_timBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手动清除中断更新标志位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启定时器更新中断
/*NVIC中断分组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC为分组2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//定时器2在NVIC中的通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);//开启定时器中断
}
// 函 数:返回定时器CNT的值
// * 参 数:无
// * 返 回 值:定时器CNT的值,范围:0~65535
uint16_t Timer_GetCounter(void)
{
return TIM_GetCounter(TIM2);
}
1.4定时器外部时钟中断主函数
当CNT自加到ARR=10时,触发定时器中断Num++;
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1,1,"Num:");
OLED_ShowString(2,1,"CNT:");
while(1)
{
OLED_ShowNum(1,5,Num,5);//不断刷新显示Num变量
OLED_ShowNum(2,5,Timer_GetCounter(),5);//不断刷新显示CNT的值
}
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//更新中断标志位等于SET
{
Num++;//Num变量自增,用于测试定时中断
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
作者:染予