4174|7

13

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

想用16位定时器捕捉1~200kHz的脉冲周期,求大神指点迷津! [复制链接]

定时器配置:
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);       
                /*---------------------------- TIM16 Configuration ----------------------------*/
                /* Time base configuration */
                TIM_DeInit(TIM16);
                TIM_TimeBaseStructure.TIM_Period = 0xffff;
                TIM_TimeBaseStructure.TIM_Prescaler = 0;
                TIM_TimeBaseStructure.TIM_ClockDivision = 0;
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

                TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);

                TIM_PrescalerConfig(TIM16, 0, TIM_PSCReloadMode_Update);

                TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
                TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
                TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
                TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
                TIM_ICInitStructure.TIM_ICFilter = 0;

                TIM_ICInit(TIM16, &TIM_ICInitStructure);       

                NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
                NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_Init(&NVIC_InitStructure);       

                TIM_ClearITPendingBit(TIM16,TIM_IT_CC1|TIM_IT_Update);
                TIM_ITConfig(TIM16, TIM_IT_CC1|TIM_IT_Update,ENABLE);  
                TIM_Cmd(TIM16, ENABLE);   
中断处理:
void TIM16_IRQHandler(void)
{
        if((TIM16CH1_CAPTURE_STA&0X80)==0)
        {          
                if((TIM_GetITStatus(TIM16, TIM_IT_CC1) != RESET))
                {
                        TIM_ClearITPendingBit(TIM16, TIM_IT_CC1);
                        if(TIM16CH1_CAPTURE_STA&0x40)
                        {
                                TIM16CH1_CAPTURE_STA |= 0x80;
                                Cap2 = TIM_GetCapture1(TIM16);
                                if(CapCount_H>0)
                                {
                                        TIM16CH1_CAPTURE_VAL2 = CapCount_H*65536 + 65536-Cap1+Cap2;                               
                                }
                                else
                                {
                                        TIM16CH1_CAPTURE_VAL2 = Cap2-Cap1;                               
                                }
                        }
                        else
                        {               
                                CapCount_H = 0;
                                Cap2 = 0;
                                Cap1 = TIM_GetCapture1(TIM16);
                                TIM16CH1_CAPTURE_STA |= 0x40;       
                        }               
                }
               
                if (TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET)       
                {
                        TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
                        if (TIM16CH1_CAPTURE_STA&0x40)         
                        {            
                                CapCount_H++;
                        }                       
                }       
        }
        else
                TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
}
结果就是不对,望大神帮我找找bug!或者有别的思路或者程序都可以,急求急求!

此帖出自stm32/stm8论坛

最新回复

TIM16CH1_CAPTURE_STA是什么寄存器??? u8变量吗?那么主程序里有清零它吧,不然只能测一次。 有TIM16的话是STM32f05x吧,我没用过。 TIM16CH1_CAPTURE_VAL2 = CapCount_H*65536 + 65536-Cap1+Cap2;    是不是多了一个65535? 增计数模式,CapCount_H是上溢中断的次数。 Cap1是第一次的捕获值,Cap2是第二次的捕获值。 举个例子: 假如中间只有一次上溢中断,即CapCount_H=1, 那么cap1到上溢的时间是 65535-cap1, 随后新的计数周期到cap2的时间就是cap2, 那么就是65535*1-cap1+cap2. 200k有点高了,你要不要试试捕获预分频,TIM_SetIC1Prescaler,最多8分频。 另外,只测一次频率感觉你是测不准的,你频率有点高,特别你这个单片机主频只有48M吧。低频捕脉宽,高频点人头。 你可以去搜一下等精度频率测量。就是在一定时间内测量整数个频率时间,然后取平均值,比较准和稳。 最后,你这个测脉宽的感觉有点长,给你参考一个430的程序。 [attach]320573[/attach] 手好痒,控制不住自己。改了就像下面那样,不过没有验证,有很大可能性会有bug,仅供参考。 void TIM16_IRQHandler(void) {                 if((TIM_GetITStatus(TIM16, TIM_IT_CC1) != RESET)) //上升沿捕获中断                 {                         TIM_ClearITPendingBit(TIM16, TIM_IT_CC1); //清除中断标志                         Cap2 =  TIM_GetCapture1(TIM16);                         TIM16CH1_CAPTURE_VAL2 =CapCount_H*65536 - Cap1 + Cap2 ;                           Cap1 =  Cap2;                           CapCount_H=0;                 }                 if (TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET) //更新溢出中断                       {                         TIM_ClearITPendingBit(TIM16, TIM_IT_Update);//清除中断标志                         CapCount_H++;                                         }         } /*Keep it simple,stupid.*/   详情 回复 发表于 2017-9-8 21:18
点赞 关注
 

回复
举报

13

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
别沉了!大家赶紧来参与讨论吧!
此帖出自stm32/stm8论坛
 
 

回复

1万

帖子

25

TA的资源

裸片初长成(高级)

板凳
 
我用过PWM输入捕获功能,中断时,直接就在寄存器里读出高电平和低电平的持续时间了。
楼主用这个功能试一下。
此帖出自stm32/stm8论坛

点评

这个功能我知道,但是用16位定时器捕捉周期的范围不够。  详情 回复 发表于 2017-9-8 11:08
 
 

回复

4008

帖子

0

TA的资源

版主

4
 
这么干看不行,你做几个实验看问题出在哪里
此帖出自stm32/stm8论坛

点评

思路是第一次捕捉到上升沿时读一次capture,第二次捕捉到上升沿时再读capture,之间定时器有更新中断,然后根据这些计算出周期值。感觉思路没啥问题,但是捕捉到的值确实不对,可能是实现方面有问题。我是一直实验的  详情 回复 发表于 2017-9-8 11:13
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

5
 
dontium 发表于 2017-9-8 09:39
我用过PWM输入捕获功能,中断时,直接就在寄存器里读出高电平和低电平的持续时间了。
楼主用这个功能试一 ...

这个功能我知道,但是用16位定时器捕捉周期的范围不够。
此帖出自stm32/stm8论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

6
 
huo_hu 发表于 2017-9-8 10:43
这么干看不行,你做几个实验看问题出在哪里

思路是第一次捕捉到上升沿时读一次capture,第二次捕捉到上升沿时再读capture,之间定时器有更新中断,然后根据这些计算出周期值。感觉思路没啥问题,但是捕捉到的值确实不对,可能是实现方面有问题。我是一直实验的,搞了好几天。。。唉,路漫漫。。。
此帖出自stm32/stm8论坛
 
 
 

回复

92

帖子

0

TA的资源

一粒金砂(中级)

7
 
TIM16CH1_CAPTURE_STA是什么寄存器???
u8变量吗?那么主程序里有清零它吧,不然只能测一次。
有TIM16的话是STM32f05x吧,我没用过。

TIM16CH1_CAPTURE_VAL2 = CapCount_H*65536 + 65536-Cap1+Cap2;   
是不是多了一个65535?
增计数模式,CapCount_H是上溢中断的次数。
Cap1是第一次的捕获值,Cap2是第二次的捕获值。
举个例子:
假如中间只有一次上溢中断,即CapCount_H=1,
那么cap1到上溢的时间是 65535-cap1,
随后新的计数周期到cap2的时间就是cap2,
那么就是65535*1-cap1+cap2.
200k有点高了,你要不要试试捕获预分频,TIM_SetIC1Prescaler,最多8分频。

另外,只测一次频率感觉你是测不准的,你频率有点高,特别你这个单片机主频只有48M吧。低频捕脉宽,高频点人头。
你可以去搜一下等精度频率测量。就是在一定时间内测量整数个频率时间,然后取平均值,比较准和稳。

最后,你这个测脉宽的感觉有点长,给你参考一个430的程序。


手好痒,控制不住自己。改了就像下面那样,不过没有验证,有很大可能性会有bug,仅供参考。
void TIM16_IRQHandler(void)
{
                if((TIM_GetITStatus(TIM16, TIM_IT_CC1) != RESET)) //上升沿捕获中断
                {
                        TIM_ClearITPendingBit(TIM16, TIM_IT_CC1); //清除中断标志

                        Cap2 =  TIM_GetCapture1(TIM16);
                        TIM16CH1_CAPTURE_VAL2 =CapCount_H*65536 - Cap1 + Cap2 ;
                          Cap1 =  Cap2;
                          CapCount_H=0;

                }

                if (TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET) //更新溢出中断      
                {
                        TIM_ClearITPendingBit(TIM16, TIM_IT_Update);//清除中断标志
                        CapCount_H++;                        
                }        


}
/*Keep it simple,stupid.*/

此帖出自stm32/stm8论坛

点评

哈哈,感谢感谢,确实如你所说。主程序中有清零的,分频了高频误差有点高。后面我实验下再说结果。谢谢啦!  详情 回复 发表于 2017-9-9 09:21
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

8
 
吓于侠义 发表于 2017-9-8 21:18
TIM16CH1_CAPTURE_STA是什么寄存器???
u8变量吗?那么主程序里有清零它吧,不然只能测一次。
有TIM16 ...

哈哈,感谢感谢,确实如你所说。主程序中有清零的,分频了高频误差有点高。后面我实验下再说结果。谢谢啦!
此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表