拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

高精度频率计模块设计:等精度测量与TDC插值技术实践

高精度频率计模块设计:等精度测量与TDC插值技术实践 1. 项目概述与需求拆解做仪器仪表和测量控制这块的工程师几乎都遇到过同一个场景手里需要测一个信号频率或者两路信号之间的时间间隔普通万用表根本看不了那么细示波器虽然能看波形但做高精度频率统计又嫌麻烦最后只能翻箱倒柜找一台台式频率计。可台式仪器又贵又占地方产线自动化或者嵌入式集成场景往往更需要一个能直接焊到板子上的频率计模块。我这次做的事情就是设计并调试了一个高精度通用时间测量频率计模块。核心指标不是“能测频率多少兆”这种粗浅层面而是要解决两个实际痛点一是频率测量要有足够高的分辨率和稳定度能在短闸门时间内读出足够多有效位数二是要能当作通用时间测量模块来用也就是测两个信号之间的时间间隔、脉宽、占空比、周期抖动这些参数而不只是简单数数。如果你也在折腾类似的东西——比如做自动化测试设备、写采集系统、搞授时同步、或者想给自己DIY一台精度说得过去的频率计这篇内容应该能帮你少走不少弯路。我会把方案选型、硬件设计、固件算法、校准验证到坑点排查都讲一遍所有内容都来自实际调板过程不是PPT方案。1.1 频率计模块的核心指标拆解先明确一个概念频率计模块和普通计数器最大的区别在于它必须在“短时间”内拿到足够精确的结果。就好比称体重普通秤你要站上去等它稳定但高精度模块要求你在100毫秒内就读出一个稳定的值而且不能抖。拆开来看指标主要分这么几块频率测量范围与分辨率。常见需求从低频比如1Hz的秒脉冲到高频比如100MHz以上的射频信号都有。我的设定是10Hz到100MHz直接计数100MHz以上通过外置分频器扩展。分辨率方面闸门时间100ms时至少要能分辨到0.1Hz量级再往上就要靠等精度测量和插值法来突破。时间间隔测量精度。这地方水很深。普通的MCU定时器引脚捕获分辨率受限于定时器时钟比如STM32的定时器跑72MHz理论上能分辨约13.9ns但实际受中断延迟和触发抖动影响能做到50ns以上就算不错。而我要做的时间测量模块目标是把单次测量分辨率做到1ns以内多周期平均后能做到亚纳秒。时基稳定度。时基是频率计的“尺子”尺子不准测什么都白搭。普通晶振的频率稳定度大约在±20ppm到±50ppm温度一变化就跑得厉害。高精度方案至少要用温补晶振TCXO要求再高就得用恒温晶振OCXO甚至外部铷钟驯服。我这个模块在板子上预留了TCXO和OCXO两种座的兼容设计方便按成本切换。1.2 应用场景与核心价值判断频率计模块不是万能的但它能解决几个非常典型的问题第一个场景是产线自动化测试。比如一个晶振厂家要批量测试晶体频率偏差如果用台式频率计一台一台接效率太低。做成模块后可以一块控制板带多个模块并行测试每个模块独立测量一路信号上位机统一收数据。这时候模块的体积、成本、接口通用性就比单纯指标重要得多。第二个场景是时间同步和设备校准。比如电力系统、通信设备里经常要测1PPS秒脉冲的上升沿对齐度。两路秒脉冲之间时间差测出来就能判断设备同步是否正常工作。这个场景要求的就是时间间隔测量功能而不是传统意义的“频率计数”。第三个场景是科研实验的数据采集。我在调试过程中就遇到过用户需要测单光子探测器的脉冲时间差信号宽度只有几十纳秒重复频率也不高。这种信号用示波器测率触发很费劲但频率计模块的TDC时间测量功能反而更适合。2. 核心测量原理与方案选型分析方案选型是整个项目里最磨人的一步。网上能搜到的频率计方案五花八门从最简单的51单片机计数器到用FPGA做等精度计数再到专用时间数字转换芯片没有对错只有适不适合。我大概梳理了四条路线逐一分析它们的优缺点后再做决定。2.1 直接计数法的局限与破解思路最容易想到的方案是直接计数法用一个已知频率的闸门信号控制计数器对输入信号脉冲计数然后用“计数结果除以闸门时间”得到频率。这个方法看似简单但有个致命缺陷——它天生存在±1个计数脉冲的量化误差。举个例子假设闸门时间正好是1秒被测信号频率是10000.5Hz理论上一秒内应该数到10000.5个脉冲但计数器只能数到整数要么10000要么10001。此时测出来的频率就是10000Hz或10001Hz相对误差大约是1/10000也就是万分之一。更糟糕的是这个误差和被测信号的频率有关信号频率越低相对误差越大。所以直接计数法只适合高频信号粗测测低频信号简直灾难。那怎么破解业界有两条主流路线。一条是等精度测量法也叫同步计数法另一条是模拟或数字插值法。等精度测量的核心思想是闸门不再是固定时间长度而是由被测信号的上升沿“同步”开启和关闭让计数时间段内被测信号脉冲数始终是整数然后去测量这个实际闸门时间到底有多长。这样一来量化误差只和测闸门时间的基准时钟有关和被测量信号频率无关达到了“等精度”的效果。插值法则更直接既然量化误差来自“闸门开启时刻”和“第一个上升沿”之间的那段零碎时间测不准那就专门去测这段零碎时间。模拟插值法用恒流源给电容充电然后用ADC读电压数字插值法用延迟链之类的方法把亚时钟周期的时间差“展开”。2.2 等精度测量与TDC方案的组合选型在做方案对比时我把四套方案放一起看方案核心原理分辨率水平实现难度成本灵活度直接计数法固定闸门内数脉冲受信号频率限制低频差低低低等精度计数同步闸门数脉冲测实际闸门受基准时钟频率限制中中中模拟插值法电容充放电测零碎时间可达ns级高中中数字TDC延迟链/游标法细分时间可达ps级高中高高最终我选择的是“等精度计数数字TDC插值”的组合方案。原因有三个第一等精度计数器负责解决“大数”的准确问题保证频率测量的相对误差压到基准时钟的量级。只要时基稳定测量结果的准确性就有可靠保障。第二在等精度计数的基础上用TDC功能去补测闸门边沿和基准时钟上升沿之间的微小时间差可以大幅提高时间测量的分辨率。TDC的延迟链能做到几十皮秒的分辨率远超MCU定时器。第三这套方案的主控可以用中高端FPGA实现也可以在带硬件TDC的MCU上实现。考虑到我后续要扩展时间间隔、脉宽测量等更多功能FPGA的灵活性更合适。2.3 时基选择TCXO与OCXO怎么选时基这事值得单独说。频率计模块的测量基准就是板上的时钟源它准不准、稳不稳直接决定了整个模块的上限。就像你拿一把刻度不准的尺子去量东西量得再仔细结果也是错的。我在选型时做了几个测试对比。普通贴片晶振有源晶振或者晶体反相器振荡频率稳定度一般能到±20ppm到±50ppm温度一波动可能跑偏到100ppm。这是什么概念呢测一个10MHz信号如果时基偏了20ppm测量结果就偏了200Hz。对于大多数要求不高的场景或许能忍但要做“高精度”模块这条路直接pass。进口品牌的温补晶振TCXO能做到±0.5ppm到±2ppm的稳定度好的甚至能到±0.1ppm级别。做通用频率计模块TCXO是起步选项。如果预算允许直接上恒温晶振OCXO稳定度能到±0.01ppm到±0.001ppm也就是十亿分之十到百亿分之一。OCXO还有个好处是开机后经过一段预热频率能稳定到很小的漂移范围内适合长时间连续测量。我的板子设计成两种兼容默认焊TCXO同时预留OCXO的焊盘和引脚定义如果客户需要更高精度直接换器件并在固件里切一下配置即可。另外我还加了参考时钟输入口可以接外部10MHz标准源这样就能把模块的精度提升到外部基准的水平这是产品化时很重要的扩展能力。3. 硬件电路设计关键点方案定了之后就进入画板阶段。硬件设计是整个项目里踩坑最多的部分信号调理、电平转换、时基供电、PCB布局每一处都有讲究。我按照信号流向从输入到输出捋一遍。3.1 前端信号调理电路设计频率计模块的输入信号不可能都是干干净净的方波。实际场景里可能是传感器输出的正弦波、有直流偏置的脉冲、带噪声的TTL信号甚至是从电缆远端传来的衰减信号。前端调理电路的任务就是把五花八门的信号变成内部计数器能正确识别的标准逻辑电平。我的前端设计分三级第一级是宽带放大/缓冲。用一颗高速运算放大器做阻抗变换和增益调整输入阻抗设置在1MΩ并一个小电容既保证对被测电路的负载效应小又能滤掉部分高频噪声。这个缓冲级的带宽至少要覆盖到100MHz超过了就得用专用比较器来做限幅放大。第二级是整形比较器。用超高速比较器把正弦波或任意波形转换成方波。比较器的阈值电平非常关键——阈值太高会漏掉小幅值信号阈值太低又容易把噪声也当信号触发。比较实用的做法是把阈值设成可调的常用三档0V针对交流耦合信号、1.65V针对3.3V系统、2.5V针对5V系统。我板子上用拨码开关切换分压电阻网络方便现场调整。第三级是施密特整形和电平转换。比较器输出虽然已经是方波但上升沿可能还有抖动或者小幅回振所以再接一个施密特触发器做沿整形。最后统一把电平转成FPGA的IO标准比如3.3V或2.5V。3.2 阻抗匹配与耦合方式的实际处理高频信号测量最忌讳的就是阻抗不连续。如果模块输入端和信号源之间阻抗不匹配信号会反射导致波形变形、测量结果跳变。我的做法是输入端做了50Ω和1MΩ两种可选输入阻抗通过继电器切换。测高频射频信号时选50Ω测普通电路节点时选1MΩ这样无论是接示波器探头还是接同轴电缆都有合适的匹配。耦合方式同样重要。交流耦合能滤掉直流偏置适合测叠加在直流上的小信号直流耦合能完整保留信号的所有信息适合测脉冲宽度和占空比这些对电平敏感的指标。我在输入端加了隔直电容和直通两条路径通过镀金跳线切换。3.3 时基电路与供电设计TCXO和OCXO对供电质量相当敏感哪怕电源纹波只有几十毫伏都会让输出频率出现杂散抖动。我给时基部分单独设计了一路LDO供电并在电源引脚附近放了低ESR的钽电容和陶瓷电容组合。走线时把时基电路单独放一个区域用地平面包围起来与数字逻辑的开关噪声隔离。如果采用OCXO还要特别注意它的启动电流很大并且需要一个预热过程。常规LDO可能撑不住开机瞬间的浪涌所以我在OCXO供电路径上加了一个限流电阻和储能电容避免上电瞬间把供电电压拉垮。调试过程中还发现一个有意思的细节OCXO的外壳接地处理不当会导致测量结果出现周期性的“呼吸效应”——频率读数慢慢飘上去又降下来。后来把OCXO外壳直接焊接到底层地平面问题就消失了。这个小细节我后来在设计文档里特别标注了。4. 固件算法实现与外层接口设计硬件只是一半另一半在固件。这块我花的时间最多尤其是等精度算法的时序控制以及TDC的校准补偿稍不留神就会让测量结果产生莫名其妙的偏差。4.1 等精度测量状态机的三段式设计等精度测量听起来简单但真正实现时要处理好几个容易出现逻辑冲突的细节。我用三段式状态机实现空闲状态等待上位机的触发命令所有计数器清零闸门开关处于关闭状态。预同步状态收到触发后打开基准时钟闸门但别急着对被测信号开门先等待被测信号的第一个上升沿。这一步很关键目的是让闸门开启时刻与被测信号边沿对齐避免开始阶段产生半个脉冲计数误差。正式计数状态闸门同时在被测信号边沿开启基准时钟和被测信号都开始计数。持续一个设定的闸门时间比如100毫秒结束后等下一个被测信号上升沿到来再同时关闭。结果运算状态把预同步阶段和正式计数阶段的计数结果相减算出实际闸门长度和被测信号脉冲数再算频率值。这里有个细节值得展开为什么还要检测“预同步阶段”的计数因为从触发信号到被测信号第一个上升沿之间的时间是不确定的如果只记录正式计数阶段的数字就没有办法精确知道实际闸门到底开了多久。预同步阶段相当于把“测量的起始边界”的微小时间差也纳入计数体系最后用减法消掉。这其实就是等精度测量比直接计数法更准确的根本原因。4.2 TDC插值的校准方法与补偿策略等精度计数解决了“不外乎整数”的问题但基准时钟本身的周期近似值还是不够用的。举个例子基准时钟是100MHz一个周期是10ns但如果TPD延迟链能做到每级10ps那么100MHz基准时钟的一个周期可以被细分成1000份。测量时闸门实际开启时间T_gate N_base_cycles × T_clk Δt_start - Δt_stop其中Δt_start和Δt_stop就是闸门两个边沿相对基准时钟上升沿的时间差需要用TDC来测量。TDC虽然分辨率高但有个“非线性”问题——延迟链的每级延迟不可能完全一致温度变化也会导致各级延迟漂移。如果直接用原始读数算Δt结果会包含系统性误差。所以固件里必须做两步补偿第一步是“码密度校准”。给TDC输入端送入一个与基准时钟不相关的、频率可变的随机信号大量统计每个延迟级被触发的次数。理想情况下各级触发次数应该均匀分布偏差量就能折算成每级的实际延迟校正系数。这个过程有点类似于ADC的直方图校正。第二步是“温度漂移补偿”。我在板子上放了一个温度传感器每测量1000次读取一次温度然后依据标定好的温度曲线对TDC结果做修正。实测下来这个修正逻辑能在0到60摄氏度范围内把时间测量引入的误差控制在±200ps以内。4.3 数据输出协议与上位机对接模块的测量结果不是自己看看就完事了最终是要被上位机或者其他系统读取的。我用的接口是UART串口加USB转串口芯片同时在板上留了SPI和I2C的引脚方便嵌入式系统直接对接。串口协议我设计得很简单每帧数据以帧头0xAA开始跟着一个字节表示测量类型0x01频率、0x02周期、0x03时间间隔、0x04脉宽等然后是四个字节的测量结果整数部分、两个字节的小数部分最后是校验字节。实际使用中测试过115200波特率下每秒钟可以输出大约200帧完整结果完全够用。上位机这边我用Python写了一个简单的读取脚本用pySerial读串口数据然后解析帧结构。如果是做产线定制可以直接把这个协议封装成DLL或者驱动让LabVIEW或者其他测试软件调用。我自己的经验是协议越简单越好别搞复杂的状态机否则联调时最容易出问题。5. 校准调试与性能验证硬件做完、固件写完剩下的就是校准和验证。这块不能省数据说话才有底气。我用了两套方法来验证模块的真实性能一是和实验室的铷原子频率标准对比二是在不同温度环境下做稳定性测试。5.1 校准流程与参考源标定校准的核心目标是让模块内部时基的输出频率尽可能精确地等于标称值。假设我用的是标称10MHz的TCXO但实际焊上去的器件频率是10.000123MHz偏差约12.3ppm。这个偏差如果不校准测出来的所有频率都会偏大约12.3ppm。校准方法有两种硬件微调和软校准。硬件微调是调整TCXO的负载电容让振荡频率逼近标称值这个方法适合小批量生产批量大的时候更推荐软件校准——把每块板的实际偏差系数算出来写进板上的EEPROM测量时用这个系数对结果做修正。我实际用的校准流程是这样的先用实验室的铷原子频率标准输出一个10MHz参考信号接到模块的参考时钟输入口然后把模块切换到“参考时钟模式”让它以外部10MHz为基准测量自己的TCXO输出频率记录偏差值写入EEPROM。这样每一块板子都有自己的校准系数生产时不用逐个调电容效率高很多。5.2 频率测量精度实测数据校准完成后我做了几个典型频率点的验证。用安捷伦的信号源输出标准频率用模块连测100组数据统计平均值、标准差和最大偏差。被测标称频率模块测量平均值标准差最大偏差相对误差10Hz10.0000002Hz0.0000004Hz0.0000011Hz~1e-71kHz1000.00001Hz0.00003Hz0.00008Hz~8e-810MHz10000000.018Hz0.002Hz0.006Hz~6e-950MHz50000000.052Hz0.008Hz0.022Hz~4e-9闸门时间设定为100ms内部时基用的TCXO。整体结果符合预期低频信号因为测量周期数多相对误差也在可控范围。5.3 时间间隔测量与抖动评估时间测量是这次项目里的一个重点特色功能。测试方法是用信号源产生两路脉冲手动调节两路之间的延迟然后让模块测时间间隔。在10ns到1000ns的范围内模块的单次测量分辨率大约是0.6ns左右。把100次测量结果做平均标准差能压到0.05ns以下。这个水平虽然和专用时间相关单光子计数模块几十皮秒还有差距但对于绝大多数工业测控和常规科研需求已经绰绰有余。测量过程中还发现一个现象当两路信号来自同一个信号源的两个输出通道时测出来的时间差非常稳但如果两路信号来自不同仪器时间差就会明显跳动。原因是不同仪器的时钟基准本身就不同步它们之间的相位关系一直在漂移。这个现象提醒我们一个重要的使用原则要做高精度时间间隔测量必须先保证两路信号有共同的时间基准否则测出来的“时间差”里包含了参考源的相互漂移。5.4 自检功能与开机自校准设计模块上还加了一个自检功能内部把一个已知频率的信号通过分频器引回测量通道相当于“测自己”。自检通过标志在串口协议里输出上位机可以做开机自检。遇到问题的时候这个自检功能能快速确认故障发生在测量通道还是时基链路。自检并不是每次开机都跑完整流程那样太慢了。实际实现是开机时快速测一次内部1MHz参考信号确认偏差在容许范围内就通过如果超范围则输出告警帧提示用户检查时基或温度环境。这个设计在生产测试和现场故障排查时非常有用。6. 实操中的典型问题与原理解析最后这部分我把自己调试过程中遇到的几个问题整理成速查表的形式。这些问题网上不一定能找到现成答案但实际调试时几乎一定会碰到拿出来给大家做个参考。6.1 高频信号测不准不只是计数器的问题现象测5MHz正弦信号时读数还行但测80MHz正弦信号时读数老是跳个几十Hz。 排查过程先用示波器看模块输入端的信号波形发现80MHz正弦波经过比较器后边沿变得有些倾斜导致施密特触发器触发点不稳定。触发点不稳定会导致相邻两个脉冲的沿间隔变大变小计数结果自然就飘了。 解决把比较器的滞环稍微调大一点同时提高比较器正反馈电阻的值让沿变得更陡。另外把输入缓冲级的带宽从100MHz提高到了200MHz减小高频衰减。调完之后80MHz测量跳动从几十Hz降到2Hz以内。经验总结频率计模块的高频性能不只看FPGA计数器能跑多快前端调理电路的带宽和边沿质量往往才是瓶颈。示波器看到波形“看着还行”不代表计数没问题。6.2 开机读数慢慢漂移OCXO预热导致的trick现象模块刚上电时测10MHz信号读数稳定在10.000015MHz左右但十几分钟后读数慢慢“爬”到10.000003MHz附近之后就基本不再变化。 问题原因我用的OCXO在常温下启动后需要预热几分钟输出频率会从偏差向标称值收敛。开机初期测量结果包含OCXO尚未稳定的偏差。 处理在用户手册里明确写了“连续上电预热5分钟后读数才达到标称精度”同时固件里加了一个“预热中”标志开机头5分钟输出结果附带标识。如果对测量速度有要求也可以用外部10MHz参考时钟作为时基这样就完全避开OCXO预热问题。6.3 两路信号测量时差跳变参考时钟地线回路问题现象用两路信号测时间间隔读数在理论值附近无规律跳变跳变量最大可达几微秒。 排查过程一开始怀疑是TDC校准有问题后来测了一下两路信号的共同参考地发现模块输入端和信号源地之间有一个不小的电势差。用示波器看这个电势差上面叠加了明显的开关电源纹波。 解决把所有模拟地、数字地、电源地在背板做星型单点接地并把模块的输入地单独接回信号源地。问题立即消失时间间隔读数恢复稳定。经验总结高频测量系统最容易忽视但影响最大的就是地线回路。接地不良的表现往往不是“完全乱跳”而是“规律性地跳一点”非常迷惑人。凡是遇到测量结果小幅漂移或跳变第一反应永远是检查地线。6.4 串口数据丢帧缓冲不足引发的偶发丢失现象上位机长时间连续读取时偶尔会出现一帧数据缺失或者校验失败的情况频率不高但影响统计。 原因FPGA内部FIFO深度不够串口发送速度跟不上测量结果生成速度导致偶发溢出。 解决把内部FIFO从128字节扩展到1024字节同时把串口中断优先级调高。改完之后连续跑8小时没有丢帧。另外建议上位机读取时不要用查询方式用中断或DMA更稳。7. 扩展思路与后续演进方向模块做到这个程度基础功能和精度已经能满足绝大多数场景了。但如果想继续往纵深做我列几个我认为有价值的扩展方向。第一是加装Wi-Fi或以太网口做成分布式测量节点。一个机房多台设备同时测量数据统一汇聚到服务器做长期趋势监控。这种需求在授时监测、电力质量分析里很常见。第二是增加触发与沿选择功能。目前模块是“上升沿触发”或“下降沿触发”可配置但改成“任意沿触发”和“脉冲宽度条件触发”就能兼容更多场景。比如在调试串口波形时只测量特定脉宽范围内的脉冲。第三是算法层做统计处理。FPGA里可以加一个直方图统计模块对连续多次时间间隔测量做分布统计输出均值和标准差。这样就不需要上位机来回传输原始数据直接给统计结论适合在线质量监控场景。第四是支持多通道扩展。我目前是一路输入但板子上留了第二路输入的硬件位置。两路同时测量就可以做真正的双通道时间间隔分析而不是靠外部切换。这几个方向我都做了一些预研固件里保留了扩展接口。这套东西后续的演进空间还很大如果在实际应用中遇到新的测量需求改起来也比较方便。
返回列表