简介:这份合集围绕单片机示波器与数字示波器电路设计,面向电子竞赛、毕业设计及嵌入式自学者,汇集从51、STM32到TMS320F28033、Arduino Pro mini等不同平台的完整方案。五套资料涵盖原理图、PCB、源程序、操作文档与初步指南,整体共66个文件,以h/c源码、jpg流程图、pdf说明文档、hex/bin固件、schdoc/pcbdoc工程文件为主,压缩包约112.94MB,便于按需查阅与二次开发。其中既有基于51单片机OLED显示的简易示波器,也有STM32数字示波器、20MHz手持式双踪袖珍示波器,还包含数字存储示波器制作与Arduino Pro mini示波器的手把手教程,覆盖从入门到进阶的典型路径。已有1066人浏览学习,适合需要快速搭建示波器项目、理解采样显示与信号调理电路设计的读者,可直接参考或复现各套方案。
1. 单片机示波器不是玩具:采样率、带宽与存储深度先算清楚
用单片机做简易示波器,大多数人的第一反应是“选个高分辨率的ADC”,但实际决定成败的从来不是位数,而是实时采样率和前端模拟带宽。比如一个1MHz的正弦波,用STM32内置ADC以1Msps采样,理论上每个周期只采到一个点,波形重建出来全是锯齿;如果再用普通运放做前端,不加带宽限制,高频噪声混叠进来,屏幕上的波形更是无法直视。数字示波器这四个字里,“数字”的含义是先采样、后重建,采样率决定能看多快的信号,存储深度决定一次能抓多长的波形,而这两项指标恰恰是单片机方案里最容易缩水的。这套“五套资料”无论哪一份,拿到手先别急着看PCB,应该先找它的采样时钟频率和前端放大器的-3dB带宽,再决定它适不适合你手上的待测信号。无论是做电源纹波测量、串口波形调试,还是低速传感器信号观察,先把这个账算清楚,后面才不会做完一套板子才发现什么都测不了。
2. 信号链设计:前端调理电路和ADC选型为什么决定示波器成败
2.1 前端输入级的三件事:衰减、跟随、偏置
单片机内置ADC的输入范围通常只有0~3.3V或者0~5V,而实际测量中遇到的双极性信号、高压信号远比这个范围宽。所以一个能用的单片机示波器,输入端必须依次完成三件事:衰减、跟随、偏置。衰减电路把±10V、±50V这类信号按比例缩小到ADC安全范围内;跟随器提供高输入阻抗,避免被测电路被示波器拉偏;偏置电路负责把衰减后的双极性信号整体平移,让它的中点正好落在ADC满量程的一半上。
常见的衰减电阻网络一般做三档切换:1:1、1:10、1:100,用继电器或模拟开关切换。电阻的精度直接影响幅度读数,至少要选0.5%误差的金属膜电阻,而且输入阻抗要设计在1MΩ左右,这样配合10x无源探头时,分压比才能与探头兼容。很多资料里的原理图只画了简单的分压加一个104电容,这种做法看低频方波还行,一旦信号频率超过几十kHz,输入电容和电阻构成的低通效应会把波形边沿拖圆,测出来的上升时间根本不是信号真实的上升时间。
跟随器之后还要有一个偏置加法器。以STM32F103为例,ADC参考电压是3.3V,若要显示-1.65V到+1.65V的信号,就必须把信号叠加一个1.65V的直流偏置。这个偏置电压如果用LDO输出直接分压,纹波和温度漂移都会被当成信号送进ADC,导致基线上下晃动。我一般会用REF3312这样的低噪声基准源,再经过一级运放缓冲后送入加法器。你在看资料里的原理图时,如果发现偏置电压只是从电源用两个电阻分压来的,那这套方案做出来大概只能看低频信号,幅度稍微小一点就会淹没在噪声里。
2.2 ADC驱动与采样保持:低阻抗源是关键
单片机内置ADC大多采用逐次逼近型结构,内部有一个采样保持电容,大小通常在几pF到十几pF。每次采样开始时,这个电容需要从外部信号源抽取电荷,如果信号源输出阻抗太高,采样瞬间电容上的电压跟不上外部信号,结果就是采样值偏低,波形出现非线性失真。ST官方手册里会给出一个推荐的最大外部阻抗和采样时间,但那是针对缓慢信号做的假设;在示波器场景里,采样时间往往被定时器压缩,这时就要靠一级ADC驱动运放去压制输出阻抗。
驱动运放应该放在抗混叠滤波器之后、ADC引脚之前,把信号源阻抗降到几十欧姆以下。它的带宽至少是目标信号最高频率的五倍,压摆率也要够,否则会在大摆幅信号边沿出现转换速率限制,方波变成梯形波。接下来是抗混叠滤波器,常见的一阶RC低通截止频率应设置在采样率的二分之一以内,工程上我会取采样率的1/5到1/2.5之间。例如采样率1Msps,低通截止频率取200kHz~400kHz。如果资料里的RC值随手写的,没有和采样率挂钩,那么高频信号折叠回来是必然的。
2.3 五套资料里的ADC选型对比:MCU内置还是外置
“五套资料”这个说法意味着你手上有一批不同方案的参考设计。从我接触过的单片机示波器资料看,核心区别通常集中在ADC上:有的直接用MCU内置12位ADC,有的用外置串行ADC,还有的用并行高速ADC,甚至有用ICL7106这类双积分ADC的。不同ADC决定了整套系统的带宽上限和程序复杂度,拿到资料后先做下面这个表格里的判断:
| 方案 | 典型采样率 | 有效位ENOB | 可测信号带宽 | 适合场景 |
|---|---|---|---|---|
| STM32内置ADC | 1~2Msps | 10~11bit | 约几十到两百kHz | 音频、PWM占空比、串口波形 |
| ADS8320外置串行ADC | 6.25Msps | 11bit | 1MHz以内 | 电机驱动电流、DCDC开关纹波 |
| AD9288并行ADC | 65Msps | 7~8bit | 20MHz以内 | 高频时钟、RF包络、电源瞬态 |
| ICL7106双积分ADC | 每秒几次 | 12bit | 极低 | 只能测直流电压,不适合示波器 |
注意表格里的“可测信号带宽”不是采样率的一半,而是考虑前端运放和抗混叠滤波器之后的实际可用上限。比如AD9288标称65Msps,但配套的运放只有30MHz带宽,那你实际能准确测量的信号只能到10MHz左右。还有一点:MCU内置ADC虽然方便,但它的采样时序受固件中断影响很大,除非用定时器触发+DMA搬运,否则数据不连续。资料里但凡声称“数字示波器”的,多半会走外置ADC加CPLD或FIFO的路线,因为只有独立硬件采样控制才能保证等间隔采样,MCU只负责读数和显示。
2.4 触发电路:简单示波器最容易被忽略
很多自制简易示波器功能上“只有波形没有稳定”,问题出在触发上。数字示波器显示时是一屏一屏地把采样点画出来,如果每一屏的起点不同,同一个周期性信号在屏幕上就会左右乱跑。最简单的软件触发是在MCU里实时比较相邻采样值,检测信号跨过预设阈值的那一瞬间,将其作为这一屏的起点。这种方案省硬件,但存在一个天然缺陷:采样是离散的,信号真实跨过阈值的时刻可能落在任意两个采样点之间,触发点的误差最大可达一个采样周期,在高扫描速度下波形依然会抖动。
如果想得到更稳定的显示,就用硬件比较器,例如LMV331把输入信号和一个由DAC产生或电位器调节的阈值电压比较,输出一个数字边沿给MCU的外部中断引脚。中断里做环形缓冲的指针重定位,能保证每次显示都从边沿处开始取数。源程序里如果用了环形缓冲,还需要特别注意“触发前数据”的处理。示波器观察波形时,往往希望看到触发前发生了什么,比如一个毛刺的前因,这要求缓冲区里Trigger Point之前保留一段数据。资料里的代码若没有这段逻辑,那它只能显示触发后的波形,排查问题时会非常别扭。
3. 原理图到PCB:布局布线决定你的示波器能不能稳定运行
3.1 模拟地与数字地的分割策略
单片机示波器是典型的数模混合系统:模拟前端处理小信号,MCU同时跑着ADC、DMA、显示和按键扫描。数字电路翻转瞬间会在电源和地平面产生很大的电流尖峰,如果模拟前端的地和数字地完全混在一起,这些尖峰就会变成示波器屏幕上的毛刺。PCB设计的第一步就是规划好地平面。
常见做法是整块地不切割,只让模拟电路集中放在一角,数字电路放另一角,ADC芯片作为桥接点。ADC的AGND和DGND在芯片内部是连在一起的,PCB上就不需要再单独分割地和数字地,否则会人为形成地环路。我之前见过一份资料,把模拟地划出来一块,只用一根细线连回数字地,测出来的波形几乎没有高频信号,原因就是细线电感在高频下形成了巨大阻抗。更合理的做法是在ADC下方做局部铺铜挖空,切断数字高速走线在模拟区下方通过的路径,让模拟参考地保持干净。如果你用AD20,可以通过“铺铜挖空”功能在模拟区域挖掉一部分地铜皮,制造一个隔离带,只保留前端信号走线和地回流孔。
3.2 基准电压和电源去耦的PCB落地
ADC基准电压是示波器精度的另一个关键点。如果直接用3.3V电源作为VREF,那么电源纹波有多大,ADC读数的误差就有多大。看过几套自制示波器资料,高端一点的设计会用TL431做基准,更低噪声的用REF3125,这样VREF误差可以控制在10mV以内。PCB布局时,基准芯片的输出要短距离直接连到ADC的VREF引脚,中间不要穿过任何数字电路区域,也不要和MCU的IO线并行走线。
电源去耦不是单纯每个芯片放一个104就完事。模拟运放电源引脚和数字MCU电源引脚要有不同的处理。运放建议在电源引脚处放100nF陶瓷电容,另外在电路板电源入口放一个10μF钽电容或者陶瓷电容,用于低频去耦。关键模拟走线要短,尤其是从偏置基准到加法器的走线,如果拖得很长,又经过数字芯片下方,就很容易被干扰。我在做这类板子时,还会给模拟电源单独加一个小LDO,比如从5V先到3.3V数字电源,再从数字电源经过一级LDO得到3.0V模拟电源,两级之间磁珠隔离,这样MCU翻转带来的噪声几乎传不进模拟前端。
3.3 从资料包读原理图和PCB的检查顺序
拿到一套资料,千万不要直接拿去打样。我一般按下面几个顺序快速过一遍,判断这套资料“能不能用”:
第一步找信号链路。从输入BNC开始,沿着走线看:输入保护电路→衰减网络→跟随器→偏置加法器→抗混叠滤波→ADC驱动→ADC→MCU→显示。如果链路上连一个输入保护二极管都没有,那么静电或者过压会直接打坏运放,这种资料只能做实验室桌面玩一玩。
第二步看PCB叠层。两层板也可以用,但对模拟前端来说,完整的地平面非常重要。我会检查第二层是否大面积铺铜,如果第二层被走线切得支离破碎,那地回流路径就会乱。四层板通常第一层信号、第二层地、第三层电源、第四层信号,这种结构更适合高频示波器。
第三步查采样时钟。ADC的采样时钟如果直接来自MCU的定时器输出,要确认是否有分频抖动。专业的示波器会单独用有源晶振给ADC提供采样时钟,因为MCU主时钟在内部经过锁相环和分频后,抖动会直接影响采样时刻的等间隔性,反映在屏幕上就是波形噪声。
第四步看DRC规则。在AD20里导入PCB后,自己跑一遍DRC:最小线宽按板厂能力设置,比如0.2mm;最小间距0.25mm;孔到孔距离至少0.3mm。重点检查模拟地和数字地之间有没有意外短接,以及ADC的模拟输入线有没有和高速数字线长距离平行。资料里如果源PCB的DRC结果全是绿色警告,那板子大概率是能工作,但可靠性要打个问号。
4. 源程序与操作文档:让示波器面板上的波形动起来
4.1 基于STM32的ADC+DMA采集最小代码
无论资料里的源程序写得有多花哨,最核心的采样部分基本绕不开ADC加DMA。下面这段是STM32F103上连续采集512个采样点的最小骨架,很多资料里的代码比这个复杂,但逻辑主干一样:
// ADC1 采样时间设为最长,打开扫描模式,DMA循环搬运 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, 512); void MX_DMA_Init(void) { __HAL_RCC_DMA1_CLK_ENABLE(); DMA_InitTypeDef dma; dma.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; dma.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; dma.Mode = DMA_CIRCULAR; // 循环模式,连续采样不中断 dma.Direction = DMA_PERIPH_TO_MEMORY; dma.PeriphInc = DMA_PINC_DISABLE; dma.MemInc = DMA_MINC_ENABLE; // 内存地址递增,依次填充数组 HAL_DMA_Init(&hdma_adc1); __HAL_LINKDMA(adc, DMA_Handle, hdma_adc1); }这段代码里最关键的是DMA_CIRCULAR循环模式。如果把它设置成普通模式,DMA在搬完512个点后就会停下来,你要自己再手动启动,而重新启动的间隔会导致丢失大量波形,屏幕上看到的信号就是断续的。循环模式让DMA在搬运完最后一个点后又自动回到缓冲区开头继续覆盖,相当于一个环形缓冲,配合软件触发可以做到无死区连续采样。另一个细节是半字对齐,STM32F103的ADC结果是12位,刚好放在16位半字里,如果按字节对齐,高低字节会错乱,显示的波形就会在满幅范围内乱跳。
4.2 采样率、时基和显示刷新的参数配合
源程序里如果没有自适应时基,波形显示出来不会符合预期。采样率由定时器触发ADC决定,例如定时器72MHz预分频72,计数周期1,就产生1MHz触发频率。但ADC每次转换也需要时间,F103的典型转换周期是12.5个ADC时钟加采样时间,如果ADC时钟为12MHz,最短转换时间大约是1μs,也就是说1Msps已经接近这个芯片的上限了。资料里若把采样率写到了2Msps,你要检查它的ADC时钟分频和采样时间,很可能实际有效采样率达不到宣称值。
显示刷新也要配套处理。如果ADC缓冲是512点,屏幕宽度128像素,就有两种常见做法:一是每4个采样点选1个显示,这叫抽取;二是每4个点取最大值和最小值,画成一条竖线,这叫峰值检测。峰值检测对观察毛刺特别有效,因为抽查很容易把窄脉冲漏掉。源程序里如果有find_peak或类似的函数,查看它是否对每个数据块同时维护最大值和最小值,而不是只取一个点,否则你看到的波峰幅度会比实际低很多。操作文档里如果只描述了“显示波形”,你可以自己在示波器上输入一个窄脉冲验证一下显示效果。
4.3 校准参数的存储与操作文档里的自检步骤
自制示波器的最大误差来源不是ADC位数,而是前端电阻精度、偏置电压误差和零点漂移。资料里真正的“操作文档”部分,至少要写清楚两件事:如何校准零点和如何校准增益。我在固件里通常会预留这样两个校准变量:
float zero_offset = 1650.0f; // 输入短路时ADC码值,对应1.65V偏置 float gain_scale = 1.0f; // 增益校准系数,用已知直流电压标定 // 电压换算 float voltage = (adc_code - zero_offset) * (3.3f / 4096.0f) * gain_scale;zero_offset对应的是前端偏置电压在ADC里的读数,正常情况下应为满量程的一半,也就是2048左右,但会因偏置基准误差和运放失调而变化。可以写一个短接输入校准模式,把ADC平均值存到Flash里。gain_scale则通过输入一个已知幅值的正弦波或直流电压来修正,例如输入2.50V标准电压,如果显示2.43V,那增益系数就是2.50/2.43。这两个参数一个管位置一个管幅度,整个测量系统的精度基本都压在它们身上。操作文档里如果连这两段校准流程都没有,那这套资料做出来的东西只能看波形形状,不能信幅度。
5. 进阶技巧:用单片机示波器量真实信号时避开五个坑
用自制示波器去测真实电路,往往比看着资料里的示例波形要复杂得多。这里有五个我经常遇到的坑,每条都能对应到实际示波器操作中。
第一个坑是拿测直流电源的示波器去看方波边沿。前端运放带宽不够时,方波会显示成圆角,上升时间被拉长。测量方波边沿的估算公式是0.35除以实测上升时间,如果显示上升时间在100ns,那说明示波器前端带宽只有3.5MHz,远不够看几十MHz的信号。要验证前端带宽,用板载方波发生器或信号源输出一个已知上升时间1ns的方波,看显示出来的边沿有没有明显变缓。
第二个坑是混叠。当信号频率接近采样率的一半时,屏幕上会出现一个低频幻影,这不是真实信号。比如用1Msps采样800kHz正弦波,显示出来可能是200kHz的缓慢波动。简单判断方法是改变采样率,如果波形的频率跟着采样率一起变,那基本就是混叠。数据资料若没有抗混叠滤波器,就尽量把被测信号限制在采样率的1/5以内。
第三个坑是探头没校准。很多单片机示波器带BNC接口,配10x无源探头,探头上有个电容微调旋钮。如果不把探头接到1kHz方波上看边沿是否平直,就会出现过冲或圆角。我一般用MCU的PWM引脚输出1kHz方波做探头校准输出,但由于MCU引脚带载能力弱,要先经过一级缓冲,否则调整出的补偿电容在接上真实信号后又会偏。
第四个坑是底噪太大。测量几十毫伏的小信号时,示波器自身噪声可能比信号还大。开启多次平均可以降低随机噪声,比如64次平均能把噪声降低大约8倍,但同时也会把随机毛刺平均掉。如果你要观察DCDC开关噪声这种有规律的高频毛刺,就不适合开平均,应该改用峰值检测方式,把毛刺的最大值保留下来。
第五个坑是触发不稳。软件触发时,如果阈值设在信号中部较平坦的位置,检测到的触发点会抖个不停。正确做法是把触发电平设在信号上升沿或下降沿的中间段,越陡峭的边沿触发越稳定。对于串口这类异步信号,比如Modbus帧,最好使用硬件比较器边沿触发,然后在触发中断里启动DMA采样,这样能稳定抓到帧起始位和后面的字节波形,用来分析波特率误差和信号质量非常直观。
最后一个顺手就能用的小技巧:用MCU的DAC输出一个已知频率的方法来验证示波器通道。很多单片机内部自带DAC,如果没有,就用PWM加RC滤波生成1kHz正弦波,接到示波器输入口。如果屏幕上显示的频率比DAC设定的频率高一倍,那很可能是采样或显示时发生了奇偶抽取错误。这个自查办法不占额外硬件,比写一百行测试代码都管用。
本文还有配套的精品资源,点击获取