
简介这份代码包围绕2021年全国大学生电子设计竞赛A题“信号失真度测量”展开面向电赛备赛者、MSP430F5529嵌入式学习者及需要信号采集与失真分析参考的开发者。方案以MSP430F5529为主控完成信号采样与失真度计算并借助NRF24L01无线模块把结果发送到手机端显示曾获省级一等奖适合借鉴基础功能实现、模块联调与工程组织方式也能据此复现主控程序、无线收发和显示交互等模块。压缩包共990个文件、约31.58MB涵盖C/H源码、Keil工程与配置文件、编译中间文件、HEX烧录文件以及无线模块相关资料可帮助读者还原完整工程结构、梳理ADC采样与频谱分析流程并排查编译、下载和通信环节的问题。目前已有4031人学习对需要赛题代码框架和移动端结果显示思路的读者具有较高参考价值。1. 电赛A题调制度测量装置里最容易翻车的不是算法而是量程边界电赛A题这道调制度测量装置翻车点常常不在算法而在量程边界。调制度 10% 的调幅波边带幅度只有载波的二十分之一换成示波器几乎看不见调制度拉到 90%包络又贴到零任何一点底噪都会让谷值判错。2021 年这道题把调幅波调制度、调频波调频度、载波频率、调制频率四个量塞进一台装置基本要求考的是精度守不守得住发挥部分比的是小调制度、弱信号下读数稳不稳。它考的不是谁会调库是谁能把整条测量链路从头讲到尾——这也是测评现场被追问最多的地方。适合已经能跑通 FFT、但读数一到边界就飘的人。2. 考点拆解四个测量量与评分表上的权重分布2.1 基本要求与发挥部分哪些指标必须一次测准这类题目的指标写法很固定一般拆成三件事测什么量、在什么范围内测、允许多大误差。基本要求通常给调制度一个百分比范围给载波频率一个频段给调制频率一个音频范围再对每个量给出绝对误差上限发挥部分往上加小调制度、多音调制、自动区分调幅与调频这些花样。评分逻辑要提前想明白绝大多数测评是按测点独立计分不是按误差比例扣。你在量程中段测得再漂亮只要量程两端的测点超差那几分就是零。所以时间分配上宁可少做一个发挥项也要把基本要求的上下边界各测三遍确认。还有几条容易被忽略的隐性要求装置要独立工作不能靠外部仪器辅助读数单一电源供电显示要能分辨到最后一位有效数字。这些不加分但做不到会直接判功能不完整。提示拿到题面第一件事不是画框图是把所有范围 误差抄成一张表标出哪些是边界测点。测评老师就是照这张表一个个测过去的。2.2 定义式与耦合关系为什么 ma 和 fc 不能各测各的调幅波的写法是载波乘一个随调制信号起伏的包络调制度 ma 的经典定义是包络最大值与最小值之差比上两者之和等价的频域写法是两倍边带幅度除以载波幅度。调频波则是载波相位里塞进一个积分项调频度 mf 等于最大频偏除以调制频率。两个定义放一起看耦合关系就出来了。测 ma 要先知道载波频率 fc才能做数字下变频、把包络取干净测 mf 要先知道调制频率 fm才能把测到的频偏换算成无量纲的调频度。四个量是链式的前一级歪一点后面全跟着歪。这也是为什么先粗测频率、再做解调、最后算比值这个顺序不能反。反过来做等于在未知载波位置的频谱上瞎找边带找错了还以为是算法有问题。采样环节还有一条岔路要选直接采样要求采样率至少四倍载波短波段下这个数字不低带通采样让载波混叠到一个中频上采样率可以降下来但必须算清楚混叠后的频率落在哪否则后面所有频率都是错的。2.3 现场排序题先测哪个量思路怎么讲测评时很爱问的一道题是如果只允许你先测一个量再拿它推其他三个你选哪个标准答法是选载波频率理由要讲三层。第一层fc 在频谱上是全局最大峰信噪比最好最容易一次测准第二层有了 fc 才能做数字下变频把调幅波的包络和调频波的瞬时频偏解出来这是后面一切的前提第三层fc 定了fm 才有地方找——调幅波去包络谱里找调频波去瞬时频率谱里找搜索范围直接从全频段缩到音频段。再加一句比值量优先的原则会更稳凡是能化成两条谱线幅度之比的量就别用绝对幅度。前端放大器增益随温度飘、滤波器通带不平这些误差在比值里直接抵消在绝对值里一分不少全留下来。追问如果接一句fc 估偏 1% 会怎样答法是把影响分开说调幅波这边下变频残留的载波会被低通滤掉大半ma 的偏差很小调频波这边相位差分直接把频率误差带进瞬时频偏mf 会明显偏。所以调频通道对 fc 的精度要求比调幅通道高一个档。3. 高频考点AM 调制度 ma 的三条路线与选型答辩3.1 路线一下变频加包络检波峰值谷值法最直观的做法是先数字下变频把载波搬到零频低通滤掉高频分量剩下的复信号取模就是包络再从包络的峰谷算 ma。直接对原始采样做希尔伯特变换取模也能得到包络但包络上会叠一层载波频率的纹波取最大值时很可能取在纹波尖上读数随采样相位跳。先下变频再低通等于把这层纹波从源头掐掉。import numpy as np def am_index_envelope(x, fs, fc): x: 采样序列; fs: 采样率; fc: 载波粗测频率 n len(x) t np.arange(n) / fs # 1) 数字下变频把载波搬到零频 bb x * np.exp(-2j * np.pi * fc * t) # 2) 低通窗口长度取整数个载波周期避免残余纹波 w max(3, int(round(fs / fc)) * 4) bb np.convolve(bb, np.ones(w) / w, modesame) # 3) 取模得到包络 env np.abs(bb) # 4) 掐掉两端过渡段用分位数代替极值 env env[int(0.1 * n):int(0.9 * n)] hi np.percentile(env, 99.0) lo np.percentile(env, 1.0) return (hi - lo) / (hi lo), env几个参数不能乱设。低通窗口长度要取载波周期的整数倍取 4 个周期是个折中再短残余纹波压不住再长包络本身的起伏会被平滑掉小调制度时尤其明显。分位数用 99 和 1 是经验值对应正态分布约 2.3 倍标准差的位置信噪比好的时候偏差不到半个百分点噪声大的场合可以放宽到 95 和 5代价是 ma 会被系统性低估。这条路线最大的优点是不用做长 FFT几十毫秒的数据就够实时性好。最大的问题在边界ma 低于 15% 时包络起伏只有均值的百分之十几和噪声同量级分位数怎么调都不稳。这时候必须换路线。3.2 路线二FFT 边带比值法配合栅栏效应校正调幅波的频谱很干净一根载波两根边带边带幅度各是载波的 ma/2。所以只要把三根谱线的幅度读准ma 就是一个除法。import numpy as np def am_index_fft(x, fs, fm_guess, span0.2): span: 在 fc±fm 附近的搜索比例默认 ±20% n len(x) X np.fft.rfft(x * np.hanning(n)) mag np.abs(X) freqs np.fft.rfftfreq(n, 1 / fs) kc int(np.argmax(mag)) # 载波峰全谱最大 fc freqs[kc] def peak_near(f0): lo np.searchsorted(freqs, f0 * (1 - span)) hi np.searchsorted(freqs, f0 * (1 span)) k lo int(np.argmax(mag[lo:hi])) return mag[k] a_up peak_near(fc fm_guess) # 上边带 a_dn peak_near(fc - fm_guess) # 下边带 a_sb 0.5 * (a_up a_dn) # 双边带取平均抵消不对称 return 2 * a_sb / mag[kc], fc为什么这里用汉宁窗矩形窗的旁瓣只衰减十几个 dB载波那么强旁瓣会直接盖住边带小调制度时读出来的边带其实是载波的泄漏。汉宁窗旁瓣压到三十多 dB代价是主瓣变宽到 4 个谱线间隔。主瓣宽度直接决定了 FFT 点数够不够。载波和边带在频率上相距 fm要把两团主瓣分开至少要求频率分辨率优于 fm 的三分之一也就是点数不少于三倍采样率除以调制频率。这个数字算出来往往比想象的大很多人在这里踩坑用 1024 点去做 1 kHz 调制的信号边带和载波糊成一团。栅栏效应是第二条误差来源。边带峰未必正好落在某条谱线上落在两条谱线中间时幅度最多被低估一成多ma 就系统性偏小。工程上的做法是做抛物线插值找到峰值谱线 k 及其左右两条用三点幅度反算真实峰位置。def parabolic_offset(a, b, c): a,b,c 为 k-1,k,k1 三条谱线幅度; 返回相对 k 的小数偏移 d a - 2 * b c return 0.0 if abs(d) 1e-12 else 0.5 * (a - c) / d算出的偏移量代回去修正幅度频率和幅度都能提一个数量级。这个技巧不复杂但测评时被问到你怎么处理栅栏效应能报出公式和误差改善量分就稳了。3.3 三条路线的对比表与追问怎么接路线适用 ma 区间数据量主要误差源现场调试难度下变频包络 分位数20% 以上几十毫秒峰谷判读受噪声影响低参数少FFT 边带比值 插值5% 以上几百毫秒以上分辨率不足、栅栏效应中点数要算模拟二极管检波30% 以上连续二极管死区、温度漂移低但边界差三类方案的差别本质上是时域判峰和频域读线的差别。时域省算力边界差频域费算力边界好。真正稳的做法是两个都实现按 ma 的粗测值自动切换先用包络法粗算一个 ma低于阈值就转 FFT 法。这个切换逻辑本身就是一个加分点。常被追问的还有为什么不用二极管包络检波。答法不要否定它要说清边界二极管有零点几伏的死区小调制度时谷值根本检不出来温度一变死区跟着变读数漂。它便宜、快、不需要 ADC做粗测或做参考通道都合适但拿它去顶指标不现实。4. 高频考点FM 调频度 mf 与两个频率量的估计4.1 瞬时频率法相位差分拿 Δf再除 fm调频波的调频度是最大频偏除以调制频率所以核心是两件事把瞬时频率曲线画出来读出它的峰峰值再把这根曲线的振荡频率测出来。瞬时频率靠解析信号的相位差分拿。相邻两点的相位差除以采样间隔就是这一点的瞬时角频率。乘上解析信号、去掉载波分量之后剩下的就是纯频偏曲线。import numpy as np from scipy.signal import hilbert, medfilt def fm_index(x, fs, fc): n len(x) t np.arange(n) / fs z hilbert(x) * np.exp(-2j * np.pi * fc * t) dphi np.diff(np.unwrap(np.angle(z))) f_inst dphi * fs / (2 * np.pi) # 相对 fc 的瞬时频偏 f_inst medfilt(f_inst, 5) # 中值滤波去掉脉冲噪声 f_inst f_inst[int(0.1 * n):int(0.9 * n)] df_pp np.percentile(f_inst, 99) - np.percentile(f_inst, 1) # 约等于 2Δf seg f_inst * np.hanning(len(f_inst)) fm np.fft.rfftfreq(len(seg), 1 / fs)[int(np.argmax(np.abs(np.fft.rfft(seg))))] return (df_pp / 2) / fm, fm, f_inst采样率是这条路线成败的关键。相位差分的噪声会被采样率放大每个采样点的相位噪声是固定量级差分除以采样间隔后频率噪声正比于采样率。只按两倍载波取采样率差分级别的噪声就能吃掉整个频偏读数。工程上取八到十倍载波或者用带通采样把载波搬到中频再处理。中值滤波窗口取五个点是个起点实际要按一个载波周期对应几个采样点来定。窗口短了去不掉脉冲长了会把频偏曲线的峰削平mf 偏小。有个反直觉的结论值得记住fc 估偏一点对 mf 的影响其实不大。因为频偏曲线整体平移峰峰值不变。真正被 fc 误差影响的是载波频率那个测点本身。这一点答出来能说明你是真做过不是背的。4.2 贝塞尔边带比值法小 mf 好用大 mf 会翻车调频波的频谱是贝塞尔函数的展开载波幅度正比于零阶第一对边带正比于一阶依此类推。小调频度下有个简洁近似一阶边带幅度比上载波幅度正好约等于 mf 的一半。mfJ0J1J1/J02·J1/J00.20.99000.09950.10050.2010.50.93850.24230.25820.5161.00.76520.44010.57511.1501.50.51180.55791.09002.1802.00.22390.57702.57705.1502.40.00250.5202208 量级—表里能读出两件事。mf 小于 0.5 的时候那个乘二的近似误差在百分之三以内可以直接用mf 到了 1误差就上到一成半必须查表反解。更要命的是非单调零阶贝塞尔函数在 2.4 附近过零比值在这里发散过了这个点又往下走同一个比值对应两个甚至多个 mf。所以这条路线只在 mf 小于 1 的窄区间里能独立用其余情况要么配合高阶边带联合反解要么干脆退回瞬时频率法。反过来小 mf 恰恰是瞬时频率法最难受的区间——两条路线正好互补按粗测值切换是正解。顺便说一个校准技巧零阶贝塞尔函数过零时载波谱线会消失这叫载波零点法。用标准信号源把 mf 缓慢调到载波消失此时 mf 恰好是那个已知的零点可以拿来标定整个调频通道的增益。这个方法不需要高精度仪器现场很好用。4.3 载波与调制频率闸门法、等精度与频谱插值载波频率如果靠计数法测误差主要来自闸门的 ±1 个计数。闸门时间固定时被测频率越低相对误差越大。真正的解法是等精度测量闸门由被测信号自己开合同时数被测脉冲和标准时钟脉冲误差只跟标准时钟和闸门长度有关跟被测频率无关。调制频率这边走频谱更省事但分辨率同样是硬约束。频率分辨率等于采样率除以点数想读准 fm 就得把点数堆上去或者做频谱插值。插值公式前面给过一个用在三条谱线上能把频率估计精度提高五到十倍代价只是几行代码。两个频率量的共同要求是测 fc 时用宽带通道测 fm 时用窄带通道别指望一条路径同时满足。前端切换量程之后滤波器的群延迟会变包络的相位会跟着变这一点在下一章还会展开。4.4 追问演练mf 小于 1 时读数为什么开始抖测评老师很爱在这个点上停一下你的调频度在小信号端为什么跳得厉害答题分三层。第一层讲现象归因mf 小意味着频偏小瞬时频率曲线的摆幅和相位差分的噪声同量级信噪比直接塌了。第二层讲分母mf 等于频偏除以调制频率分母的测量误差和分子的误差按同样的比例进结果两边一叠加误差翻倍。第三层讲对策加大采样率压噪声、多段数据同步平均、或者在 mf 小于某个阈值时自动切到贝塞尔边带比值法——小 mf 时能量集中在第一对边带比值法正好占便宜。最后补一句我在两种方法之间做了交叉校验读数相差超过阈值就提示重新测量这句话的分量比任何公式都重因为它说明你想过读数的可信度问题。5. 易错点测评台上五个当场失分的做法5.1 用最大值最小值直接算 ma错在哪包络序列直接求全局最大和全局最小代进定义式算调制度。为什么错单点极值对噪声最敏感。噪声让最大值偏高、最小值偏低分子被放大、分母被压缩ma 系统性偏大而且随着信噪比下降越来越偏。现场换个信号源幅度读数就跳一格评委一眼看出不稳。怎么答对改成 99 和 1 分位数或者对包络做直方图找双峰。答辩时把极值统计量对野值敏感这句话说出来再补一句分位数相当于给峰谷判读加了一个软阈值这题就过了。5.2 采样率只按两倍载波取错在哪按奈奎斯特定理取最低采样率觉得够用就行。为什么错定理保证的是能恢复不是能测准。调幅通道里采样率低意味着每个载波周期只有两三个点下变频后的低通几乎没得选调频通道里相位差分噪声正比于采样率两倍采样下瞬时频偏的抖动可以直接吃掉小 mf 的读数。怎么答对说清楚两条路线各自的采样率下限直接采样取八到十倍载波或者走带通采样但必须显式算出混叠后的频率并做校验。答辩时主动说我留了多少余量、为什么留比报一个数字更有说服力。5.3 一个 FFT 同时测四个量错在哪一帧数据做一次频谱载波、边带、调制频率全在同一张谱上找。为什么错四类谱线的分辨率需求差一个量级。载波频率是窄带高峰几百点就够边带要和载波分开点数得往上翻调制频率藏在包络里得先把载波去掉。用一套参数硬扛结果是每一项都勉强及格边界测点全超差。怎么答对讲清分通道、分量程的结构——粗测用短帧快出结果精测用长帧单独跑两次测量之间用粗测结果约束搜索范围。这不是浪费算力是把算力花在刀刃上。5.4 换量程不重跑基线错在哪前端换挡之后接着往下测不重新做零点和增益校准。为什么错换挡意味着换了一条模拟通道放大器的增益误差、抗混叠滤波器的群延迟、甚至 ADC 输入端的偏置全都变了。包络法对这种变化尤其敏感因为它读的是绝对幅度。血泪经验是中段测得很准一换到小量程ma 整体偏了两三个百分点。怎么答对给出换挡即重校的流程并说明用内部参考信号做两点校准零点用静默段、增益用标准幅度段。答辩时说清我把校准做成了换挡后的自动动作操作者不需要记住评委会认这个设计。5.5 显示直接刷单次结果错在哪每次测量就把当前值直接推到屏幕上末位一直跳。为什么错单次测量的方差摆在那儿末位跳动不代表算法差但评委看到的就是读数不稳稳定度这一项直接扣。而且人眼对跳动的容忍度极低跳两下就会被判不可用。怎么答对加滑动平均并且设一个死区——变化量小于末位一个字就不刷新。同时保留一个快速模式用于找信号一个稳定模式用于读数用按键切换。答辩时把这两种模式的区别讲清楚说明你知道实时性和稳定性是矛盾的。6. 从代码到测评台把误差压到指标内的三步走代码跑通只是起点能不能在测评台上守住指标取决于误差有没有被分配过。我的做法是把自己的链路按环节列出来逐段估误差再决定每一段花多少代价。环节典型误差来源处理动作现场怎么验证前端调理增益漂移、滤波器通带不平换挡自动重校通道幅频建档换挡后测同一点看读数是否回原位采样相位噪声、时钟抖动采样率留八倍余量时钟走独立低抖路径输入纯载波看瞬时频率曲线的厚度频率估计分辨率不足、栅栏效应长帧加窗三点抛物线插值换不同点数的两帧看结果是否收敛比值计算谱线泄漏、边带不对称双边带取平均搜峰范围按 fm 约束人为让上下边带不等看平均是否稳显示单次方差大滑动平均 死区刷新连续观察一分钟末位是否只在一个字内跳三步走的顺序别搞反。第一步是分段验证只给纯载波看频率读数准不准再给单音调幅看包络好不好最后给调频看瞬时频率曲线干不干净。哪一步的残差超了预期就停在那里查不要带着病往下走。第二步是边界扫描调制度从 10% 一路拉到 90%每 10% 记一个点画出误差曲线。误差曲线如果是单调的说明有一处系统性偏差可以补如果是忽大忽小的锯齿说明是随机噪声得靠平均。第三步才是自动切换把前面测出来的边界写进判断条件让装置自己选路线。押题的角度也说一句。这类题现场的追问高度集中在三个方向一是边界上你怎么保证二是两种方法结果不一致你信谁三是如果只能保留一个误差源你砍哪个。前两个对应上面的边界扫描和交叉校验第三个考的是误差分配的意识——答砍掉前端增益漂移因为它同时污染所有测量量而频谱分辨率只污染小调制度那一段方向就对了。从那以后我每次做完这类测量装置都会强制走一遍纯载波—单音调幅—单音调频的三段验证哪怕时间只剩半小时。因为翻车从来不是因为算法不够聪明而是因为没人愿意在边界上多测那三个点。这份A题代码工程按调幅、调频、频率估计分了模块参数和切换阈值都写在注释里照着跑一遍再对着自己的板子改比看十篇经验帖快。希望帮到你。本文还有配套的精品资源点击获取