用两个定时器的各两路输入捕获测量4路频率,测量不准确

2019-07-21 08:57发布

背景
1、我同时测量4路频率信号,频率范围50~250Hz范围;
2、为了减轻单个定时器输入捕获的压力,以及减小输入捕获中断函数中不同通道之间的采集干扰,我使用定时器4的通道1和通道2,和定时器2的通道3和通道4来采集四路频率信号。
试验发现:
1、单独采集每一路频率,误差为1Hz;
2、同时采集其中的任意两路,测量频率显示一直在变化,而且变化还比较大。
请问这是什么原因造成的?该如何改进?
先贴一段代码吧
  //定时器4通道1和通道2输入捕获配置
void TIM4_Cap_Init(u16 arr,u16 psc)

 GPIO_InitTypeDef      GPIO_InitStructure;
 TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
 TIM_ICInitTypeDef      TIM4_ICInitStructure;  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   //使能TIM4时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //使能GPIOB时钟
 
 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6 | GPIO_Pin_7 ;  //PB6,PB7 清除之前设置 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;       //下拉输入 
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 GPIO_ResetBits(GPIOB,GPIO_Pin_6); 
 GPIO_ResetBits(GPIOB,GPIO_Pin_7); 
 
 //初始化定时器4 TIM4 
 TIM_TimeBaseStructure.TIM_Period = arr;   //设定计数器自动重装值
 TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器  
 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;    //设置时钟分割:TDTS = Tck_tim
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数模式
 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
 //初始化TIM4输入捕获参数
 TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1;       //CC1S=01  选择输入端 IC1映射到TI1上
  TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //上升沿捕获
  TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
  TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;     //配置输入分频,不分频
  TIM4_ICInitStructure.TIM_ICFilter = 0x00;           //IC1F=0000 配置输入滤波器 不滤波
  TIM_ICInit(TIM4, &TIM4_ICInitStructure);
 
 TIM4_ICInitStructure.TIM_Channel = TIM_Channel_2;       //CC1S=02  选择输入端 IC1映射到TI2上
  TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //上升沿捕获
  TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
  TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;     //配置输入分频,不分频
  TIM4_ICInitStructure.TIM_ICFilter = 0x00;           //IC1F=0000 配置输入滤波器 不滤波
  TIM_ICInit(TIM4, &TIM4_ICInitStructure);               
 
 TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 
  TIM_Cmd(TIM4,ENABLE );  //使能定时器4
}  
//定时器4中断服务程序 
void TIM4_IRQHandler(void)
{
  if((TIM4CH1_CAPTURE_STA&0X80)==0)     //还未成功捕获 
 {  
  if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
  {    
   if(TIM4CH1_CAPTURE_STA&0X40)     //已经捕获到高电平了
   {
    if((TIM4CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    {
     TIM4CH1_CAPTURE_STA|=0X80;    //标记成功捕获了一次
     TIM4CH1_CAPTURE_VAL=0XFFFF;
    }else TIM4CH1_CAPTURE_STA++;
   } 
  }
  
  if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
  { 
   if(TIM4CH1_CAPTURE_STA&0X40)  //捕获到一个下降沿   
   {      
    TIM4CH1_CAPTURE_STA|=0X80;  //标记成功捕获到一次上升沿
    TIM4CH1_CAPTURE_VAL=TIM_GetCapture1(TIM4);
      TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Falling); //CC1P=0 设置为上升沿捕获
   }else               //还未开始,第一次捕获上升沿
   {
    TIM4CH1_CAPTURE_STA=0;    //清空
    TIM4CH1_CAPTURE_VAL=0;
     TIM_SetCounter(TIM4,0);
    TIM4CH1_CAPTURE_STA|=0X40;  //标记捕获到了上升沿
      TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Falling);  //CC1P=1 设置为下降沿捕获
   }     
  }    
  }
 
 if((TIM4CH2_CAPTURE_STA&0X80)==0)     //还未成功捕获 
 {  
  if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
  {    
   if(TIM4CH2_CAPTURE_STA&0X40)     //已经捕获到高电平了
   {
    if((TIM4CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    {
     TIM4CH2_CAPTURE_STA|=0X80;    //标记成功捕获了一次
     TIM4CH2_CAPTURE_VAL=0XFFFF;
    }else TIM4CH2_CAPTURE_STA++;
   } 
  }
  
  if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET)//捕获2发生捕获事件
  { 
   if(TIM4CH2_CAPTURE_STA&0X40)  //捕获到一个下降沿   
   {      
    TIM4CH2_CAPTURE_STA|=0X80;  //标记成功捕获到一次上升沿
    TIM4CH2_CAPTURE_VAL=TIM_GetCapture2(TIM4);
      TIM_OC2PolarityConfig(TIM4,TIM_ICPolarity_Falling); //CC1P=0 设置为上升沿捕获
   }else               //还未开始,第一次捕获上升沿
   {
    TIM4CH2_CAPTURE_STA=0;    //清空
    TIM4CH2_CAPTURE_VAL=0;
     TIM_SetCounter(TIM4,0);
    TIM4CH2_CAPTURE_STA|=0X40;  //标记捕获到了上升沿
      TIM_OC2PolarityConfig(TIM4,TIM_ICPolarity_Falling);  //CC1P=1 设置为下降沿捕获
   }     
  } 
 }  
  TIM_ClearITPendingBit(TIM4, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_Update);    //清除中断标志位
}

主函数
if(TIM4CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
  {
   cycle1=TIM4CH1_CAPTURE_STA&0X3F;
   cycle1*=65536;//溢出时间总和
   cycle1+=TIM4CH1_CAPTURE_VAL;//得到总的高电平时间(us)
   frequency1 = 1000000/cycle1;
  
   while(USART_GetFlagStatus(UART5, USART_FLAG_TC)==RESET);
   USART_SendData(UART5,  MotorPCBID);
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  TIM4CH1Flag);
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  TIM4CH1_CAPTURE_STA);
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  TIM4CH1_CAPTURE_VAL>>8);
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  TIM4CH1_CAPTURE_VAL& 0x00FF);
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  (cycle1>>8));
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  (cycle1 & 0x00FF));
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  (frequency1>>8));
   while(USART_GetFlagStatus(UART5, USART_FLAG_TXE)==RESET);
   USART_SendData(UART5,  (frequency1 & 0x00FF));
  
   TIM4CH1_CAPTURE_STA=0;//开启下一次捕获
  }
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
正点原子
1楼-- · 2019-07-21 11:09
中断太频繁了,导致还没处理第一个中断,第二个中断就来了,没来得及读,互相干扰。
奋斗的小鸟
2楼-- · 2019-07-21 14:00
 精彩回答 2  元偷偷看……
ZKFT
3楼-- · 2019-07-21 17:07
大神,能具体帮我说一下两路输入捕获的处理方法么??我都调试了好久了
maskinmother
4楼-- · 2019-07-21 18:04
奋斗的小鸟 发表于 2014-8-4 11:49
回复【2楼】正点原子:
---------------------------------
原子哥,问题解决了,确实如你所说,是这一句TIM ...

你怕是在睁眼说瞎话噢,有什么关系吗?明明是你的定时器2和4的中断服务函数会相互干扰嘛。这才是导致测不准的根本原因

一周热门 更多>