简介:基于单片机的相位计设计资料包,面向电子、通信类毕业设计学生与嵌入式初学者,完整覆盖从理论分析到软硬件实现的全过程。资料以相位差测量为核心,包括输入信号调理电路、显示模块、接口电路、电源管理等硬件方案,以及ADC采样、FFT数字信号处理、相位计算、交互界面等软件实现思路,适合作为课程设计或毕设的参考框架。
包内共36个文件,大小4.41MB,以PDF论文与DOC文档为主,另有C/H源代码、Keil工程文件、原理图、Hex烧录文件、元器件数据手册及波形图等。论文部分涵盖多种相位测量方法,原理图便于理解硬件连接,源程序可直接参考或二次开发。
目前已有56人学习下载,对于希望快速搭建原型并撰写论文的学生来说,可直接复用其中的设计文档、代码与参考论文,节省查阅和整理资料的时间,同时也能借助完整的软硬件配套材料,深入掌握单片机的实际工程应用。
1. 相位计用单片机测的是什么,为什么能成毕业设计
两个同频正弦信号之间的相位差,用示波器看最直观,但要把这个量做成一台能自动读数、能连续显示、还能写进论文里的仪器,很多人第一反应是加上一大片模拟电路。实际把方案做下来会发现:精度上限最先卡在过零比较器前面的运放和电阻上,单片机定时器只是把两路信号过零点的相对时间差读出来,测相位这件事就完成了。这个标题覆盖的是一条完整信号链:前级放大整形、相位差提取、定时器捕获、软件校准,以及用于存档和答辩的测试数据。适合电子与自动化方向的课程设计、毕业设计,也适合初入行的嵌入式工程师理解一台“测量系统”的完整长相。
2. 相位差测量原理:过零检测与 FFT 两条路线怎么选
2.1 过零检测法:把相位差折算成时间差
两路同频正弦波过零点在时间轴上错开 Δt,周期为 T,则相位差 φ = 360° × Δt / T。单片机能直接量到的只有电平和时间,所以常见做法是把正弦波经过比较器整形成方波,再用单片机的输入捕获功能记录上升沿的定时器计数值。只要两路信号频率相同,这个映射关系就严格成立;频率不同时“相位差”没有定义,仪器应该提示频率超出量程,而不是给一个随机数。
设计时先定量程再选器件。比如输入频率 10Hz~50kHz,定时器计数频率 72MHz,在 50kHz 时每个周期只有 1440 个计数,量化相位分辨率 0.25°,这个量级已经接近过零抖动的影响;在 10Hz 时有 720 万个计数,量化误差几乎可以忽略。如果用的是 51 单片机的 12MHz 主频且没有硬件捕获,计数频率只能到 1MHz 左右,50kHz 下只剩 20 个计数,此时必须靠外部计数或更高主频来撑,这也是后面软件设计中优先推荐带输入捕获的 32 位定时器的原因。
2.2 FFT 相位谱方法:把问题从时域搬到频域
另一条思路是对两路信号分别做 ADC 采样,得到离散序列后做 FFT,取出基波分量的复数表示,相位就是 atan2(imag, real)。两路信号的基波相位相减得到相位差。FFT 法不需要整形电路,波形畸变、带谐波时仍然能锁定基波相位;代价是需要较高的采样率和足够的样本点数,计算量大,STC89C52 这类 8 位机跑得很吃力,用 STM32 时也要考虑是定点 FFT 还是浮点 FFT。
教学项目里 FFT 方案还有一个实际难点:很难向答辩老师讲清楚整周期采样和频谱泄漏的关系,而过零检测用一条波形图就能说明白。两者并不互斥,频率较高或者信号噪声大时,可以用 FFT 做精测,用过零检测做快速扫频。但就这个标题来说,过零检测法硬件成本低、软件链路短,更适合完整走一遍软硬件设计流程。
2.3 两种方案的对比与选型结论
| 对比项 | 过零检测法 | FFT 相位谱法 |
|---|---|---|
| 硬件开销 | 运放、比较器,不需要 ADC 采样保持 | 需要较高采样率的 ADC 和缓冲电路 |
| 可测频率上限 | 受比较器带宽和捕获速度限制 | 受 ADC 采样率和 FFT 点数限制 |
| 抗噪声能力 | 一般,过零点抖动直接进入误差 | 较强,窗函数能抑制带外噪声 |
| 对波形要求 | 近似正弦,或至少过零稳定 | 周期信号皆可,谐波不影响基波测量 |
| 软件代码量 | 少,核心几十行 | 较大,需要傅里叶变换和定标 |
| 误差校准难度 | 简单,线性拟合即可 | 复杂,要考虑采样同步和频谱泄漏 |
从课程设计和大多数工程测量需求来看,过零检测法结构最清晰、成本最低、校准最直观。下面的硬件和软件设计都按过零检测方案展开,这也是这类设计最常见的落地路径。
2.4 先定指标再选器件
动手画原理图之前,先写下一行目标:量程 10Hz~50kHz,相位显示分辨率 0.1°,系统误差不超过 1°。这个目标决定了两件事:比较器要有足够的压摆率,双通道波形在过零点的传输延迟差要小;定时器计数频率要足够高,使量化误差远小于系统误差。量化引起的相位分辨率为 360° × f_signal / f_counter,例如 f_counter = 72MHz、f_signal = 1kHz,则分辨率约 0.005°,已经足够。
有这两项硬指标后,芯片选型就明确了:优先选带输入捕获的 32 位定时器,比如 STM32 的 TIM2、TIM5,因为 32 位计数器在 72MHz 下约 60 秒才回绕,低频信号一个周期内不会溢出;如果必须用 16 位定时器或 8 位单片机,就要另写溢出补偿。这段分析写进论文的“可行性分析”一节,能直接撑起一部分字数。
3. 硬件设计:前级调理、整形和输入捕获接口
3.1 硬件信号链的五个环节
一张通用相位计硬件框图可以拆成五段:输入保护、幅度调理、过零整形、相位差提取、单片机测量与显示。输入保护用两个背靠背二极管把信号钳位在电源轨内,防止误接高压;幅度调理的任务是把 0.1V~5V 的可变输入统一到比较器合适的输入电平;比较器整形把正弦波变成方波;如果采用异或门方案,这里还要加一个 74HC86;最后方波直接进单片机定时器捕获通道。屏幕和按键挂在外设总线即可。
比较重要的是调理与整形的接口。常见做法是用 LM393 搭施密特触发器,正反馈电阻取 10kΩ~100kΩ,反馈比例决定滞回窗口。滞回窗口太小时,噪声会让方波边沿反复抖动;太大时,过零点会被偏移,造成一个固定的相位误差。一般把窗口设在 20mV~50mV 之间,再配合软件平均,效果比单纯追求窄窗口更好。想省掉运放的话,也可以用带滞回的比较器直接接受信号,但输入阻抗和幅度适配会差一些。
3.2 幅度适配的两种做法:手动增益与自动增益
输入幅度范围较宽时,固定增益放大会导致小信号不足、大信号削顶。最稳的教学做法是级联一个运放做 0~20dB 可调增益,用电位器手动校准;工程上常用可变增益放大器或程控增益,但成本和电路复杂度高很多。以 STM32 为核心的方案,也可以干脆不做大幅放大,而是用两路比较器加基准电压产生方波,因为相位测量只关心过零点,不关心幅度。
这里要提醒一个常见误区:不要把正弦波直接接单片机引脚。单片机输入引脚通常带施密特触发,但输入范围不能超过 VDD,负半周会通过引脚内部二极管漏电,长期使用容易损坏。所以哪怕信号已经是干净的方波,也要先经过串联电阻和钳位二极管再进 MCU。硬件调试时如果发现捕获通道计数异常,首先用示波器确认引脚处已经变成 0~3.3V 的方波,而不是原始正弦波。
3.3 双通道捕获 vs 异或门测脉宽
相位提取有两条路可走。一条是把两路整形后的方波直接接到两个输入捕获通道,在软件里做时间差减法,这是推荐做法,既省异或门,还能同时测出周期;另一条是把两路方波接进 74HC86 异或门,输出脉冲宽度等于 Δt,测量脉宽再除以周期。异或门方案单片机只用一路捕获,但异或门输出不包含超前或滞后信息,还要额外用一个 D 触发器判断方向,硬件链路反而更长。
以 STM32F103 为例,定时器 TIM2 的 CH1 和 CH2 分别接基准信号和待测信号,按键接 PB0、PB1,LCD1602 数据线接 PC0~PC7,RS 和 EN 接 PC8、PC9。这样分配可以避开捕获通道的共用引脚。引脚分配是硬件设计里最好改也最容易被忽视的一环,布线前先在表格里过一遍功能复用,否则做完板子才发现调试脚和捕获通道冲突,只能飞线。
| MCU 引脚 | 模块接口 | 功能 |
|---|---|---|
| PA0 | 基准信号整形输出 | TIM2_CH1 输入捕获 |
| PA1 | 待测信号整形输出 | TIM2_CH2 输入捕获 |
| PB0 / PB1 | 按键 | 量程切换、校准模式 |
| PC0 ~ PC7 | LCD1602 D0~D7 | 并口显示数据 |
| PC8 / PC9 | LCD1602 RS / EN | 显示控制 |
3.4 最小系统与调试前的检查点
单片机最小系统就是晶振、复位、电源去耦,外加为调试预留的 SWD 或串口。STM32 用 SWD 时需要 PA13、PA14,20 脚封装里这两个脚经常被占用,布板前要确认。硬件调试顺序建议分三步:先量电源,再量比较器输出,最后量捕获波形。比较器输出端如果出现明显振铃,就在输出串联一个 100Ω 电阻;如果出现多个上升沿,就适当调大滞回窗口。
Keil 环境里常见的坑集中在芯片型号和器件包上。工程建好后第一件事是确认 Device 里选的是实际芯片型号,Pack Install 装的是对应系列,否则编译通过但下载后不进调试、外设寄存器地址对不上的问题会浪费大量时间。这类问题与相位计本身无关,但几乎每个调试现场都会遇到。
4. 软件实现:输入捕获、相位换算和自动量程
4.1 定时器输入捕获初始化与中断读取
软件的第一个任务是配置定时器,让两路信号沿到来时硬件自动记录计数器的当前值。核心点是 PSC 预分频器:分频值越大,可测时间越长,但相位分辨率越低。只要信号频率不低于 10Hz,72MHz 计数频率下用 32 位计数器不会溢出,因此 PSC 直接设 0,不要为了“低频更稳”而分频。用寄存器写初始化代码更直观:
void Phase_Timer_Init(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // 启动 TIM2 时钟 TIM2->PSC = 0; // 计数频率 = 72MHz,不预分频 TIM2->ARR = 0xFFFFFFFF; // 32 位自由运行,不回绕 TIM2->CCMR1 = (0x01 << 0) | (0x01 << 8) // CH1、CH2 映射到输入引脚 | (0x0F << 4) | (0x0F << 12); // 输入滤波 16 个时钟周期 TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; // 使能两路捕获 TIM2->DIER = TIM_DIER_CC1IE | TIM_DIER_CC2IE; // 开捕获中断 NVIC_EnableIRQ(TIM2_IRQn); TIM2->CR1 |= TIM_CR1_CEN; // 启动计时 }CCMR1 的低两位选择通道 1 的输入映射,默认映射到 TI1;高两位对应通道 2 映射到 TI2。输入滤波系数 0x0F 会把窄于 16 个计数时钟的毛刺滤掉,以 72MHz 计算约 222ns,远小于正常信号的过零沿宽度。PSC 保持 0,确保每个信号周期的计数值尽量大;即使测量 0.5Hz 超低频信号,32 位计数器约 60 秒才回绕,仍然不需要分频。
提示:PSC 只在定时器只有 16 位、且信号频率很低导致计数器反复溢出时才需要调整;32 位计数器方案直接保持 0。
中断服务程序里读取两个捕获寄存器并做差:
volatile uint32_t prev_ccr1, period_cnt, phase_delta; void TIM2_IRQHandler(void) { uint32_t ccr1 = TIM2->CCR1; uint32_t ccr2 = TIM2->CCR2; uint32_t sr = TIM2->SR; if (sr & TIM_SR_CC1IF) { // 基准信号上升沿 if (prev_ccr1) { period_cnt = ccr1 - prev_ccr1; // 一个完整周期占用计数 phase_delta = (int32_t)(ccr2 - ccr1); // 相对基准沿的时间差 } prev_ccr1 = ccr1; } TIM2->SR = 0; // 及时清标志 }这里利用的是 CH1、CH2 共享同一个计数器:CCR2 里存的是最近一次待测信号边沿的时刻,在基准沿到来时相减,就得到 Δt 对应的计数值。phase_delta 声明为 int32_t,因为待测信号可能比基准超前,此时 CCR2 比 CCR1 小,减出来是负数。如果两路信号频率不一致,period_cnt 会不断变化,软件里要做判断并提示频率超范围。
4.2 相位差换算:归一化与相位卷绕处理
拿到 period_cnt 和 phase_delta 后,换算公式为:
#include <math.h> float Phase_ToDegree(int32_t delta, uint32_t period) { float norm = (float)delta / (float)period; // 先归一化到周期比例 norm = norm - floorf(norm + 0.5f); // 映射到 [-0.5, 0.5) return norm * 360.0f; // 转成角度 }这里必须做归一化取模,不能直接乘 360。定时器自由运行时,delta 可能因为超前或计数器回绕而多出若干个完整周期;floorf 的作用是把整数周期部分剥掉,只保留一个周期内的相位差。对 51 单片机这类没有浮点单元的环境,可以改用整数取模:delta 对 period 取余,再线性映射到角度,效果一样且更快。显示端用正负号区分超前和滞后,0° 表示两路同相。
平均滤波放在换算之后比较合适。常见做法是连续取 16 个相位值,剔除一个最大值和一个最小值,再对剩余 14 个求平均,同时去掉过零抖动引起的尖刺和随机噪声。平均次数越多显示越稳定,但刷新越慢,一般刷新率做到 5 次/秒即可。
4.3 自动频率跟踪与软件架构
频率直接从 period_cnt 反推:f = 72MHz / period_cnt,不需要额外测频电路。量程切换建议在软件里设两个阈值,比如 period_cnt 小于 3600 提示高频超量程,大于 720 万提示低频超时,而不要频繁改写 PSC,因为改预分频会让当前测量周期的计数基准变动,产生毛刺数据。
软件架构拆成三个模块:capture 负责中断和时间戳,phase_calc 负责换算和平均,lcd_task 负责显示。主循环里用状态机依次执行“测量完成检查、相位计算、显示刷新”,显示刷新用标志位触发,不要在中断里直接操作 LCD,否则中断时间长会导致丢捕获。这套结构在论文里画成三层框图,比贴全部代码更有说服力。
5. 误差校准、测试记录与论文素材组织
5.1 误差来源与抑制措施
把误差分清楚,论文的测试部分就有了骨架。比较器传输延迟是固定偏差,量级在纳秒级,低频段折算到角度很小,用软件校准即可;过零抖动是随机误差,通过施密特滞回和中位平均压掉;定时器量化误差是系统误差,和计数频率负相关,PSC=0 时已经压到最小。
| 误差来源 | 典型量级 | 抑制办法 |
|---|---|---|
| 比较器传输延迟 | ns 级,固定偏差 | 软件零点校准 |
| 过零抖动 | 0.1°~1° 随机 | 滞回窗口 + 中位平均 |
| 定时器量化 | 0.005° @ 1kHz / 72MHz | PSC=0,用 32 位计数器 |
| 双通道不对称 | 随元器件而异 | 分压电阻选 1% 精度 |
5.2 标定步骤:用信号源建立入射-测量表
标定不需要精密相位基准,一台双通道信号发生器就够。把两个通道设为同频正弦波,先让两路同为 0°,记录显示值作为零点偏差;再依次设置 30°、60°、90°、180°,记录每个点的多次平均值。对设定值和实测值做线性拟合,得到 y = kx + b,把 k 和 b 存入 EEPROM。之后每次测量先做反变换,相位显示误差一般能压到 1° 以内。
不要只标一个频率。比较器延迟和运放相位偏移随频率变化,至少要取 100Hz、1kHz、10kHz 三个频率点分别标定,论文里把三个频率的 k 和 b 列成一张小表,比单纯写“误差小于 1°”更有说服力。
5.3 论文的测试表格应包含哪些列
测试记录表建议这样设计:设定相位、被测信号频率、输入幅值、显示相位 5 次、标准差、最大绝对误差。多次读数能体现随机波动,标准差说明稳定性,最大绝对误差对应系统误差。每个频率点的表格后补一段文字,选一个最大偏差解释来源,比如“1kHz 时最大偏差出现在 150°,主要由滞回窗口不对称导致”,这种写法比空泛的“结果满足要求”可信得多。
论文技术章节不要贴全部代码,流程图加一段关键输入捕获代码就足够。答辩要查的是实际测试记录和标定数据,这些原始素材一定要留档:用固定移相器复测 0°、90°、180° 三个点后,把屏幕照片和信号发生器设置界面一起存好,被问到误差来源时直接翻对应的记录页说“该点是 xx 误差主导”。
本文还有配套的精品资源,点击获取