ESP32 波形发生器

基于 ESP32 的多功能 DDS 信号发生器 · WiFi 网页控制 · 串口命令

v1.0 ESP32 Arduino Core 3.3.8 DDS 100kHz

📦 产品概述

ESP32 多功能波形发生器是一款基于 ESP32 开发板实现的 DDS 信号发生器。 支持通过 WiFi 网页串口命令 两种方式进行控制, 可输出正弦波、三角波、方波、锯齿波四种波形,并支持频率、幅度以及方波占空比的实时调节。

主要特性

✅ 四种波形:正弦波、三角波、方波、锯齿波
✅ 频率范围:1 Hz ~ 5 kHz
✅ 幅度范围:0 ~ 255(8-bit DAC,0 = 0V,255 = 3.3V)
✅ 方波占空比:0% ~ 100% 连续可调
✅ 采样率:100 kHz(5kHz 时每周期 20 点)
✅ 32 位 DDS 累加器,频率分辨率约 0.000023 Hz
✅ WiFi 配置自动保存至 EEPROM,串口命令可重置
✅ 双控制方式:Web 网页 + 串口命令

🔌 硬件说明

引脚连接

ESP32 引脚功能说明
GPIO25波形输出DAC1 模拟输出,连接示波器或负载
GND地线与测量设备共地
USB供电 + 串口5V 供电,同时用于串口通信

硬件连接图

ESP32 Dev Board
GPIO25 ────► CH1
GND ────► GND
USB ──── PC
连线示意
示波器 / 万用表
CH1
GND
注意事项:
GPIO25 为 DAC 输出,不要连接到超过 3.3V 的电压。
输出阻抗较高,驱动能力弱,建议接高阻抗负载(>10kΩ)。
如需驱动低阻抗负载,建议添加运放缓冲电路。

🚀 首次使用

  1. 上传程序(默认已烧录)
    打开 Arduino IDE → Tools → Board → ESP32 Dev ModuleTools → Port → 你的 COM 口 → 点击上传按钮。
  2. WiFi 配置 —— 上传完成后打开串口监视器(115200 波特率),将看到:
    === ESP32 Waveform Generator === Serial commands: reset, restart, status, help ✓ Timer: 100kHz --- WiFi Initialization --- No saved config found ========================================== WiFi Configuration Mode ========================================== Enter SSID:
    依次输入 WiFi 信息(不同 IDE 输入方式或有不同,Arduino IDE 是输入完直接回车):
    Enter SSID: ChinaNet-home ← 输入你的 WiFi 名称 Enter Password: 12345678 ← 输入密码 ✓ Config saved to EEPROM ← 自动保存
    即使输错也没关系,连接不上会再次提示输入。
    Connecting to ChinaNet-home......... ✓ WiFi connected! IP: 192.168.1.100 ✓ Web server started → Open http://192.168.1.100
  3. 访问网页 —— 在浏览器地址栏输入串口显示的 IP 地址(如 http://192.168.1.100),即可打开控制界面。
    ⚠ 你获得的 IP 不一定是上面这个,请以串口实际显示的 IP 为准。

🌐 Web 控制界面

🎵 ESP32 波形发生器
▶ 状态: 运行中
波形:[ 正弦波 ▾ ]
占空比: 50% [50] (仅方波时显示)
频率: 100Hz [100]
幅度: 128 [128]
▶ 开始 ⏹ 停止

控制项说明

控制项类型范围说明
波形选择下拉菜单正弦 / 三角 / 方波 / 锯齿实时切换波形类型
占空比滑杆 + 输入框0 ~ 100%仅方波时显示,调节高电平占比
频率滑杆 + 输入框1 ~ 5000 Hz输出信号频率
幅度滑杆 + 输入框0 ~ 255输出电压(0 = 0V,255 = 3.3V)
开始按钮启动波形输出
停止按钮停止输出(输出 0V)
滑杆 + 输入框联动:
拖动滑杆 → 数字输入框同步更新
直接在数字框输入 → 滑杆同步移动
支持精确数值设定

串口命令

打开串口监视器(115200 波特率),输入以下命令后回车:

命令列表

命令功能说明
help显示帮助列出所有可用命令
status显示系统状态显示 WiFi 和波形参数
reset清除 WiFi 配置清除后需要重启设备
restart重启 ESP32设备重新启动

命令示例

1. 查看状态

> status ← ">" 符号后面是需要输入并回车的,下同 --- System Status --- WiFi Config: Present (SSID: ChinaNet-home) WiFi Connected: Yes IP Address: 192.168.1.100 Waveform: Sine Frequency: 100 Hz Amplitude: 128 Duty Cycle: 50% Waveform Running: Yes

2. 清除 WiFi 配置(更换网络时使用)

> reset >>> RESET command received <<< === Clearing WiFi Config === ✓ WiFi configuration cleared! Magic number: 0x0000 (was 0xA5A5) SSID cleared Password cleared Please restart the device to enter config mode

3. 重启设备

> restart Restarting... [ ESP32 重新启动,进入 WiFi 配置模式 ]

4. 帮助

> help --- Available Commands --- reset - Clear saved WiFi configuration restart - Restart the device status - Show system status help - Show this help

DDS 原理与实现

什么是 DDS

DDS(Direct Digital Synthesis,直接数字频率合成)是一种 从单个固定频率的参考时钟生成任意波形的全数字技术。与传统的模拟振荡器(如 VCO、PLL)不同, DDS 通过数字累加和查表的方式合成波形,具有以下显著优势:

🎯 频率分辨率极高(取决于累加器位宽)
⚡ 频率切换速度极快(仅需写入频率字)
🔄 相位连续(频率切换时波形不跳变)
📐 任意波形可编程(修改波表即可)

核心原理

DDS 的核心由三个部分构成:N 位相位累加器波表(Wave Table / LUT)DAC(数模转换器)

频率字
(FTW / phaseInc)
N 位相位累加器
(phaseAcc, 32bit)
每个时钟: += phaseInc
波表 LUT
(512 点)
DAC
(8-bit)
输出
▲ 采样时钟 100 kHz(定时器中断驱动)

每个采样时钟周期,相位累加器加上一个固定的增量(频率字 phaseInc), 累加器的高位作为地址去波表中查值,查到的波形数据送给 DAC 输出。当累加器溢出时自然回到零, 实现循环输出,保证相邻周期的相位连续。

频率计算公式

设采样率为 Fs,累加器位宽为 N,目标频率为 Fout,则相位增量(频率字)为:

phaseInc = Fout × 2N ÷ Fs

本项目参数代入:

参数符号
采样率Fs100,000 Hz(100 kHz)
累加器位宽N32 bit
波表长度M512 点
频率字计算phaseInctargetFreq × 232 ÷ 100000
理论频率分辨率ΔFFs ÷ 2N = 100000 ÷ 4294967296 ≈ 0.000023 Hz

本项目的 DDS 实现

① 波表预生成(generateWaveTable()

启动时在 SRAM 中生成一个 512 点的 uint8_t waveTable[512],每个点对应 一个 DAC 输出值(0 ~ 255)。

  • 正弦波:通过 sin(2π × t) 计算,范围 [-1, +1] 映射到 [0, 255]
  • 三角波:分段线性函数——0→25% 上升,25%→75% 下降,75%→100% 上升
  • 方波:根据占空比阈值判定,前半周期输出最大值,后半周期输出最小值
  • 锯齿波:线性递增 y = 2t - 1

波表在波形类型、幅度或占空比变化时重新生成。

② 相位累加器(phaseAcc

32 位无符号整数 volatile uint32_t phaseAcc,每个定时器中断自动累加 phaseInc。累加器 自然溢出 即为一个完整周期的结束, 溢出后从 0 继续累加,保证相邻周期的相位连续,无需任何软件干预。

③ 查表输出(onTimer() ISR)

定时器中断以 100 kHz 的频率触发,在 ISR(中断服务程序)中执行的步骤:

void IRAM_ATTR onTimer() {
  if (waveformRunning) {
    dacWrite(25, waveTable[phaseAcc >> 23]);  // 查表 + DAC 输出
    phaseAcc += phaseInc;                       // 累加相位
  }
}

phaseAcc >> 23 右移 23 位(32 - 9 = 23), 取 32 位累加器的高 9 位作为 512 点波表的索引地址(29 = 512)。 查表值直接写入 ESP32 的 8 位 DAC(GPIO25)。

④ 频率更新(updatePhaseIncrement()

void updatePhaseIncrement() {
  uint64_t inc = (uint64_t)targetFreq * (1ULL << 32) / SAMPLE_RATE;
  phaseInc = (uint32_t)inc;
}

使用 64 位中间变量避免乘法溢出。由于 phaseInc 的变化只影响后续的 累加步进,而不会重置相位累加器,因此频率切换时波形相位是连续的,不会产生跳变或毛刺。

关键代码映射

代码位置对应 DDS 部件说明
#define SAMPLE_RATE采样时钟频率100 kHz
#define WAVE_TABLE_SIZE波表大小512 点
waveTable[512]查找表 (LUT)存储预计算波形值
phaseAcc相位累加器32-bit,溢出自动回绕
phaseInc频率字 / 相位增量控制输出频率
onTimer()采样输出 ISR每个中断输出一个 DAC 值
phaseAcc >> 23波表地址生成取高 9 位寻址 512 点波表
updatePhaseIncrement()频率调谐字计算公式: freq × 2³² ÷ Fs
generateWaveTable()波表重构波形/幅度/占空比变化时调用

为什么选择 32 位累加器?

32 位累加器提供了极高的频率分辨率(约 0.000023 Hz),即使是 1 Hz 的超低频信号也能精确合成。 如果使用 16 位累加器,频率分辨率仅为约 1.5 Hz(100000 ÷ 65536),低频段的精度会明显不足。

为什么选择 512 点波表?

512 点(2⁹)的波表配合 100 kHz 采样率,在 5 kHz 最高频率时每周期输出 20 个采样点, 在 1 kHz 时每周期有 100 个点。这是在 ESP32 有限的 SRAM(512 字节波表)和波形质量之间的良好折中。 更多点数可进一步降低高频失真,但内存开销也会相应增加。

DDS 信号流程图

用户设定:波形类型 / 频率 / 幅度 / 占空比
① generateWaveTable()
按需重建 512 点波表
② updatePhaseIncrement()
频率 → 相位增量换算
③ 定时器中断 ISR (100 kHz)
phaseAcc += phaseInc; ← 32 位累加器累加
idx = phaseAcc >> 23; ← 取高 9 位作为波表地址
val = waveTable[idx]; ← 查表取值
dacWrite(GPIO25, val); ← 写入 DAC
ESP32 DAC (8-bit) → GPIO25 模拟信号输出

📊 技术参数

电学参数

参数说明
供电电压5V (USB)通过 USB 口供电
输出电压0 ~ 3.3V8 位 DAC 分辨率
输出阻抗≈ 5 kΩ建议负载 > 10 kΩ
输出频率1 Hz ~ 5 kHz100 kHz 采样率
频率分辨率≈ 0.000023 Hz32 位 DDS 累加器
输出引脚GPIO25DAC1 通道

波形参数

波形特征占空比可调
正弦波平滑、低失真
三角波线性上升 / 线性下降
方波快速电平跳变✅(0% ~ 100%)
锯齿波缓慢上升、快速下降

采样精度

参数
DAC 分辨率8-bit(256 级)
采样率100 kHz
波表点数512 点
5 kHz 每周期点数20 点
1 kHz 每周期点数100 点
50 Hz 每周期点数2000 点

🔧 故障排除

问题 1:没有波形输出

可能原因解决方法
GPIO25 未连接检查杜邦线连接是否牢固
GND 未共地确保示波器 / 负载与 ESP32 共地
波形未开始点击网页"开始"按钮启动输出
幅度为 0调节幅度滑杆到 > 0

问题 2:WiFi 连接失败

检查 WiFi 密码是否正确。
使用 reset 命令清除配置后重新配置。
确保 WiFi 是 2.4 GHz 频段(ESP32 不支持 5 GHz WiFi)。
检查路由器是否开启了 MAC 地址过滤。

问题 3:网页无法访问

确认串口监视器显示的 IP 地址。
电脑和 ESP32 必须在同一局域网内。
尝试 ping <ESP32-IP> 测试连通性。
临时关闭 Windows 防火墙进行测试。

问题 4:波形有毛刺 / 不光滑

降低频率(100 Hz 以下波形非常平滑)。
降低幅度(避免 DAC 非线性区)。
检查电源纹波,建议使用质量较好的 USB 供电。

问题 5:方波占空比不正确

确保波形类型选择了"方波"。
占空比滑块仅在方波时显示。调节后波形会重新生成。

常用命令速查

🌐 网页操作

操作说明
浏览器打开 IP访问控制界面
选择波形切换正弦/三角/方波/锯齿
拖动滑杆调节频率/幅度/占空比
点击开始启动波形输出
点击停止停止输出

⌨ 串口命令

命令用途
help显示帮助
status查看状态
reset清除 WiFi 配置
restart重启设备