新手发帖,请多关照
程序是在原子开发板的例程的基础上修改的,例程是捕获一个高电平后再捕获低电平来计算一个高电平的脉宽,我改成捕获两个高电平,测量两个高电平的时间来算频率,
另外计数的方式也修改了下,例程中捕获一个高电平后会清零计数器,下一次捕获后直接读取CCR1的值来计算时间,这种方式确实方便了溢出处理,但我在测试中发现这种方式
精度不高,数值整体偏大,测大于10KHZ的信号(信号发生器)后误差会越来越大(10K时候有2%),按道理来说1μS计数一次的方式测试10K的信号误差不会有这大,最后我发现
从1K到50K误差值整体偏大,通过计算我发现了规律,如果换算成计数器的个数值的话就很好解释了,因为实测的计数器的个数值比实际频率对应的计数器个数值要小2-3,所以造成
了测试结果的整体偏大,找到了问题就要解决,因为是整体小2-3,所以我怀疑是清零计数器造成的,我尝试去掉清零读取两次CCR1的值算差值的方式,问题解决了,测试精度显著提高
5HZ 到 20K 误差小于 千分之1 后面的误差我就没算了因为我只需要测到10K就可以。100K内的误差还是挺小的,因为定时器设置的是1μS计数,输入未分频,所以这个测试的频率不会
太高,下面附两张测试的结果和中断部分的程序。
新人不懂版规,如有排版,文字描述不清的地方请各位多多包含,献丑了,附件中有源代码,战舰开发板可直接运行
中断部分的程序
[mw_shl_code=c,true]//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM5CH1_CAPTURE_STA&0X3F)==0X3f)//高电平太长了
{
TIM5CH1_CAPTURE_STA=0X80;//标记成功捕获了一次
TIM5CH1_CAPTURE_VAL=0;
}
else TIM5CH1_CAPTURE_STA++;
}
}[/mw_shl_code]
[mw_shl_code=c,true] if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
{
if(TIM5CH1_CAPTURE_STA&0X40) //第二次捕获到上升沿
{
ReadValue2 = TIM_GetCapture1(TIM5);
if ((ReadValue2 > ReadValue1)&&(TIM5CH1_CAPTURE_STA==0x40)) //无溢出
{
TIM5CH1_CAPTURE_VAL = (ReadValue2 - ReadValue1);
}
else //有溢出
{
TIM5CH1_CAPTURE_VAL = ((0xFFFF - ReadValue1) +ReadValue2);
}
TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
}
else //第一次捕获上升沿
{
ReadValue1=TIM_GetCapture1(TIM5);
//TIM5CH1_CAPTURE_STA=0; //清空
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA = 0X40; //标记捕获到了上升沿
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}[/mw_shl_code]
测试信号50K
测试信号5 Hz
|