打印
[STM32F4]

timer输入捕获测频率偶尔会得到真实值的一半

[复制链接]
2066|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tvrgt|  楼主 | 2020-9-5 19:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用了定时器的输入捕获功能来测得频率,有两个中断,一个是上升沿信号中断,一个是计数器溢出中断,我现在不懂那个500 是咋回事,测着测着突然出来这么一个,每次都是实际值的一半
代码,上升沿中断和溢出中断, 第一次溢出后开始取数,用上这次上升沿的数值减去一次上升沿的数值得出信号源频率值,但是偶尔会出现捕获值翻倍,好像漏掉了一次上升沿一样,我开启了 溢出判断也并没有进入贴一下中断服务函数
void TIMER2_IRQHandler(void)
{
           if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_UP))
                 {
                         timer_interrupt_flag_clear(TIMER2,TIMER_INT_UP);
                         timer2_counter_overflow++;
       timer2_interrupt_clear();
                         update_flag++;
                  if(timer2_counter_overflow==2)
                         {
                         timer2_interrupt_disable(); //double time capture,????????g???????2.????????
                   timer_disable(TIMER2);
                         timer2_counter_overflow=0;
       timer2_interrupt_clear();
                   }
                 }
                 
    if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH0))
    {
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
/* !!!!!!!!!! */interrupt_flag1++; /* !!!!!!!!!!!!!! */      
            /* read channel 0 capture value */
        /* read channel 0 capture value */
                        if((timer2_counter_overflow==1) && (RESET == timer_flag_get(TIMER2,TIMER_INTF_CH0OF)))//wu yi chu
                                {
        if(0 == ccnumber0)
        {
        CH0_CAPTURE_OLD = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0)+1;
         ccnumber0 = 1;
        }   
        else if(1 == ccnumber0)
        {
        CH0_CAPTURE_NEW = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0)+1;
        if(CH0_CAPTURE_NEW > CH0_CAPTURE_OLD)
        {
        ic1value = CH0_CAPTURE_NEW - CH0_CAPTURE_OLD;
        }
        else{
                                                ic1value = ((0xFFFF - CH0_CAPTURE_OLD) + CH0_CAPTURE_NEW);
                                                }                        
                                                fre_highcapture_1= 10000000/ ic1value;
/* !!!!!!!!!! */fre_highcapture_1_OLD=fre_highcapture_1;
            if(fre_highcapture_1<9980)
            {         
/* !!!!!!!!!! */int_CH0_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }
            if(fre_highcapture_1>10012)
            {         
/* !!!!!!!!!! */int_CH0_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }                                                
              int_CH0_flag=1;
              ccnumber0 = 0;
          }
        }                              

                  if((timer2_counter_overflow==1) &&(SET == timer_flag_get(TIMER2,TIMER_INTF_CH0OF)))//you yi chu
                   {
                          timer_flag_clear(TIMER2,TIMER_INTF_CH0OF);
/* !!!!!!!!!! */fre_highcapture_1=fre_highcapture_1_OLD;
/* !!!!!!!!!! */timer2_interrupt_disable();  /* !!!!!!!!!! */     
/* !!!!!!!!!! */timer_disable(TIMER2);       /* !!!!!!!!!!!!!!! */         
                          int_CH0_flag=1;
                           ccnumber0 = 0;
                   }      
      }                       
    if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH1))
                        {
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH1);
/* !!!!!!!!!! */ interrupt_flag2++; /* !!!!!!!!!!!! */      
        /* read channel 0 capture value */
                        if((timer2_counter_overflow==1) && (RESET == timer_flag_get(TIMER2,TIMER_INTF_CH1OF)))
                                {
        if(0 == ccnumber1)
        {
        CH1_CAPTURE_OLD = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_1)+1;
         ccnumber1 = 1;
        }
        else if(1 == ccnumber1)
        {
         CH1_CAPTURE_NEW = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_1)+1;
         if(CH1_CAPTURE_NEW > CH1_CAPTURE_OLD)
           {
                        ic2value = CH1_CAPTURE_NEW - CH1_CAPTURE_OLD;
           }
       else{
          ic2value = ((0xFFFF - CH1_CAPTURE_OLD) + CH1_CAPTURE_NEW);
           }                        
            fre_highcapture_2= 10000000/ ic2value;
/* !!!!!!!!!! */fre_highcapture_2_OLD=fre_highcapture_2;
            if(fre_highcapture_2<9980)
            {         
/* !!!!!!!!!! */int_CH1_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }
            if(fre_highcapture_2>10012)
            {         
/* !!!!!!!!!! */int_CH1_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }   
            int_CH1_flag=1;
            ccnumber1 = 0;  
        }
       }

                   if((timer2_counter_overflow==1) &&(SET == timer_flag_get(TIMER2,TIMER_INTF_CH1OF)))
             {
                    timer_flag_clear(TIMER2,TIMER_INTF_CH1OF);
                    fre_highcapture_2=fre_highcapture_2_OLD;
/* !!!!!!!!!! */timer2_interrupt_disable();  /* !!!!!!!!!! */     
/* !!!!!!!!!! */timer_disable(TIMER2);       /* !!!!!!!!!!!!!!! */
                    int_CH1_flag=1;
                     ccnumber1 = 0;
             }      
    }
    if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH2))
    {
        /* clear channel 0 interrupt bit */
     timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH2);
/* !!!!!!!!!! */ interrupt_flag3++;/* !!!!!!!!!! */
                        if((timer2_counter_overflow==1) && (RESET == timer_flag_get(TIMER2,TIMER_INTF_CH2OF)))
                        {
        if(0 == ccnumber2)
        {
        CH2_CAPTURE_OLD = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_2)+1;
         ccnumber2 = 1;
        }
        else if(1 == ccnumber2)
        {         
         CH2_CAPTURE_NEW = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_2)+1;
         if(CH2_CAPTURE_NEW > CH2_CAPTURE_OLD)
          {
                      ic3value = CH2_CAPTURE_NEW - CH2_CAPTURE_OLD;
          }
                     else
         {
                            ic3value = ((0xFFFF - CH2_CAPTURE_OLD) + CH2_CAPTURE_NEW);
                                 }                        
                                fre_highcapture_3= 10000000/ ic3value;
                                if(fre_highcapture_3<9980)
                                {         
/* !!!!!!!!!! */int_CH2_flag=1;  /* !!!!!!!!!!!!!!!!! */        
                                }
                                if(fre_highcapture_3>10012)
                                {         
/* !!!!!!!!!! */int_CH2_flag=1;  /* !!!!!!!!!!!!!!!!! */        
                                }
                                int_CH2_flag=1;
                                ccnumber2 = 0;
       }
     }
                if((timer2_counter_overflow==1) && (SET == timer_flag_get(TIMER2,TIMER_INTF_CH2OF)))
                 {
                        timer_flag_clear(TIMER2,TIMER_INTF_CH2OF);
/* !!!!!!!!!! */fre_highcapture_3=fre_highcapture_3_OLD;
/* !!!!!!!!!! */timer2_interrupt_disable();  /* !!!!!!!!!! */     
/* !!!!!!!!!! */timer_disable(TIMER2);       /* !!!!!!!!!!!!!!! */
                        int_CH2_flag=1;
                        ccnumber2 = 0;
                 }      

    }
    if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH3))
    {
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH3);
/* !!!!!!!!!! */interrupt_flag4++;/* !!!!!!!!!! */
                        if((timer2_counter_overflow==1) && (RESET == timer_flag_get(TIMER2,TIMER_INTF_CH3OF)))
                        {
        if(0 == ccnumber3)
        {
         CH3_CAPTURE_OLD = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_3)+1;
         ccnumber3 = 1;
        }
        else if(1 == ccnumber3)
        {
         CH3_CAPTURE_NEW = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_3)+1;
         if(CH3_CAPTURE_NEW > CH3_CAPTURE_OLD)
           {
                        ic4value = CH3_CAPTURE_NEW - CH3_CAPTURE_OLD;
           }
        else{
            ic4value = ((0xFFFF - CH3_CAPTURE_OLD) + CH3_CAPTURE_NEW);
            }                        
          fre_highcapture_4 = 10000000/ ic4value;
/* !!!!!!!!!! */fre_highcapture_4_OLD=fre_highcapture_4;
            if(fre_highcapture_4<9980)
            {         
/* !!!!!!!!!! */int_CH3_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }
            if(fre_highcapture_4>10012)
            {         
/* !!!!!!!!!! */int_CH3_flag=1;  /* !!!!!!!!!!!!!!!!! */        
            }
            int_CH3_flag=1;     
            ccnumber3 = 0;
        }
      }

                 if((timer2_counter_overflow==1) && (SET == timer_flag_get(TIMER2,TIMER_INTF_CH3OF)))
                 {
                        timer_flag_clear(TIMER2,TIMER_INTF_CH3OF);
/* !!!!!!!!!! */fre_highcapture_4=fre_highcapture_4_OLD;/* !!!!!!!!!! */
/* !!!!!!!!!! */timer2_interrupt_disable();  /* !!!!!!!!!! */     
/* !!!!!!!!!! */timer_disable(TIMER2);       /* !!!!!!!!!!!!!!! */
                        int_CH3_flag=1;
                        ccnumber3 = 0;
                 }
   }
}

使用特权

评论回复
沙发
tvrgt|  楼主 | 2020-9-6 15:31 | 只看该作者
香水城 发表于 2020-9-6 14:26
假定待测信号周期短于定时器计数周期。 你应该测量两次上沿捕捉事件或两次下沿捕捉事件才合理啊。

这个没有问题,问题是出现漏掉一次中间捕获值,或者说是没有捕获到

使用特权

评论回复
板凳
香水城| | 2020-9-7 10:03 | 只看该作者
硬件捕捉是不会丢的,除非你软件处理上出了问题,比方代码处理过程漏掉了1次捕捉。

代码精简点,尤其被捕捉信号频率较高时。

使用特权

评论回复
地板
tvrgt|  楼主 | 2020-9-7 14:30 | 只看该作者
香水城 发表于 2020-9-7 10:03
硬件捕捉是不会丢的,除非你软件处理上出了问题,比方代码处理过程漏掉了1次捕捉。

代码精简点,尤其被捕 ...

我设了捕获溢出标志查询,并未发生漏掉的情况
按您说的精简处理时间,那也只是会降低出错的机率而不能完全消除吧

使用特权

评论回复
5
香水城| | 2020-9-8 10:15 | 只看该作者
tvrgt 发表于 2020-9-7 14:30
我设了捕获溢出标志查询,并未发生漏掉的情况
按您说的精简处理时间,那也只是会降低出错的机率而不能完 ...

你如果确认没有漏掉溢出,那就可能是你信号本身或代码处理方面的问题。

精简处理时间不能停留在简单降低出错机会,要保证不能出错,尤其代码处理上。如果不能保证,那么
这个测法就用不了,得另想办法。

不知你现在的被测信号频率是多少,我之前用F411做过输入信号的周期和占空比的测试,
当时5个us以上是没问题的。【代码应该还有一定优化空间】

我是使用PWM输入的方法 或单通道上下沿翻转方法都验证过的。

使用特权

评论回复
6
chengxiaoke| | 2021-7-23 16:33 | 只看该作者
楼主这个问题解决了吗?我也想要一段输入捕获历程,能否发我邮箱里,2290085314@qq.COM,谢谢楼主大大

使用特权

评论回复
7
乖了去| | 2022-5-31 22:03 | 只看该作者
GD32定时器输入捕获有bug

使用特权

评论回复
8
sadicy| | 2022-6-1 20:15 | 只看该作者
感觉是软件问题,查代码吧

使用特权

评论回复
9
通讯不上| | 2024-2-21 08:58 | 只看该作者
楼主解决了吗,我现在也碰到了同样的问题。目前已经排除了信号的问题,因为我用pwm模式去采频率的话是没有这个问题的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

8

帖子

0

粉丝