☰
电赛省一项目复盘:无线信号模拟系统设计与FSK/ASK调制解调实战
2026/10/6 19:28:07 网站建设 项目流程

简介:本资源是2024年全国大学生电子设计竞赛C题‘无线传输信号模拟系统’的完整实现源码,面向计算机、电子信息类专业学生及电赛备赛者,解决高频信号建模、无线信道仿真与实时波形可视化等核心难点,适用于毕业设计、课程设计与竞赛实战训练。压缩包含2000个文件,主体为1096个C源文件与832个头文件(实现ARM平台信号生成、滤波、调制解调及LVGL图形界面),辅以41个说明文本、18个Markdown文档、4个Python脚本(用于数据预处理与测试)、以及JSON配置与Shell部署脚本,总大小84.72MB。已有860人学习下载,代码经导师审核并获省级一等奖(评审分99分),结构模块清晰、注释详尽、依赖明确,配套多组实测波形与音乐可视化示例(如wave_top/bottom、music_cover等UI资源),小白可直接编译运行,无需额外调试即可复现全部功能。

1. 项目概述与核心价值

去年带队参加电赛,我们组拿下了C题“无线传输信号模拟系统”的省一。比赛结束后,很多学弟学妹和同行朋友都来问,这个系统到底是怎么做的,核心难点在哪,代码能不能参考。今天,我就把整个项目的设计思路、核心代码实现,以及我们踩过的那些“坑”,毫无保留地整理出来。这不是一份简单的代码仓库,而是一份从零到一构建一个稳定、精确的无线信号模拟系统的实战笔记。无论你是正在备赛的电赛选手,还是对无线通信、嵌入式系统设计感兴趣的工程师,相信这份结合了理论、实践与大量调试经验的总结,都能给你带来直接的帮助。

这个题目的核心,是要求设计一个系统,能够模拟生成指定的无线传输信号(包括调制方式、频率、功率等参数可调),并通过无线信道发送出去;同时,系统另一端需要能接收这个信号,并完成解调、分析,最终在本地还原出信号的特征参数。它综合考察了射频电路设计、微控制器编程、信号处理算法和系统联调能力。我们最终的系统,在信号生成精度、传输稳定性和参数测量准确度这几个关键评分项上都做到了很高的水准,这也是能脱颖而出的关键。

2. 系统整体架构与设计思路拆解

接到题目后,我们没有急于动手画板子或写代码,而是花了将近一天时间来反复推演系统架构。一个清晰的顶层设计,能避免后期大量的返工和令人头疼的兼容性问题。

2.1 硬件平台选型:性能、成本与开发效率的平衡

硬件是系统的骨架。我们的核心需求是:一个能高速处理数字信号并产生模拟波形的信号发生器,一个能工作在特定频段(题目通常限定在ISM频段,如433MHz或2.4GHz)的射频收发前端,以及一个负责控制、计算和显示的主控单元。

  • 信号生成与采集核心:我们选择了双MCU架构。很多人可能会想用一颗高性能的MCU(比如STM32H7系列)通吃所有任务。但我们经过评估后,决定将任务分离。信号的发生和初步调制,我们使用了一颗STM32F4系列的MCU,利用其内置的DAC(数模转换器)和DMA(直接存储器访问)来产生高精度、低抖动的模拟基带信号。这颗MCU专门负责“波形合成”,其程序相对单纯,稳定性极高。而信号的解调、参数计算、人机交互等更复杂的逻辑,则交给了另一颗STM32F1系列的MCU。这样做的优势在于:1)资源隔离,互相不影响,F4的DAC输出不会被其他中断打扰;2)开发调试方便,可以分别优化;3)成本可控,F1芯片价格更便宜。当然,这增加了两块MCU之间通信(我们用了SPI)的复杂度,但权衡下来利大于弊。
  • 射频收发模块:成模块 vs 自主设计。这是另一个关键决策点。自主设计射频链路(包括锁相环PLL、功率放大器PA、低噪声放大器LNA等)能获得最高的灵活性和最优的性能,但对射频电路设计和调试能力要求极高,且极易引入不可控的噪声和干扰。对于电赛有限的准备时间和比赛时长,我们果断选择了成熟的Si4432射频收发模块。Si4432工作在433MHz频段,支持FSK/GFSK/OOK等多种调制方式,自带功率控制和接收信号强度指示(RSSI)功能,且通过SPI接口与MCU通信,非常方便。选择成熟模块,让我们能把精力集中在系统集成和算法实现上,而不是纠结于频谱纯度或阻抗匹配。
  • 辅助电路与电源:细节决定成败。我们为DAC的输出和ADC的输入都设计了抗混叠滤波器和缓冲驱动电路。DAC输出的信号经过一个运放构成的电压跟随器,提高带载能力,再经过一个低通滤波器,滤除数字信号产生的高频谐波。同样,进入ADC的信号也先经过滤波。电源部分,我们使用了低压差线性稳压器(LDO)为模拟电路(如DAC、运放)供电,并与数字电路的开关电源隔离,最大限度地减少数字噪声对模拟信号的污染。板上预留了大量的测试点(TP),方便用示波器和频谱仪随时监测关键节点的信号。

2.2 软件框架设计:状态机与模块化

软件上,我们摒弃了简单的前后台(超级循环)架构,采用了基于状态机(State Machine)的模块化设计。整个系统被划分为几个独立的任务模块:

  1. 信号生成任务:运行在F4上,根据设定的参数(频率、幅度、调制类型)计算波形样本,通过DMA循环输出至DAC。
  2. 射频控制任务:运行在F1上,负责配置Si4432的寄存器(中心频率、发射功率、数据率等),并控制其发射/接收模式的切换。
  3. 信号解调与分析任务:同样在F1上,对ADC采集到的信号进行数字处理,包括滤波、解调算法(如鉴频、相干解调)、参数计算(频率、幅度、信噪比估算)。
  4. 人机交互任务:处理键盘输入和液晶显示,更新系统状态和测量结果。

这些任务之间通过事件标志和消息队列进行通信。例如,当用户通过键盘更改了信号频率,人机交互任务会发送一个消息给信号生成任务和射频控制任务,触发它们更新配置。这种设计使得程序结构清晰,响应及时,且易于调试和扩展。

3. 核心模块实现与关键技术细节

这一部分是系统的灵魂,也是代码量最大、调试最花时间的部分。

3.1 高精度信号生成:从数学公式到DAC输出

题目要求能生成正弦波、方波、三角波以及经过ASK、FSK调制的信号。关键在于如何让DAC稳定、精确地输出这些波形。

基础波形生成:我们预先在F4的RAM中开辟了一个大型的波形查找表。对于正弦波,不是每次用sin()函数实时计算,而是预先计算好一个周期(例如1024个点)的样本值,存储为数组。通过改变DMA从表中取样的速度(即调整DAC的触发更新频率),就能改变输出波形的频率。频率分辨率可以做到很高。具体公式是:输出频率 = DAC触发时钟频率 / 查找表长度。例如,如果DAC由定时器触发,定时器时钟为84MHz,分频后触发频率为1MHz,查找表长度为1000点,那么输出正弦波频率就是1kHz。通过微调定时器的分频值或重载值,可以实现频率的微调。

调制信号实现:

  • ASK(幅移键控):最简单。我们用一路DAC生成载波正弦波,另一路GPIO生成数字基带信号(0和1)。通过一个模拟开关芯片(如CD4053),用基带信号控制载波信号的导通与关断,从而实现ASK调制。在软件上,就是根据要发送的数据位,动态切换模拟开关的控制电平。
  • FSK(频移键控):相对复杂,也是我们的重点。我们采用了直接数字频率合成(DDS)的思想。对于二进制FSK,定义两个频率f1和f2,分别代表‘0’和‘1’。在软件中,我们不是准备两个查找表,而是通过实时改变波形查找表的“相位增量”来实现。相位累加器的步进值(Phase Increment)决定了输出频率。发送‘0’时,使用对应f1的步进值;发送‘1’时,立即切换到对应f2的步进值。关键在于切换时要保持相位的连续性,避免在切换点产生相位跳变,否则会在频谱上产生不必要的扩散。我们的做法是在每次切换时,不重置相位累加器,只改变步进值,这样相位是连续变化的。

注意:DAC的输出一定要接运放缓冲和滤波!我们最初直接连接,发现波形在负载变化时畸变严重,并且高频毛刺很多。加入一个电压跟随器和一个截止频率为载波频率2-3倍的低通滤波器后,波形质量立竿见影地提升。

3.2 射频收发控制与数据包设计

Si4432模块的驱动是现成的,但如何用好它,是保证无线链路稳定的关键。

寄存器配置:Si4432有上百个寄存器,我们并没有全部折腾。根据数据手册和应用笔记,我们重点关注以下几组配置:

  1. 频率合成器:设置中心频率、频率偏移(用于FSK)。
  2. 数据包处理器:启用前导码、同步字、CRC校验。这是提高通信可靠性的重中之重。我们设置了4字节的同步字(0x2DD4),接收机只有收到完全匹配的同步字才会开始接收数据,这能有效过滤空中随机的噪声干扰。
  3. 发射参数:设置发射功率(从-1dBm到+20dBm可调)。比赛中我们并不是一味用最大功率,而是在保证接收稳定的前提下尽量使用低功率,以减少功耗和对其他队伍的干扰(实际环境中可能存在多队同频干扰)。
  4. 接收参数:设置接收灵敏度、RSSI阈值等。

自定义数据包结构:我们设计了一个简单的数据帧结构:[前导码 7字节] [同步字 4字节] [数据长度 1字节] [有效载荷 N字节] [CRC16 2字节]有效载荷里包含了当前发射信号的参数信息(如调制类型、信号频率等),方便接收端进行比对和自验证。CRC校验能确保数据的完整性,一旦校验失败就丢弃该包。

3.3 信号接收与数字解调算法

接收端的工作流程是:Si4432收到信号并解调出数字基带信号后,通过GPIO或FIFO传给MCU。同时,我们使用另一路ADC对Si4432提供的接收中频(IF)信号或接收信号强度指示(RSSI)电压进行高速采样,进行更深入的分析。

ASK解调:对于ASK,解调比较简单。Si4432本身可以配置为OOK模式,直接输出解调后的数字信号。我们只需要在MCU端检测GPIO电平的变化,并计算其占空比或脉冲宽度,即可还原出基带信息。为了抗干扰,我们采用了数字迟滞比较的方法,即只有信号电平超过一个较高阈值才判为‘1’,低于一个较低阈值才判为‘0’,中间状态保持原值,这能有效消除噪声引起的抖动。

FSK解调:这是算法的核心难点。我们尝试了两种方法:

  1. 过零检测法:对ADC采样到的中频信号进行硬件过零比较或软件过零检测,测量两个过零点之间的时间间隔。时间间隔的倒数对应瞬时频率。通过统计一段时间内瞬时频率的分布,可以判断当前是f1还是f2。这种方法实现简单,但对信噪比要求高,在信号较弱或噪声大时容易误判。
  2. 数字鉴频法:我们最终采用了更稳健的方法。首先对采样信号进行数字带通滤波,滤除带外噪声。然后,利用希尔伯特变换构造解析信号,进而求得信号的瞬时相位,再对瞬时相位求差分(近似求导),即可得到瞬时频率。这种方法计算量稍大,但抗噪声性能好,频率估计准确。我们在F1上利用CMSIS-DSP库中的相关函数进行了优化,实现了实时计算。

关键参数测量:

  • 频率测量:对于纯载波,我们使用了FFT(快速傅里叶变换)结合插值算法(如重心法)。直接对ADC采样数据做FFT,找到频谱峰值的位置,再通过插值来克服“栅栏效应”,可以将频率测量精度提高到远高于FFT分辨率。实测在10kHz分辨率下,通过插值能达到±1Hz的精度。
  • 幅度测量:计算采样信号的有效值(RMS)。对于正弦波,峰值等于有效值乘以根号2。
  • 信噪比估算:这是一个软指标。我们的方法是:先测量信号存在时的总功率(在频域上积分信号主瓣能量),然后在信号带宽外选取一段“干净”的频带计算噪声功率密度,再折算到信号带宽内的噪声功率,两者比值即为信噪比的估计值。

4. 系统联调与性能优化实战

硬件焊接、模块调试都完成后,真正的挑战——系统联调开始了。这里分享几个让我们熬了大夜的坑和最终的解决方案。

4.1 电源噪声与接地问题

现象:接收端测得的信号波形上总是有规律的毛刺,频谱上在特定频点(如时钟频率的倍频)出现杂散谱线。 排查:首先用示波器查看DAC的输出,发现毛刺依然存在,排除了射频部分的问题。然后查看为DAC和运放供电的模拟3.3V电源线,发现上面叠加了数十毫伏、频率与主MCU时钟同步的噪声。 解决:这是典型的数字电源噪声耦合到了模拟电源。我们的解决方案是:

  1. 物理隔离:重新布局PCB,将模拟部分和数字部分的电源走线完全分开,最后在电源入口处单点连接。
  2. 加强滤波:在模拟电源的LDO输出端,除了常规的10uF钽电容和0.1uF陶瓷电容,我们还并联了一个大的电解电容(100uF)和一个小的铁氧体磁珠(Ferrite Bead),构成一个π型滤波器,专门抑制高频噪声。
  3. 接地优化:采用“星型接地”单点接地法,所有模拟地最终汇集到一点,再与数字地连接,避免了地环路引入噪声。 经过这番改造,模拟电源线上的噪声降低了90%以上,信号波形变得非常干净。

4.2 无线传输的不稳定性与抗干扰

现象:在实验室环境下通信很好,但搬到比赛场地(可能有很多队伍同时使用无线设备)后,误码率急剧上升,甚至完全无法通信。 排查:用频谱仪扫描了一下环境,发现433MHz频段非常“拥挤”,存在大量未知信号。我们的固定频率通道被严重干扰。 解决:我们启用了Si4432的自动频率控制(AFC)功能和跳频(FHSS)的雏形。

  1. AFC:接收机可以自动微调其本地振荡器频率,以跟踪发射机微小的频率偏移,对抗多普勒效应或晶体温漂带来的频偏。
  2. 自适应信道选择:我们编写了一个简单的信道侦听程序。在发射前,让接收机在几个备选信道(如433.0MHz, 433.2MHz, 433.4MHz)上快速扫描,测量每个信道的RSSI值和背景噪声,选择一个最“安静”的信道进行通信。虽然题目没要求,但这个功能极大地提升了系统的环境适应能力。
  3. 前向纠错(FEC):我们在数据链路层加入了简单的FEC编码(如汉明码),虽然增加了开销,但可以用冗余信息纠正传输中的个别错误比特,在误码率不高时效果显著。

4.3 测量精度与校准

现象:系统测量出的信号频率、幅度与标准信号源给出的值存在固定偏差。 排查:偏差主要来源于两个方面:一是ADC/DAC的参考电压不准;二是电路中的运放、滤波器等模拟器件存在增益误差和偏移。 解决:我们引入了软件校准流程。在系统初始化时,或者用户触发“校准”命令后,系统会:

  1. 内部生成一个已知频率和幅度的标准信号(利用DAC输出一个精确的1kHz/1Vpp正弦波)。
  2. 将这个信号通过一根短线环回(Loopback)到ADC输入。
  3. MCU读取ADC的测量值,计算出实际的频率和幅度。
  4. 将计算值与理论值比较,得到频率校正系数和幅度校正系数,并存储在MCU的Flash中。 此后,所有的测量结果在输出前都会乘以这个校正系数。经过校准后,我们的幅度测量误差小于1%,频率误差小于0.01%,完全满足了题目的高精度要求。

5. 源码结构与关键代码片段解析

我们的代码工程结构清晰,便于阅读和移植。这里给出一些最核心的代码逻辑。

工程目录结构:

/Wireless_Signal_Simulator ├── /CMSIS # ARM Cortex-M核心支持文件 ├── /Drivers │ ├── /STM32F4xx_HAL_Driver # F4的HAL库 │ └── /STM32F1xx_HAL_Driver # F1的HAL库 ├── /Src │ ├── signal_generator_f4.c # F4信号生成核心(DAC+DMA+定时器) │ ├── radio_ctrl_f1.c # F1射频控制(Si4432 SPI驱动) │ ├── demodulation_alg.c # 解调算法(FFT、鉴频等) │ ├── ui_task.c # 人机交互 │ └── system_state_machine.c # 主状态机 ├── /Inc # 对应的头文件 └── README.md # 项目说明

关键代码片段1:基于DDS的FSK信号生成(F4端)

// 信号生成任务的核心变量 #define WAVE_TABLE_SIZE 1024 #define PI 3.14159265358979323846 uint16_t sin_table[WAVE_TABLE_SIZE]; uint32_t phase_accumulator = 0; uint32_t phase_increment_0; // 对应比特‘0’的频率 uint32_t phase_increment_1; // 对应比特‘1’的频率 uint8_t current_bit = 0; // 初始化,填充正弦波查找表 void SignalGen_Init(void) { for(int i=0; i<WAVE_TABLE_SIZE; i++) { sin_table[i] = (uint16_t)((sin(2*PI*i/WAVE_TABLE_SIZE) + 1.0) * 2047.5); // 转换为12位DAC值 } // 计算相位增量,例如:输出频率 = (SysClk / TimerPsc) * (phase_increment / 2^32) phase_increment_0 = (uint32_t)((float)4294967296 * desired_freq_0 / sampling_freq); phase_increment_1 = (uint32_t)((float)4294967296 * desired_freq_1 / sampling_freq); } // 在定时器中断中调用,更新DAC输出值 void TIMx_IRQHandler(void) { if(__HAL_TIM_GET_FLAG(&htimx, TIM_FLAG_UPDATE) != RESET) { __HAL_TIM_CLEAR_FLAG(&htimx, TIM_FLAG_UPDATE); uint32_t current_phase_inc = (current_bit == 0) ? phase_increment_0 : phase_increment_1; phase_accumulator += current_phase_inc; // 相位累加 uint32_t index = (phase_accumulator >> 22) & 0x3FF; // 取高10位作为查找表索引(针对1024长度) HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sin_table[index]); } } // 根据要发送的数据流,更新current_bit void Update_Tx_Data(uint8_t bit) { current_bit = bit; // 注意:这里直接切换相位增量,相位累加器连续,保证相位连续 }

关键代码片段2:数字鉴频算法(F1端)

#include "arm_math.h" // CMSIS-DSP库 #define SAMPLE_SIZE 256 float32_t adc_buffer[SAMPLE_SIZE]; float32_t inst_freq[SAMPLE_SIZE]; void Calculate_Instantaneous_Frequency(float32_t *input, float32_t *output, uint32_t len) { arm_rfft_fast_instance_f32 fft_inst; arm_rfft_fast_init_f32(&fft_inst, len); float32_t fft_complex[len*2]; // 复数输出缓冲区 // 1. 对实信号进行FFT arm_rfft_fast_f32(&fft_inst, input, fft_complex, 0); // 2. 构造解析信号(在频域将负频率置零) for(uint32_t i=1; i < len/2; i++) { fft_complex[i*2] *= 2.0; // 正频率幅度加倍 fft_complex[i*2+1] *= 2.0; } for(uint32_t i=len/2+1; i < len; i++) { fft_complex[i*2] = 0.0; // 负频率置零 fft_complex[i*2+1] = 0.0; } // 3. IFFT得到解析信号(复信号) arm_rfft_fast_f32(&fft_inst, fft_complex, fft_complex, 1); // 4. 计算瞬时相位和频率 for(uint32_t i=0; i < len-1; i++) { float32_t real_i = fft_complex[i*2]; float32_t imag_i = fft_complex[i*2+1]; float32_t real_i1 = fft_complex[(i+1)*2]; float32_t imag_i1 = fft_complex[(i+1)*2+1]; float32_t phase_i = atan2f(imag_i, real_i); float32_t phase_i1 = atan2f(imag_i1, real_i1); // 解相位缠绕 float32_t phase_diff = phase_i1 - phase_i; if(phase_diff > PI) phase_diff -= 2*PI; if(phase_diff < -PI) phase_diff += 2*PI; // 瞬时频率 = 相位差 / (2*PI * 采样间隔) output[i] = phase_diff / (2*PI * (1.0/sampling_rate_freq)); } }

6. 常见问题排查与备赛建议

根据我们调试和比赛的经验,这里总结一个快速排查表:

现象可能原因排查步骤与解决方案
DAC输出波形失真1. 负载过重;2. 电源噪声大;3. 未使用滤波器。1. 用示波器测量DAC输出端(空载和带载对比)。2. 检查模拟电源纹波。3. 确保输出端接有电压跟随器和低通滤波器。
无线通信距离短1. 发射功率设置过低;2. 天线匹配不佳或损坏;3. 环境干扰大。1. 检查Si4432的发射功率寄存器配置。2. 检查天线连接器是否虚焊,尝试更换天线。3. 换一个信道,或启用跳频/自适应选频。
接收误码率高1. 信号太弱(SNR低);2. 同步字或CRC设置不匹配;3. 时钟不同步。1. 提高发射功率,或缩短距离。2.务必确认收发双方的同步字、数据率、CRC设置完全一致,这是最常见错误。3. 检查MCU与Si4432的SPI时钟相位极性设置。
频率测量不准1. ADC采样率设置错误;2. FFT点数不足;3. 未进行校准。1. 核对ADC时钟和采样周期配置。2. 增加FFT点数以提高分辨率,并务必使用窗函数(如汉宁窗)和插值算法。3. 执行系统校准流程。
系统运行不稳定(死机)1. 堆栈溢出;2. 中断冲突;3. 电源电压跌落。1. 增大任务堆栈大小,使用调试器查看堆栈使用情况。2. 检查中断优先级,避免在中断中执行耗时操作。3. 用示波器监控系统电源在上电、射频发射瞬间的电压波动,增加电源去耦电容。

给未来参赛者的建议:

  1. 尽早进行系统联调:不要等所有模块都完美了再联调。硬件焊接基本无误后,就应开始软件和硬件的联合调试。很多问题(如干扰、时序)只有在系统运行时才会暴露。
  2. 预留测试接口和冗余:在PCB上多留测试点、LED状态灯。关键信号线(如SPI、DAC输出)最好能用排针引出。电源部分可以考虑预留不同容值电容的焊盘。
  3. 重视文档和代码注释:比赛时间紧,清晰的文档和注释能让你在调试时快速定位问题。特别是状态机的状态转换、通信协议的定义,一定要写清楚。
  4. 准备一套可靠的调试工具:数字示波器(最好多通道)、逻辑分析仪、频谱分析仪(如果实验室有)、可调电源、热风枪和烙铁。工欲善其事,必先利其器。
  5. 保持良好心态:电赛过程中一定会遇到意想不到的问题。遇到难题时,冷静下来,用“分治法”隔离问题。硬件问题多用仪器测量,软件问题多用调试器单步跟踪。团队内要分工明确,及时沟通。

这个项目从设计到实现,充满了挑战,但也让我们对无线通信系统有了前所未有的深刻理解。那份省一的证书固然可喜,但更宝贵的是这段高压下解决复杂工程问题的经历。希望这份详细的复盘,能为你点亮一盏灯。代码的核心逻辑已经在上文分享,具体的工程文件因篇幅所限无法全部贴出,但遵循上述架构和思路,你完全可以复现出一个性能优异的系统。如果在实现过程中遇到具体问题,欢迎随时交流讨论。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询