最近要用STM32F103RCT6的TIM8做输入捕获,网上不好找到可以直接搬运的代码,然后就移植TIM2的输入捕获做,然后一直遇到匪夷所思的问题!
出现的问题就是,在主函数进入while循环前配置好TIM8之后,进入主函数循环点灯测试,发现程序运行几百次循环后就自动停止了,感觉是跑飞了。一般程序跑飞很多情况下都是中断的部分没设置好,我也排查了问题出现的原因,基本确定就是中断的问题。
这里还有个情况值得提出来,但是我到现在也不知道原因所在:
就是 TIM_ICInitTypeDef TIM_ICInitStructure;
这个句柄放在哪的问题,正点的源码里面把这个放在了捕获定时器配置的函数外,说这个是全局变量,不放在外面的话也许会有问题。测试的时候在内在外确实不一样,放在函数里的话,程序运行几百次循环后就跑飞了,开始跑飞的时刻是固定的;放在函数外的话,大概是运行几千次循环后跑飞,开始跑飞的时刻也是固定的,就是比刚才晚了一会发生。
根据发生的时间,我大致计算了一下程序运行几百次循环后就跑飞对应发生的是什么情况,就是定时器发生更新中断的时刻。如果是因为中断配置的问题导致这种跑飞,那句柄写在外面为什么会推迟跑飞的时间呢?毕竟定时器计时又不会变。
上面这个问题留给有经验的人来解答,下面我说说经过检查后确定出中断配置哪里有问题。
原因就是高级定时器TIM1和TIM8配置时的一些宏定义和函数名有所不同,比如看这张图
我们可以发现,对于通用定时器TIM2TIM3,中断函数就只有类似TIMx_IRQn这样一个整体的;而对于高级定时器TIM1,对应于不同类型的中断,都有对应的中断服务函数,反而没有TIM1_IRQn,TIM8_IRQn这个东西。
在进行高级定时器的中断配置的时候,需要把不同中断类型分开配置,像这样
NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_IRQn; //TIM8更新中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel =TIM8_CC_IRQn ; //TIM8捕获中断
NVIC_Init(&NVIC_InitStructure);
中断服务函数也要分开来写,函数名也一定要对应
void TIM8_CC_IRQHandler(void)
{
if((TIM8CH3_CAPTURE_STA&0X80)==0)
{
if (TIM_GetITStatus(TIM8, TIM_IT_CC3) != RESET)
{
if(TIM8CH3_CAPTURE_STA&0X40)
{
TIM8CH3_CAPTURE_STA|=0X80;
TIM8CH3_CAPTURE_VAL=TIM_GetCapture3(TIM8);
TIM_OC3PolarityConfig(TIM8,TIM_ICPolarity_Rising);
}else
{
TIM8CH3_CAPTURE_STA=0;
TIM8CH3_CAPTURE_VAL=0;
TIM_SetCounter(TIM8,0);
TIM8CH3_CAPTURE_STA|=0X40;
TIM_OC3PolarityConfig(TIM8,TIM_ICPolarity_Falling);
}
}
}
TIM_ClearITPendingBit(TIM8, TIM_IT_CC3);
}
void TIM8_UP_IRQHandler(void)
{ if((TIM8CH3_CAPTURE_STA&0X80)==0)
{
if(TIM_GetITStatus(TIM8, TIM_IT_Update) != RESET)
{
if(TIM8CH3_CAPTURE_STA&0X40)
{
if((TIM8CH3_CAPTURE_STA&0X3F)==0X3F)
{
TIM8CH3_CAPTURE_STA|=0X80;
TIM8CH3_CAPTURE_VAL=0XFFFF;
}else TIM8CH3_CAPTURE_STA++;
}
}
}
TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
}
这样问题就解决了。从通用定时器移植过来的时候血泪教训