当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]由于我们当时的题目除了测量频率之外,更麻烦的是测量占空比。而这两个的测量方法联系比较紧密,所以也一并把测量占空比的方法写出来。使用平台:官方STM32F429DISCOVERY开

由于我们当时的题目除了测量频率之外,更麻烦的是测量占空比。而这两个的测量方法联系比较紧密,所以也一并把测量占空比的方法写出来。

使用平台:官方STM32F429DISCOVERY开发板,180MHz的主频,定时器频率90MHz。

相关题目:

(1)测量脉冲信号频率f_O,频率范围为10Hz~2MHz,测量误差的绝对值不大于0.1%。(15分)

(2)测量脉冲信号占空比D,测量范围为10%~90%,测量误差的绝对值不大于2%。(15分)

思路一:外部中断

思路:这种方法是很容易想到的,而且对几乎所有MCU都适用(连51都可以)。方法也很简单,声明一个计数变量TIM_cnt,每次一个上升沿/下降沿就进入一次中断,对TIM_cnt++,然后定时统计即可。如果需要占空比,那么就另外用一个定时器统计上升沿、下降沿之间的时间即可。

缺点:缺陷显而易见,当频率提高,将会频繁进入中断,占用大量时间。而当频率超过100kHz时,中断程序时间甚至将超过脉冲周期,产生巨大误差。同时更重要的是,想要测量的占空比由于受到中断程序影响,误差将越来越大。

总结:我们当时第一时间就把这个方案PASS了,没有相关代码(这个代码也很简单)。不过,该方法在频率较低(10K以下)时,可以拿来测量频率。在频率更低的情况下,可以拿来测占空比。

思路二:PWM输入模式

思路:翻遍ST的参考手册,在定时器当中有这样一种模式:

 

 

简而言之,理论上,通过这种模式,可以用硬件直接测量出频率和占空比。当时我们发现这一模式时欢欣鼓舞,以为可以一步解决这一问题。

但是,经过测量之后发现这种方法测试数据不稳定也不精确,数据不停跳动,且和实际值相差很大。ST的这些功能经常有这种问题,比如定时器的编码器模式,在0点处频繁正负跳变时有可能会卡死。这些方法虽然省事,稳定性却不是很好。

经过线性补偿可以一定程度上减少误差(参数在不同情况下不同):

freq=Frequency*2.2118-47.05;

思路三:输入捕获

思路:一般来说,对STM32有一定了解的坛友们在测量频率的问题上往往都会想到利用输入捕获。首先设定为上升沿触发,当进入中断之后(rising)记录与上次中断(rising_last)之间的间隔(周期,其倒数就是频率)。再设定为下降沿,进入中断之后与上升沿时刻之差即为高电平时间(falling-rising_last),高电平时间除周期即为占空比。

 

该方法尤其是在中低频(<100kHz)之下精度不错。

缺点:稍有经验的朋友们应该都能看出来,该方法仍然会带来极高的中断频率。在高频之下,首先是CPU时间被完全占用,此外,更重要的是,中断程序时间过长往往导致会错过一次或多次中断信号,表现就是测量值在实际值、实际值×2、实际值×3等之间跳动。实测中,最高频率可以测到约400kHz。

总结:该方法在低频率(<100kHz)下有着很好的精度,在考虑到其它程序的情况下,建议在10kHz之下使用该方法。同时,可以参考以下的改进程序减少CPU负载。

改进:

前述问题,限制频率提高的主要因素是过长的中断时间(一般应用情景之下,还有其它程序部分的限制)。所以进行以下改进:

1. 使用2个通道,一个只测量上升沿,另一个只测量下降沿。这样可以减少切换触发边沿的延迟,缺点是多用了一个IO口。

2. 使用寄存器,简化程序

之所以改用TIM2是因为TIM5的CH1(PA0)还是按键输入引脚。本来想来这应当也没什么,按键不按下不就是开路嘛。但是后来发现官方开发板上还有一个RC滤波……

所以,当使用别人的程序之前,请一定仔细查看电路图。

 

这样,最高频率能够达到约1.1MHz,是一个不小的进步。但是,其根本问题——中断太频繁——仍然存在。

解决思路也是存在的。本质上,我们实际上只需要读取CCR1和CCR2寄存器。而在内存复制过程中,面对大数据量的转移时,我们会想到什么?显然,我们很容易想到——利用DMA。所以,我们使用输入捕获事件触发DMA来搬运寄存器而非触发中断即可,然后将这些数据存放在一个数组当中并循环刷新。这样,我们可以随时来查看数据并计算出频率。

改进意见,列出如下:

1.可以设定仅有通道2进行下降沿捕获并触发中断,而通道1捕获上升沿不触发中断。在中断函数当中,一次读取CCR1和CCR2。这样可以节省大量时间。

2.可以先进行一次测量,根据测量值改变预分频值PSC,从而提高精度

3.间隔采样。例如每100ms采样10ms.

这样的改进应当能够将最高采样频率增加到2M.但是频率的进一步提高仍然不可能。因为这时的主要矛盾是中断函数时间过长,导致CPU还在处理中断的时候这一次周期就结束了,使得最终测量到的频率为真实频率的整数倍左右。示意图如下:

 

因此,高频时仍然推荐以下方法。

思路四:使用外部时钟计数器

这种方法是我这几天回答问题时推荐的方法。思路是配置两个定时器,定时器a设置为外部时钟计数器模式,定时器b设置为定时器(比如50ms溢出一次,也可以用软件定时器),然后定时器b中断函数中统计定时器a在这段时间内的增量,简单计算即可。[!--empirenews.page--]

缺点:

1.无法测量占空比,高频的占空比测量方法见下文。

2.在频率较低的情况下,测量精度不如思路3(因为测量周期为100ms,此时如果脉冲周期是200ms……)。

3.输入幅值必须超过3V 。如果不够或者超出,需要加入前置放大器。

总结:这种方法精度很高,实测在2MHz之下误差为30Hz也就是0.0015%(由中断服务程序引发,可以使用线性补偿修正),在25MHz之下也是误差30Hz左右(没法达到更高的原因是波形发生器的最大输出频率是25MHz^_^)。同时,从根本上解决了中断频率过高的问题。而由于低频的问题,建议:在低频时,或者加大采样间隔(更改TIM7的周期),或者采用思路3的输入捕获。

此外,还有一个莫名其妙的问题就是,中断当中如果不加入sprintf(str,"%3.3f",TIM_ExtCntFreq/1000.0)这一句,TIM_ExtCntFreq就始终为0 。我猜测是优化的问题,但是加入volatile也没有用,时间不够就没有理睬了。

思路五:ADC采样测量(概率测量法)

一般的高端示波器,测量频率即是这种方法。简而言之,高速采样一系列数据,然后通过频谱分析(例如快速傅里叶变换FFT),获得频率。F4有着FPU和DSP指令,计算速度上可以接受。但是ADC的采样频率远远达不到。官方手册上声明,在三通道交替采样+DMA之下,最高可以达到8.4M的采样率。然而,根据香农采样定理,采样频率至少要达到信号的2倍。2M信号和8.4M的采样率,即使能够计算,误差也无法接受。所以,ADC采样是无法测量频率特别是高频频率的。

但是,无法测量频率,却可以测量占空比,乃至超调量和上升时间(信号从10%幅值上升到90%的时间)!原理也很简单,大学概率课上都说过这个概率基本原理:

 

当采样数n趋于无穷时,事件A的概率即趋近于统计的频率。所以,当采样数越大,则采样到的高电平占样本总数的频率即趋近于概率——占空比!

 

因此,基本思路即是等间隔(速度无所谓,但必须是保证等概率采样)采样,并将这些数据存入一个数组,反复刷新。这样,可以在任意时间对数组中数据进行统计,获得占空比数据。

缺点:

1.精度低:实测2MHz下误差约1.3%,低频时无法统计(比如,频率10Hz,而ADC采样时间50ms。这时如果采样时间中刚好全是高电平,占空比为1……)。

2.内存占用大:数据池大小为65536,占用了64KB内存。

3.有响应延迟:测量出来的是“平均占空比”而非“瞬时占空比”。由于我测试时使用的是波形发生器,输出波形相当稳定(1W+的价格毕竟是有它的道理的……),实际应用当中一般不能够达到这样的水平,势必带来响应延迟(准确说应该是采样系统积分惯性越大)。

4.幅值过低(0.3V)无法测量,过高则超过ADC允许最大值。所以必须视情况使用不同的前置放大器。

实际上使用时如何取舍,就需要看实际情况了。毕竟,这只是低成本下的解决方案而已。

综上,对这几种方法做一个总结:

外部中断:编写容易,通用性强。缺点是中断进入频繁,误差大。

PWM输入:全硬件完成,CPU负载小,编写容易。缺点是不稳定,误差大。

输入捕获:可达到约400kHz。低频精度高,10Hz可达到0.01%以下,400kHz也有3%。缺点是中断频繁,无法测量高频,幅值必须在3.3~5V之间。

外部时钟计数器(首选):可达到非常高的频率(理论上应当是90MHz)和非常低的误差(2MHz下为0.0015%且可线性补偿)。缺点是低频精度较低,同样幅值必须在3.3~5V之间。

ADC采样频率测量法:难以测量频率,高频下对占空比、上升时间有可以接受的测量精度(2MHz下约1.3%),低频下无法测量。幅值0.3~3.3V,加入前置放大则幅值随意。

ADC采样频谱分析:高端示波器专用,STM32弃疗。

我采用的方法是:首先ADC测量幅值并据此改变前置放大器放大倍数,调整幅值为3.3V ,同时测量得到参考占空比。而后使用外部时钟计数器测量得到频率,如果较高(>10000)则确认为频率数据,同时ADC测量占空比确认为占空比数据。否则再使用输入捕获方法测量得到频率、占空比数据。

对于各个方法存在的线性误差,使用了线性补偿来提高精度。一般情况下,使用存储在ROM中的数据作为参数,当需要校正时,采用如下校正思路:

波形发生器生成一些预设参数波形(例如10Hz,10%;100K,50%;2M,90%……),在不同区间内多次测量得到数据,随后以原始数据为x,真实数据为y,去除异常数据之后,做y=f(x)的线性回归,并取相关系数最高的作为新的参数,同时存储在ROM当中。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

在嵌入式系统开发、调试和测试过程中,J-Link作为一种高效的调试工具,为开发者提供了极大的便利。然而,要想充分发挥J-Link的功能,首先需要正确安装其驱动程序。本文将详细介绍J-Link驱动的安装过程,并深入解析其中...

关键字: jlink 嵌入式系统 嵌入式开发

与谷歌的合作使 Nordic 能够在 nRF Connect SDK 中嵌入开发人员软件,以构建与安卓移动设备兼容的谷歌Find My Device和未知跟踪器警报服务

关键字: 谷歌 SoC 嵌入式开发

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

嵌入式开发作为当今电子工程和信息技术领域的核心分支,涵盖了广泛的软硬件技术和系统集成方法,用于构建高性能、低成本、低功耗、体积小巧且功能专一的嵌入式系统。这些系统无处不在,从微型传感器节点到复杂的工业控制设备,从日常使用...

关键字: 嵌入式开发 Python

嵌入式开发是当今信息技术领域不可或缺的一部分,它融合了硬件设计、软件开发和系统集成等多个学科,专门用于创建那些被嵌入到特定设备或系统中的专用计算机系统。嵌入式开发的主要过程包括利用分立元件或集成器件进行电路设计、结构设计...

关键字: 嵌入式开发 硬件设计 软件开发

嵌入式开发作为一种专业且技术密集型的领域,涵盖了从硬件底层驱动、中间件到应用层软件开发等多个层面的工作,其所需的工具种类繁多,各有针对性,旨在提升开发效率、保证代码质量以及简化调试过程。

关键字: 嵌入式开发 keil

嵌入式开发作为信息技术领域的重要分支,其涉及的语言种类繁多,各具特色。这些语言的选择取决于目标平台的特性、性能需求、开发者的熟练程度以及项目的具体要求。本文将详细介绍几种常见的嵌入式开发语言,包括C语言、C++、汇编语言...

关键字: 嵌入式开发 C语言

嵌入式开发是一项综合了硬件设计、软件编程以及系统整合的技术活动,其目的是为了创造出能够在特定环境中高效、稳定运行的嵌入式系统。这一流程涵盖了多个紧密关联且不可或缺的阶段,从最初的客户需求分析到最终的产品测试和交付,每个环...

关键字: 嵌入式开发 硬件设计

嵌入式开发作为一个融合了计算机软硬件和系统工程的综合性领域,其成功与否往往取决于三个核心要素的有效整合与协调。这三个要素分别是:硬件平台的选择与设计、软件开发及其优化、以及系统级的设计与集成。深入理解并熟练掌握这三个方面...

关键字: 嵌入式开发 ARM
关闭
关闭