ARTICLE DETAIL

资讯详情

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

基于CH32V307的开源示波器设计:从ADC采样到波形显示的完整实现路径

基于CH32V307的开源示波器设计:从ADC采样到波形显示的完整实现路径 如果你一直在关注 RISC-V 单片机大概会注意到一个现象凡是带高速 USB、以太网、大容量 SRAM 的国产 RISC-V 芯片迟早会被玩家拿去做“开源示波器”这一类的测量仪器项目。原因并不复杂——示波器的本质是 ADC 采集、数据搬运、显示刷新而这三件事恰好能压榨出一颗 MCU 的极限性能。CH32V307 就是这类芯片里能见度很高的一颗144MHz 主频、内置 FPU、官方标称 4Msps 的 12 位 ADC、USB 2.0 高速接口。单看这几个参数它已经具备了一个入门级数字示波器的核心条件。很多人会问现在几十块钱就能买到一台二手虚拟示波器自己用 MCU 做一台到底有什么意义我的判断是开源示波器项目的价值从来不在“省钱”而在于它把采样率、触发、时基、信号调理、显示同步这一整套测量链路完整暴露在你面前。做完这个项目你获得的不仅是一块能看波形的板子更是对 ADC 时序、DMA 搬运、中断优先级和信号完整性最直观的理解。这篇文章会从芯片选型、系统架构、硬件前端、代码框架到验证方法完整梳理一台 CH32V307 开源示波器的实现路径。1. 为什么有人坚持在 RISC-V 单片机上做开源示波器先解决一个认知问题示波器的核心是高速 ADC 和模拟前端MCU 只是外围控制为什么非要选 CH32V307传统教学用的 STM32F103 也能做“简易示波器”但绝大多数作品停留在 1Msps 以内屏幕刷新率低触发功能弱本质上是一个“数据采集器加波形显示”离示波器的使用体验还很远。CH32V307 的出现改变了这个平衡点它同时具备更高的主频、带 FPU 的 RISC-V 核心、以及官方 ADC 性能标称 4Msps这套组合让单片机上做出“可用级示波器”成为可能。另一个原因在生态层面。CH32V307 的官方评估板价格不高板载 WCH-Link 调试器拿到手就能用 MounRiver Studio 打开工程不需要昂贵的第三方调试器。对于高校实验室、电子爱好者、嵌入式初学者来说这是一个试错成本很低的平台。更重要的是这个项目有着天然的“可复现性”和“可扩展性”。你可以在社区找到多种基于 CH32V307 的开源示波器方案有的把波形显示在 1.8 寸 TFT 彩屏上有的用 USB 把数据传给 PC 上位机有的用 OLED 做成便携笔式示波器。不同方案取舍不同但底层代码高度相似ADC 连续采样、DMA 环形缓冲、软件触发、数据标定。你只要吃透这一层就可以把同一套逻辑搬到其他芯片上这种“测量思维”的迁移价值非常大。当然也必须承认局限4Msps 采样率决定它能轻松观察音频信号、PWM 波形、串口通信波形但无法直接测量高频射频信号。它不是替代专业示波器的工具而是一台适合学习和日常调试低速数字电路的仪器。这个定位想清楚后项目的技术方向和成本控制都会清晰很多。2. CH32V307 的硬件能力与选型边界2.1 核心参数与测量能力的关系CH32V307 采用沁恒自研的青稞 V4F 内核最高主频 144MHz带单精度浮点运算单元。这些参数对于示波器意味着什么先看 ADC。按官方数据手册其 12 位 ADC 最高采样率可达 4Msps即每秒 400 万次采样。根据奈奎斯特采样定律理论最高可观测信号频率约为 2MHz但实际工程中一般按信号频率的 5 到 10 倍采样所以它能可靠观察的信号带宽大约在几百 kHz 以内。这个带宽覆盖了音频、电机驱动 PWM、UART/I2C/SPI 通信、电源纹波分析等大量嵌入式调试场景。其次是存储。CH32V307 最大支持 192KB SRAM这决定了 ADC 的 DMA 缓冲区能开多大。比如要存储 8192 个采样点每个点 2 字节在内存中占 16KB这对多数 MCU 来说已经有些紧张但对 CH32V307 来说只是内存的一小部分。更大的缓冲区意味着你能在一次触发后拿到更长的波形记录方便观察信号细节。然后是接口。CH32V307 内置 USB 2.0 高速 OTG理论速率 480Mbps这让“MCU 持续把波形数据传给 PC 上位机”成为可能。如果只有串口921600 波特率传输一屏 4096 点也需要数秒根本谈不上实时交互。USB 高速接口是它区别于普通低端 MCU 的重要分水岭。2.2 与其他芯片的简单对比芯片内核主频高速USB标称ADC采样率典型示波器定位STM32F10372MHz无约1Msps教学实验级采集器STM32F407168MHz有约2.4Msps中端DIY示波器RP2040133MHz无约0.5Msps(常规)逻辑分析仪方向更合适CH32V307144MHz有最高4Msps入门级开源示波器这里需要强调芯片选型不能只看峰值参数。ADC 实际采样率与时钟树配置、采样保持时间、DMA 带宽、代码中断开销都有关系。在看任何开源项目前先翻开数据手册的 ADC 章节确认你使用的 ADC 时钟源是否足够这是避免后面被“采样率虚标”坑的关键。3. 一套开源示波器的总体架构与核心概念示波器看起来是一个独立仪器实际上可以拆成四个子系统信号输入前端、ADC 采样与触发、数据存储与处理、显示与人机交互。信号输入前端负责把外部电压调整到 ADC 可接受的范围内。MCU 的 ADC 输入一般是 0 到 3.3V而你要测量的信号可能是正负 5V、正负 12V所以必须通过电阻分压、运放跟随或衰减电路做电平变换。这一级设计不好后面芯片能力再强也无法得到准确波形。ADC 采样与触发是示波器的灵魂。所谓触发就是让波形稳定显示的关键机制。如果没有触发每个采样周期开始的时间点不一样屏幕上看到的波形就会左右乱跑。最简单的触发是“上升沿过阈值触发”当采样值从低于某一电压变成高于该电压时认为捕捉到一个信号边沿从这一时刻开始记录后续波形。ADC 采集完成后数据先进入 DMA不断在内存中形成一个环形缓冲。主循环或中断负责判断触发条件一旦满足就把缓冲区内的一段有效波形交给显示任务。这类分段式处理比“采集一点显示一点”更稳定也是示波器能保持高刷新率的原因。理解这个架构后你会发现开源示波器的代码并不神秘它没有用到复杂的数学库核心逻辑就是“持续采集 找触发点 截取波形 显示”。真正区分项目水平的是各模块之间的时序配合和异常处理。例如DMA 缓冲区被写满后何时取走数据触发条件在数据已经越过边界时如何处理显示刷新时是否会造成图像撕裂4. 最容易被低估的环节前端信号调理与输入保护4.1 为什么不能把信号直接接到 ADC 引脚我在不少初学者项目里看到过这种接法用杜邦线把待测信号直接连到 MCU 的 ADC 引脚如果信号电压不超过 3.3V确实能出波形但这样做存在两个隐患。第一输入阻抗不匹配外部信号源会被 MCU 引脚的低输入阻抗拉偏导致测量结果失真第二一旦接错线或误测高压MCU 当场烧毁。示波器前端需要解决三件事阻抗匹配、电压档位切换、过压保护。专业示波器输入端通常有 1MΩ 输入阻抗需并联约 10-20pF 电容来补偿。开源项目中常见做法是用两个电阻做分压并接一个小电容进行高频补偿再用运放做电压跟随器隔离后送入 ADC。特别要提醒的是输入保护建议使用双向 TVS 管或二极管钳位电路把输入电压限制在 0 到 3.3V 之间。若没有保护电路后续的调试失误代价会很高。4.2 一个可用的前端结构以下是一个适合 DIY 的前端链路适合正负 5V 到正负 50V 范围内的信号测量需配合衰减比使用输入端子 - 电阻分压衰减网络 - 电压跟随器 - 二极管钳位 - ADC 引脚考虑到实际运放功耗和电压范围建议使用单电源 3.3V 供电的轨到轨运放例如常见的 LMV358、MCP6002 等。输入信号经分压后正负电压不能直接送入单电源运放通常还要叠加一个 1.65V 的直流偏置让信号中心落在 ADC 量程中点。这样处理后ADC 采样值减去偏置对应的数字量再乘以电压缩放系数就能还原出真实电压。这里的设计细节较多建议画一张小电路图先做仿真再结合实际测量修正。如果没有把握可以先做一版“只测正电压、不测负电压”的简易通道把项目跑通后再完善负电压处理和量程切换。模块化迭代比一步到位更稳妥。4.3 安全边界提醒任何示波器项目都应当遵守一条底线不要直接测量市电或高压电路。DIY 示波器缺少隔离电源和安全外壳一旦直接接触高压不仅会损坏设备还可能威胁人身安全。测量对象请限制在电子产品实验板、低压电源、隔离后的信号源等安全范围内。这一点无论项目多复杂都不应该妥协。5. 开发环境准备与工程搭建5.1 需要的硬件笔者建议采用官方 CH32V307 评估板或基于 CH32V307VCT6 的核心板作为起点。之所以不建议一开始就自己画板是因为示波器对模拟前端布局有要求初次做项目时应优先把固件和算法跑通再考虑 PCB 设计。硬件清单大致如下CH32V307 开发板带 WCH-Link 调试器更佳一块带 SPI 或并口接口的 TFT 彩屏建议 2.0 寸到 3.5 寸之间若干电阻、电容、运放用于搭建前端调理电路信号发生器或用另一块开发板产生的 PWM 信号杜邦线、面包板、精密可调电源如果开发板上没有屏幕接口可以用 USB 先实现“PC 端上位机显示”这样也能完成波形展示。5.2 软件工具链CH32V307 官方推荐的 IDE 是 MounRiver Studio它自带编译工具链和烧录插件可以直接编译和下载官方 EVT 例程。MounRiver Studio 基于 Eclipse 框架用起来和常见嵌入式 IDE 差别不大。安装完成后建议先在官方 EVT 压缩包中找到 “ADC” 或 “TIM” 相关例程验证开发板能正常编译、下载、运行。这一步虽然简单但能尽早暴露驱动安装和调试器兼容问题。此时最容易遇到的问题有三个开发板无法被识别、下载时提示找不到 WCH-Link、工程路径中文导致编译错误。前两个问题一般通过重装驱动和检查 USB 线解决第三个问题把工程放到纯英文目录即可。5.3 建立一个最小工程官方 EVT 工程结构通常是“每个外设一个独立工程”。建议新建一个自己的示波器工程把 ADC、DMA、GPIO、SPI/TFT 等外设驱动放在不同源文件里。目录结构可以参考这样组织scope_demo/ ├── User/ │ ├── main.c │ ├── ch32v30x_it.c │ └── scope_core.c ├── Periph/ │ ├── adc_dma.c │ ├── trigger.c │ └── tft_display.c ├── Debug/ └── README.md保持目录清晰的好处是当你后续增加串口调试、USB 上传或按键交互功能时不需要重构整个工程。6. 核心采集代码ADC DMA 触发逻辑这一部分是整个示波器的核心。下面代码基于 CH32V307 EVT 的标准外设库风格编写具体 API 名称请以你下载的 SDK 实际版本为准。6.1 初始化 ADC 与 DMA 连续采集主程序中首先要配置 ADC1 从某个通道采集通过 DMA 把结果循环搬运到一个缓冲区。/* 文件adc_dma.c示意代码请按实际 EVT 工程适配 */ #include ch32v30x.h #define ADC_WAVE_BUF_SIZE 4096 static __attribute__((aligned(4))) uint16_t aADCValue[ADC_WAVE_BUF_SIZE]; void ADC1_DMA_Init(void) { GPIO_InitTypeDef GPIO_InitStructure {0}; ADC_InitTypeDef ADC_InitStructure {0}; DMA_InitTypeDef DMA_InitStructure {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)((ADC1-RDATAR)); DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)aADCValue; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize ADC_WAVE_BUF_SIZE; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel1, DMA_InitStructure); ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; ADC_InitStructure.ADC_ContinuousConvMode DISABLE; ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }这段代码的关键点有三个DMA 工作在循环模式采集数据会自动回绕填充程序中无需频繁处理中断。ADC 校准必须在使能 ADC 并启用 DMA 之前完成。ADC_SampleTime_239Cycles5是较长的采样时间适合先验证功能提高采样率时可换成更短的采样时间配置但精度也会随之下降。启动 DMA 后aADCValue数组中的元素会被不断更新。如果只需要看实时波形直接在主循环中滚动读取数组即可如果希望触发稳定则需要再增加触发判断。6.2 上升沿与下降沿触发逻辑触发判断可以放在主循环外部函数中也可以在一轮 DMA 缓冲更新后调用。下面的示意代码在满缓冲区中搜索第一个越过阈值的点并将该点作为显示起始索引。/* 文件trigger.c触发逻辑示意 */ #include trigger.h static uint32_t startIndex 0; void Wave_TriggerProcess(const uint16_t *buf, uint32_t len, uint16_t level, uint8_t edgeMode) { uint32_t i; uint16_t pre buf[0]; uint16_t cur; /* 简单软件搜索触发点实际项目可针对包络做多点过滤 */ for (i 1; i len; i) { cur buf[i]; if (edgeMode TRIGGER_MODE_RISING) { if (pre level cur level) { startIndex i; break; } } else if (edgeMode TRIGGER_MODE_FALLING) { if (pre level cur level) { startIndex i; break; } } pre cur; } } uint32_t Wave_GetStartIndex(void) { return startIndex; }实际应用中建议对 ADC 采样值做一个简单的滑动滤波再判断边沿否则噪声较大时触发点会抖动。更高级的做法是使用硬件比较器或定时器 PWM 触发但那需要引入额外外设资源初期版本不必追求。6.3 波形显示映射当触发点确定后就把缓冲区中的数据映射到屏幕坐标。常见 LCD 分辨率是 320×240横向 320 个像素不可能显示 4096 个采样点因此需要按比例抽取或做最大值最小值包络显示。下面这个代码实现了“每列取一个对应采样点”的画点方式适合验证链路。/* 文件scope_render.c显示映射示意 */ #include tft_display.h #define SCREEN_W 320 #define SCREEN_H 240 #define BASE_Y 120 #define VOLT_SCALE 64 void Scope_DrawWaveform(const uint16_t *buf, uint32_t totalLen, uint32_t startIndex, uint16_t level) { int x, y; uint32_t idx; TFT_ClearScreen(); /* 清屏实际项目中可只清波形区域 */ for (x 0; x SCREEN_W; x) { idx (startIndex (uint32_t)x * (totalLen / SCREEN_W)) % totalLen; y BASE_Y - (int)((int32_t)buf[idx] - (int32_t)level) / (4096 / SCREEN_H); if (y 0) { y 0; } else if (y SCREEN_H) { y SCREEN_H - 1; } TFT_DrawPoint(x, y, COLOR_WAVE); } }这里的映射做了简单的裁剪避免数据越界导致显示花屏。实际显示中还可以叠加坐标网格、触发电平线、电压刻度等信息但由于不同 LCD 驱动差异较大建议先从“画点出波形”这一步开始验证通过后再完善 UI。6.4 主循环流程void main(void) { uint16_t currentStart 0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); SystemCoreClockUpdate(); Delay_Init(); TFT_Init(); ADC1_DMA_Init(); while (1) { Wave_TriggerProcess(aADCValue, ADC_WAVE_BUF_SIZE, 2048, TRIGGER_MODE_RISING); currentStart Wave_GetStartIndex(); Scope_DrawWaveform(aADCValue, ADC_WAVE_BUF_SIZE, currentStart, 2048); Delay_Ms(10); } }主循环采用了一种最简单的实现反复在缓冲区中找触发找到后绘制整屏波形。20 毫秒更新一次感官上是连贯的。当工程跑通后可以采用更高效的结构在 DMA 传输完成中断里设置标志位主循环只在标志位置位时才触发绘制避免每轮都全部扫描一遍缓冲区。7. 显示与上位机方案从屏幕到 PC 端7.1 屏幕直驱方案CH32V307 的 GPIO 速度足够驱动常见的 SPI 屏幕。点亮一块 SPI TFT 屏幕的核心步骤是初始化 LCD 控制器寄存器、设置显示窗口、按像素写入颜色数据。这个驱动流程比较固定关键是移植厂商提供的屏幕驱动时注意时序延时。SPI 屏幕的数据线 MOSI、时钟线 SCK、片选 CS 分别接到 MCU 的 GPIO如果屏幕带触摸功能还要额外处理触摸面板的中断和 I2C/SPI 接口。在示波器显示中屏幕刷新率直接影响使用体验。如果每帧都清空全屏再画线会产生闪烁。建议维护一个 320×240 的显存数组先把波形画进显存再一次写入屏幕。这样能明显改善显示流畅度。7.2 USB 虚拟串口上传到 PC对于不想接屏幕的用户另一种方案是让 CH32V307 通过 USB 高速接口枚举为一个虚拟串口把 ADC 数据发送到 PC 上位机。这个方案的优点是 PC 可以保存波形、自动计算幅值频率后续扩展空间更大。PC 端可以先用 Python 写一个最小接收程序验证数据是否能正确到达。# host_scope.py —— 极简串口波形接收示例 import serial import matplotlib.pyplot as plt # 根据实际设备修改串口号和波特率 ser serial.Serial(COM3, 2000000, timeout1) raw_values [] print(等待 CH32V307 数据按 CtrlC 停止) try: while len(raw_values) 1024: line ser.readline() if line: try: value int(line.strip()) raw_values.append(value) except ValueError: pass except KeyboardInterrupt: print(退出接收) finally: ser.close() if raw_values: plt.plot(raw_values) plt.title(CH32V307 Open Source Scope) plt.xlabel(Sample Index) plt.ylabel(AD Value) plt.show()这种方式只适合验证链路不适合高带宽实时显示。要实现流畅的 PC 波形建议自行设计简单的二进制帧协议每帧带同步头、数据类型和校验位把 2 字节 ADC 数据连续上传上位机再解析成波形数据效率会远高于文本行格式。8. 运行验证与常见问题排查8.1 如何确认系统正常工作工程烧录后不要马上追求复杂波形。按下面顺序逐步验证先给 ADC 输入一个稳定电压比如从开发板的 3.3V 经电阻分压得到 1.65V观察屏幕显示是否是一条水平直线。这条直线对应的 ADC 值应在 2048 左右偏差不能太大。若水平线正确说明 ADC、DMA、LCD 链路已经打通。然后在输入端接入一个低频方波信号例如由另一块开发板产生的 1kHz PWM先通过电阻分压把幅值降到 3.3V 以内。如果触发逻辑正确屏幕波形会稳定在一个位置不再左右漂移。此时再提高信号频率测试找出波形开始失真的边界。最后用正弦波信号源或手机耳机孔输出正弦波检查屏上显示的正弦波是否平滑。这一步能验证采样点数是否足够以及触发电平是否合适。8.2 常见问题排查表问题现象可能原因排查方式解决方案ADC 值恒定不变DMA 未启动或输入引脚悬空检查 DMA_Cmd 是否执行给 ADC 输入明确电压检查引脚复用配置波形是一条直线且数值接近 4095输入电压超出量程或引脚悬空用万用表测量输入电压确认前端分压和钳位电路正常波形显示乱跳无法稳定触发阈值或边沿模式不对打印缓冲区前 100 个值调整触发阈值或降低采样率屏幕刷新闪烁没有用显存连续刷屏观察刷新过程改用帧缓冲后再整屏更新采样率明显偏低ADC 采样时间配置过长抓取一段正弦波数周期缩短 ADC_SampleTime检查时钟源下载程序失败驱动未装或调试器损坏查看设备管理器重装 WCH 驱动换 USB 口8.3 从现象定位问题的原则排查示波器问题时最忌讳同时修改多处代码。建议采用“信号注入法”从一级一级链路去推先用固定电压验证 ADC 数值再用低频规则信号验证触发最后引入不规则信号观察误差。每换一个信号源只观察一个变量问题很快就会精确到某一层。9. 工程化建议与进阶路线9.1 代码层面的工程建议示波器固件中采样代码和 UI 代码应当严格分层。采集部分尽量不要加入耗时的浮点运算或 LCD 操作否则会拖慢采样时序。可以在 DMA 中断中只做标志置位把复杂判断放在主循环阈值以下的任务中。采样数据的标定计算尽量使用整型运算减少不必要的浮点开销。建议把 ADC 原始值、电压换算公式、触发电平统一用一个配置结构体管理这样后续增加一键调零、自动量程等功能时不需要修改散落各处的数。所有与硬件相关的参数比如屏幕像素宽高、ADC 采样深度、参考电压值最好用宏定义集中在头文件中方便代码移植。9.2 安全与稳定性建议CH32V307 虽然性能不错但 ADC 的输入引脚依然脆弱。建议在任何完整项目中ADC 输入前端必须加入限流电阻和钳位保护。测试时不要把开发板和外部电路共地接错。如果使用 USB 同时给屏幕和信号源供电要考虑地线干扰带来的测量误差。生产或长期运行的设备还要额外关注电源去耦和散热问题。示波器采样持续高速运行时MCU 内部功耗会比空闲高不少开关电源纹波会直接耦合进 ADC 测量结果。在 ADC 参考电压引脚附近增加滤波电容是性价比最高的改进之一。9.3 后续可以深化的方向跑通一个基础的 CH32V307 开源示波器后建议按照下面三个阶段继续推进。第一个阶段是完善触发和交互增加按键调上下限、水平时基调整、电平调节并在屏幕上绘制坐标网格。第二个阶段是优化信号调理加入多档位继电器衰减网络做自动量程。这会涉及比较器电路和运放带宽选择是项目从“玩具”走向“仪表”的关键一步。第三个阶段是引入 USB 高速上位机把大量波形数据传到 PC在 PC 端实现频域分析、波形保存、协议解码。此时 CH32V307 的 USB 高速接口和 192KB SRAM 才会真正被充分利用。如果一个项目做完后你想再深入理解 RISC-V 芯片的内部实现还可以尝试把触发逻辑从主循环软件扫描改成 DMA 中断与定时器联动的硬件方案对比两种架构在最大采样率下的差异。这种底层时序能力的提升才是这个项目最值得沉淀的经验。回到最开始的问题CH32V307 开源示波器值不值得做如果只是为了“看波形”答案可能不值得但如果是为了理解一台示波器如何从 ADC 引脚上的电压变化变成屏幕上一条稳定的正弦曲线那这个项目就是一门非常生动的进阶课。推荐把官方 EVT 例程先下载下来从点亮屏幕和读取 ADC 原始值开始慢慢迭代出自己的版本。
返回列表