打印

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

[复制链接]
1219|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tvrgt|  楼主 | 2020-9-5 18:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用了定时器的输入捕获功能来测得频率,有两个中断,一个是上升沿信号中断,一个是计数器溢出中断,我现在不懂那个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;
                 }
   }
}

使用特权

评论回复
沙发
xdqfc| | 2020-9-6 10:48 | 只看该作者
本帖最后由 xdqfc 于 2020-9-6 10:50 编辑

增加从模式的上升沿触发复位功能,设定上升沿捕获,也可以增加通道2的下降沿捕获(GD32好像有瑕疵),一般上升沿中断里面就可以直接读数据了,哪里还需要减什么东西啊,多此一举了,然后换算一下即可,好功能被浪费了,而且楼主的代码量太大,直接看不明白。早前我就用这个功能解码433M的无线电编码信号的(测量脉冲宽度)。

使用特权

评论回复
板凳
xdqfc| | 2020-9-6 10:56 | 只看该作者
这个小项目,楼主居然用了两个中断??

使用特权

评论回复
地板
tvrgt|  楼主 | 2020-9-6 15:27 | 只看该作者
xdqfc 发表于 2020-9-6 10:48
增加从模式的上升沿触发复位功能,设定上升沿捕获,也可以增加通道2的下降沿捕获(GD32好像有瑕疵),一般上 ...

因为要接4个通道,用复位的话其他通道测量的就会受影响,难道是用溢出计数给其通道补偿计数值? 我现在是用溢出控制定时器启动时间,运转2次即停止

使用特权

评论回复
5
tvrgt|  楼主 | 2020-9-6 15:30 | 只看该作者
xdqfc 发表于 2020-9-6 10:56
这个小项目,楼主居然用了两个中断??

用了溢出中断控制启动时间

使用特权

评论回复
6
tvrgt|  楼主 | 2020-9-6 16:36 | 只看该作者
xdqfc 发表于 2020-9-6 10:48
增加从模式的上升沿触发复位功能,设定上升沿捕获,也可以增加通道2的下降沿捕获(GD32好像有瑕疵),一般上 ...

主要的问题是出现漏掉一次中间捕获值,或者说是没有捕获到,计数值是正常的两倍

使用特权

评论回复
7
sonicll| | 2020-9-7 09:29 | 只看该作者
楼主你检查一下你固件库里的 timer_interrupt_flag_clear()这个函数的写法:

旧版固件库:
void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
{
    TIMER_INTF(timer_periph) &= (~(uint32_t)interrupt);
}

新版固件库:
void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
{
    TIMER_INTF(timer_periph) = (~(uint32_t)interrupt);
}

如果是旧版的写法,可能会出现你说的漏掉中断的问题,旧版的写法不是原子操作,可能会出现“清除了不该清除的标志位”这种问题

使用特权

评论回复
8
lvben5d| | 2020-9-7 13:07 | 只看该作者
sonicll 发表于 2020-9-7 09:29
楼主你检查一下你固件库里的 timer_interrupt_flag_clear()这个函数的写法:

旧版固件库:

楼上贴的2个函数  名字一样  但是执行意思不一样,上面是写1清0,写面是直接清0 有点。。

使用特权

评论回复
9
tvrgt|  楼主 | 2020-9-7 14:25 | 只看该作者
sonicll 发表于 2020-9-7 09:29
楼主你检查一下你固件库里的 timer_interrupt_flag_clear()这个函数的写法:

旧版固件库:

这个都检查过了,清中断都是直接写0的

使用特权

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

本版积分规则

2

主题

8

帖子

0

粉丝