OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5086|回复: 4

战舰开发板输入捕获例程 出现漏记定时器溢出中断次数

[复制链接]

7

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2015-4-20
在线时间
32 小时
发表于 2022-3-9 13:43:12 | 显示全部楼层 |阅读模式
20金钱
本帖最后由 gongpeng192 于 2022-3-9 22:18 编辑

我把系统时钟更改为64M,输入捕获频率改为64M 会出现漏记1次定时器溢出次数的现象,我怀疑是定时器更新中断跟输入捕获中断同时发生了,然后把定时器更新中断漏掉了,有没有这种可能?求大神解释下,谢谢。
int main(void)
{
        long long temp=0;
        
    HAL_Init();                                     //初始化HAL库   
    Stm32_Clock_Init(RCC_PLL_MUL8);           //设置时钟,72M
        delay_init(64);                               //初始化延时函数
        uart_init(115200);                                        //初始化串口
        LED_Init();                                                        //初始化LED        
//    TIM3_PWM_Init(500-1,64-1);               //72M/72=1M的计数频率,自动重装载为500,那么PWM频率为1M/500=2kHZ
    TIM5_CH1_Cap_Init(0XFFFF,0);                //以64Mhz的频率计数
        
        while(1)
    {
//        delay_ms(10);
//                TIM_SetTIM3Compare2(TIM_GetTIM3Capture2()+1);
//                if(TIM_GetTIM3Capture2()==300)TIM_SetTIM3Compare2(0);        
        if(TIM5CH1_CAPTURE_STA&0X8000)        //成功捕获到了一次高电平
                {
                        temp=TIM5CH1_CAPTURE_STA&0X3FFF;
                        temp*=65536;                                     //溢出时间总和
                        temp+=TIM5CH1_CAPTURE_VAL;      //得到总的高电平时间
                        printf("%lld ",temp);//打印总的高点平时间
                        TIM5CH1_CAPTURE_STA=0;          //开启下一次捕获
                }
    }
}




//定时器更新中断(计数溢出)中断处理回调函数, 该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行
{
        if((TIM5CH1_CAPTURE_STA&0X8000)==0)                                //还未成功捕获
        {
                if(TIM5CH1_CAPTURE_STA&0X4000)                                //已经捕获到高电平了
                {
                        if((TIM5CH1_CAPTURE_STA&0X3FFF)==0X3FFF)        //高电平太长了
                        {
                                TIM5CH1_CAPTURE_STA|=0X8000;                        //标记成功捕获了一次
                                TIM5CH1_CAPTURE_VAL=0XFFFF;
                        }else TIM5CH1_CAPTURE_STA++;
                }         
        }               
}

//定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
        if((TIM5CH1_CAPTURE_STA&0X8000)==0)                                //还未成功捕获
        {
                if(TIM5CH1_CAPTURE_STA&0X4000)                                //捕获到一个下降沿                 
                {                                 
                        TIM5CH1_CAPTURE_STA|=0X8000;                                //标记成功捕获到一次高电平脉宽
            TIM5CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);//获取当前的捕获值.
                        TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
            TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//配置TIM5通道1上升沿捕获
                }
                else                                                                                  //还未开始,第一次捕获上升沿
                {
                        TIM5CH1_CAPTURE_STA=0;                                        //清空
                        TIM5CH1_CAPTURE_VAL=0;
                        TIM5CH1_CAPTURE_STA|=0X4000;                                //标记捕获到了上升沿
                        __HAL_TIM_DISABLE(&TIM5_Handler);              //关闭定时器5
                        __HAL_TIM_SET_COUNTER(&TIM5_Handler,0);
                        TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
                        TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获
                        __HAL_TIM_ENABLE(&TIM5_Handler);                //使能定时器5
                }                    
        }               
}


最佳答案

查看完整内容[请看2#楼]

你要关定时器那就没办法了,你可以全局只关捕获中断啊,溢出中断就让它一直进中断,看你的逻辑应该是计算频率之类的,溢出中断加个判断捕获有效的条件,占用不了多少周期,你的输入捕获频率要是大于定时器时钟的1/5,建议你换主频更高的IC
我要一步一步往上爬    在最高点乘着叶片往前飞   小小的天 留过的泪和汗   总有一天我有属于我的天
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

2131

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4731
金钱
4731
注册时间
2015-1-10
在线时间
591 小时
发表于 2022-3-9 13:43:13 | 显示全部楼层
gongpeng192 发表于 2022-3-11 22:40
可能会存在定时器溢出中断跟输入捕获中断同时发生的现象,假设先进了输入捕获中断,在执行输入捕获中断程 ...

你要关定时器那就没办法了,你可以全局只关捕获中断啊,溢出中断就让它一直进中断,看你的逻辑应该是计算频率之类的,溢出中断加个判断捕获有效的条件,占用不了多少周期,你的输入捕获频率要是大于定时器时钟的1/5,建议你换主频更高的IC
回复

使用道具 举报

11

主题

2131

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4731
金钱
4731
注册时间
2015-1-10
在线时间
591 小时
发表于 2022-3-11 09:34:14 | 显示全部楼层
不会,只要中断标志置位就会进中断
回复

使用道具 举报

7

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2015-4-20
在线时间
32 小时
 楼主| 发表于 2022-3-11 22:40:43 | 显示全部楼层
阿侑kevin 发表于 2022-3-11 09:34
不会,只要中断标志置位就会进中断

可能会存在定时器溢出中断跟输入捕获中断同时发生的现象,假设先进了输入捕获中断,在执行输入捕获中断程序的过程中定时器溢出了,后面又把定时器关掉了,这样不就漏掉了一次定时器溢出中断?请指点下,谢谢,我这里实测确实有时候会漏掉一次。
我要一步一步往上爬    在最高点乘着叶片往前飞   小小的天 留过的泪和汗   总有一天我有属于我的天
回复

使用道具 举报

0

主题

1

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2022-4-2
在线时间
23 小时
发表于 2022-6-18 20:08:55 | 显示全部楼层
楼主 我也出现了和你一样的情况 经过了两个小时的debug 我发现不是漏记了一个,而是有时多记了,请注意你的这个函数void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
中的
TIM5CH1_CAPTURE_STA|=0X4000;                      //标记捕获到了上升沿
这一句代码,把或删掉,改成
TIM5CH1_CAPTURE_STA =0X4000;        
应该就可以了。
因为之前可能存在了计数器的溢出,也就意味着TIM5CH1_CAPTURE_STA在你开始有效捕获时溢出次数不为零,这样就导致了多判溢出的情况。
至于你说的在定时器溢出中断跟输入捕获中断同时发生的现象,这是没有影响的,因为TIMx->SR的相对应的位被置位后会触发中断,同时发生若是没有清除两个中断的话就会再进一次中断服务函数而已。
附上我我写的代码关键部分,我测试是可行的
void TIM5_IRQHandler(void)
{
        if (TIM_GetITStatus(TIM5,TIM_IT_CC1))
        {
                if (GetTemp & 0x80)
                {
                        TIM_ClearITPendingBit(TIM5,TIM_IT_CC1);
                        return;
                }
                else if (GetTemp & 0x40)
                {
                        period = (arr+1)*(GetTemp & 0x3F) + TIM_GetCapture1(TIM5) - period;
                        period = period * (psc+1) / 84000000.0;
                        GetTemp |= 0x80;
                        TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);
                }
                else
                {
                        GetTemp = 0x40;
                        period = TIM_GetCapture1(TIM5);
                        TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);
                }
                TIM_ClearITPendingBit(TIM5,TIM_IT_CC1);
        }
        if (TIM_GetITStatus(TIM5,TIM_IT_Update))
        {
                TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
                if ((GetTemp & 0x3F)==0x3F) return;
                GetTemp += 1;
        }
        return;
}
我就是把上文说的那一段代码修改了程序就合理了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 22:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表