这次我们尝试使用中断进行定时。
具体步骤为:
①能定时器时钟。
RCC_APB1PeriphClockCmd();
② 初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit();
③开启定时器中断,配置NVIC。
void TIM_ITConfig();
NVIC_Init();
④使能定时器。
TIM_Cmd();
⑥编写中断服务函数。
TIMx_IRQHandler();
首先我们设置一下TIM,结构体TIM_TimeBaseInitTypeDef中有五个元素,其中除了TIM_RepetitionCounter只能用于TIM1和TIM8之外,其他四个都需要设置。
void TIM2_init(u16 arr, u16 psc)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Period = arr;//重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;//预分频系数
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2,ENABLE);
}
接下来设置NVIC,
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
将两部分合在一起,
void TIM2_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Period = arr;//重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;//预分频系数
TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2,ENABLE);
NVIC_Init(&NVIC_InitStruct);
}
然后需要设置中断服务函数,我们在启动文件中找到TIM2口对应的中断服务函数的函数名,复制过来,
void TIM2_IRQHandler(void) //TIM2中断
{
static u8 i = 0;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 更新中断
{
switch(i)
{
case 0:GPIO_ResetBits(LED_GPIO_PORT, LED_GPIO_PIN);i++;break;
case 1:GPIO_SetBits(LED_GPIO_PORT, LED_GPIO_PIN);i=0;break;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIMx的中断待处理位:TIM 中断源
}
}
这样,每发生一次中断都会使LED灯改变状态。我们想要设置时间是1s,那么我们要如何在主函数中填写函数TIM2_Init()的两个参数呢,通过手册我们可以知道,时间的计算方式为
((psc+1)*(arr+1))/fck
其中fck是频率,比如72MHz对应的fck就是72000000。所以当我们填入arr=9999, psc=7199时,定时就是1s
int main()
{
LED_GPIO_Config();
TIM2_Init(9999,7199);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
while(1);
}
实验现象:小灯每一秒改变一次状态