OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9831|回复: 13

求助一个自己编的测频率的程序,测量结果误差较大

[复制链接]

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-10-12
在线时间
4 小时
发表于 2021-7-19 22:54:12 | 显示全部楼层 |阅读模式
3金钱
最近开始学STM32,买的正点原子的精英板,带2.8寸LCD屏。
这个程序是我想拿来测频率的,希望能在1Hz-7kHz左右达到相对误差不超过0.01%的目标。程序的大概思路是,利用TIM3的输入捕获,使能从模式的复位模式,在外部信号上升沿到来时初始化计数器,在下一个上升沿到来时获取捕获值,在主函数中计算出频率,并用LCD显示。计数时有考虑外部信号过长导致计数器溢出,仿照例程设计了一个变量保存溢出次数。
测试的结果是,输入0-3.3V的方波信号,信号是1Hz时测得约0.9Hz,是10Hz时测得约9Hz,在1kHz时测得500多Hz,高到100kHz左右测得约1kHz。(具体的数据没记下来)
很奇怪问题出在哪。如果是因为中断服务函数执行时间太长,那也应该是比真实数据更大才对啊?希望各路高人能指点迷津,不胜感激。
代码如下:

频率测量.rar

4.75 MB, 下载次数: 50

最佳答案

查看完整内容[请看2#楼]

感谢各位,自己找到问题了。 我使用的从模式:复位模式,能在上升沿到来时对计数器值硬件清零。但是同时触发的更新事件,开启了更新中断,致使溢出次数统计变量有一个无效的加一。只要在计算时减去这个一就好了。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-10-12
在线时间
4 小时
 楼主| 发表于 2021-7-19 22:54:13 | 显示全部楼层
感谢各位,自己找到问题了。
我使用的从模式:复位模式,能在上升沿到来时对计数器值硬件清零。但是同时触发的更新事件,开启了更新中断,致使溢出次数统计变量有一个无效的加一。只要在计算时减去这个一就好了。
回复

使用道具 举报

109

主题

5562

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10541
金钱
10541
注册时间
2017-2-18
在线时间
1908 小时
发表于 2021-7-22 09:56:33 | 显示全部楼层
帮顶~~
回复

使用道具 举报

11

主题

2103

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4588
金钱
4588
注册时间
2015-1-10
在线时间
574 小时
发表于 2021-7-22 10:10:38 | 显示全部楼层
为啥要用从模式,直接输入捕获不行吗?TIM3的中断优先级是否最高,我没搞过100KHz的,但是1KHz的你那点中断代码还不至于测不准
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2021-7-21
在线时间
2 小时
发表于 2021-7-22 10:35:04 | 显示全部楼层
真的好难哦~~`
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-10-12
在线时间
4 小时
 楼主| 发表于 2021-7-22 16:41:06 | 显示全部楼层
阿侑kevin 发表于 2021-7-22 10:10
为啥要用从模式,直接输入捕获不行吗?TIM3的中断优先级是否最高,我没搞过100KHz的,但是1KHz的你那点中断 ...

我是想在上升沿到来后对计数器值硬件清零
回复

使用道具 举报

11

主题

2103

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4588
金钱
4588
注册时间
2015-1-10
在线时间
574 小时
发表于 2021-7-23 09:19:30 | 显示全部楼层
ThZhang0424 发表于 2021-7-22 16:41
我是想在上升沿到来后对计数器值硬件清零

不需要啊,上升沿来了自动会把计数值放到CCR寄存器里面,记一下这个值,下个上升沿来了更新CCR,两个值之差就是周期,再加个定时器溢出就可以了,给你个参考:void TIM11_IRQHandler(void)
{
        static uint16_t capStart = 0, overflowCnt = 0;
        uint16_t freq = 0;
        
        if (TIM_GetITStatus(TIM11, TIM_IT_Update) == SET) {
                TIM_ClearITPendingBit(TIM11, TIM_IT_Update);        
                if (overflowCnt & 0x8000)
                                overflowCnt++;
        }
        
        if (TIM_GetITStatus(TIM11, TIM_IT_CC1) == SET) {
    /* Clear TIM11 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM11, TIM_IT_CC1);
               
    if (!(overflowCnt & 0x8000)) {
      /* Get the Input Capture value */
      capStart = TIM_GetCapture1(TIM11);
                        overflowCnt = 0x8000;                //set capture start count flag
    } else {
                        freq = 1000000/(1000*(overflowCnt[0] & 0x7FFF) + TIM_GetCapture1(TIM11) - capStart);
                                capStart = TIM_GetCapture1(TIM11);
                                overflowCnt = 0x8000;
                        }                        
    }
  }
}


回复

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2021-7-27
在线时间
0 小时
发表于 2021-7-27 20:43:20 | 显示全部楼层
ThZhang0424 发表于 2021-7-19 22:54
感谢各位,自己找到问题了。
我使用的从模式:复位模式,能在上升沿到来时对计数器值硬件清零。但是同时触 ...

请问一下要改哪个地方呀?
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2021-7-27
在线时间
0 小时
发表于 2021-7-27 21:02:21 | 显示全部楼层
ThZhang0424 发表于 2021-7-19 22:54
感谢各位,自己找到问题了。
我使用的从模式:复位模式,能在上升沿到来时对计数器值硬件清零。但是同时触 ...

我试了一下 你这个压缩包的代码好像没有问题。但是信号的电压不能太小貌似、
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-10-12
在线时间
4 小时
 楼主| 发表于 2021-7-30 10:58:19 | 显示全部楼层
何念 发表于 2021-7-27 21:02
我试了一下 你这个压缩包的代码好像没有问题。但是信号的电压不能太小貌似、

啊这……
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2020-10-12
在线时间
4 小时
 楼主| 发表于 2021-7-30 10:58:47 | 显示全部楼层
阿侑kevin 发表于 2021-7-23 09:19
不需要啊,上升沿来了自动会把计数值放到CCR寄存器里面,记一下这个值,下个上升沿来了更新CCR,两个值之 ...

okk,多谢
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2021-7-15
在线时间
2 小时
发表于 2021-7-31 10:02:31 | 显示全部楼层
请问有修改好的代码吗?我在我的电脑上运行了一下你的代码测量结果不太准确。万分感谢!
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2022-10-3
在线时间
5 小时
发表于 2023-7-13 12:34:21 | 显示全部楼层
                        LCD_ShowxNum( 30, 90, fre_int, int_cnt, 16, 0 );                         LCD_ShowChar( 30 + int_cnt * 8, 90, '.', 16, 0 );                         LCD_ShowxNum( 30 + int_cnt * 8 + 8, 90, fre_dec, 3, 16, 0 );                         LCD_ShowString( 30 + int_cnt * 8 + 32, 90, 32, 16, 16, "Hz" );
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2022-10-3
在线时间
5 小时
发表于 2023-7-13 12:34:49 | 显示全部楼层
                        LCD_ShowxNum( 30, 90, fre_int, int_cnt, 16, 0 );
                        LCD_ShowChar( 30 + int_cnt * 8, 90, '.', 16, 0 );
                        LCD_ShowxNum( 30 + int_cnt * 8 + 8, 90, fre_dec, 3, 16, 0 );
                        LCD_ShowString( 30 + int_cnt * 8 + 32, 90, 32, 16, 16, "Hz" );
请问这几行代码是啥意思?
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 04:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表