ESP32 DAC 真模拟输出入门:dacWrite 与「假 PWM」的区别

前置知识:PWM 完全入门。PWM 调光的本质是「快速开关骗过眼睛」,输出引脚上其实只有 0V 或 3.3V 两种电平。本篇讲的是 DAC——货真价实的连续电压输出。


一、DAC vs PWM:一字之差,本质不同

维度PWM(占空比)DAC(真模拟)
输出电平只有 0V / 3.3V(高速跳变)任意中间电压(连续)
原理时间平均「骗」负载电阻网络直接分压
可用引脚任意 GPIO仅 GPIO25/26(经典 ESP32)
分辨率理论可到 16 位8 位(256 级)
需要滤波吗视负载而定不需要
典型用途LED 亮度、电机调速波形发生、偏置电压、音频

一句话:PWM 是「占空比艺术」,DAC 是「电压直出」。驱动 LED 用 PWM 就够;要生成正弦波或给运放提供偏置,必须 DAC。


二、芯片可用性速查(重要)

芯片DAC说明
经典 ESP32✅ 2 路(GPIO25/26,通道 1/2)8 位
ESP32-S2✅ 2 路(GPIO17/18)8 位
ESP32-S3❌ 无 DAC用外置 DAC(如 MCP4725,走 I2C)
ESP32-C3/C6❌ 无 DAC同上

新项目若必须真模拟输出且用 S3/C3:MCP4725 模组(12 位、I2C、约 ¥3)是标准答案——I2C 用法见总线篇。


三、dacWrite 五分钟上手

#define DAC_PIN 25   // 只能是 25 或 26!

void setup() { /* DAC 无需 pinMode 初始化 */ }

void loop() {
  dacWrite(DAC_PIN, 0);     // 输出 0V
  delay(1000);
  dacWrite(DAC_PIN, 128);   // 输出约 1.65V
  delay(1000);
  dacWrite(DAC_PIN, 255);   // 输出约 3.3V
  delay(1000);
}
  • 8 位 = 0~255,每级约 12.9mV
  • 输出阻抗较高(不适合直接驱动低阻负载),带运放缓冲才稳
  • 输出电压是「约」——实测有偏差,精确场合需要标定

四、实战:生成正弦波

#define DAC_PIN 25

void setup() {
  Serial.begin(115200);
}

void loop() {
  // 生成 100Hz 正弦:每周期 100 点,每点 100µs
  for (int i = 0; i < 100; i++) {
    float v = (sinf(i * 2 * PI / 100) + 1) / 2 * 255;
    dacWrite(DAC_PIN, (int)v);
    delayMicroseconds(100);
  }
}

用硬件定时器替换 delayMicroseconds 可获得稳定的频率输出——定时器篇的四层选型在此直接适用。

性能天花板:DAC 转换速率约 8µs/次 → 理论最高方波 ~1MHz、实用正弦几十 kHz。做音频(语音级)可行,HiFi 不现实。


五、进阶:音频入门(0.5 秒了解)

DAC + 功放(MAX98357A)就是最简 ESP32 音频链路。但现代做法是 I2S 数字音频(精度高、不占 DAC)——属于 L3 知识点,本站后续专文。DAC 音频的价值在于理解原理:把 PCM 采样值按采样率循环 dacWrite 就是裸音频输出。


六、避坑速查表

场景结论
用 S3/C3 调 dacWrite芯片无 DAC,编译可能过但无输出;改用 MCP4725
想在 GPIO25/26 用 ADCGPIO25/26 复用 ADC2 通道——开 Wi-Fi 后冲突,别混用
DAC 输出带不动负载输出阻抗高,加运放电压跟随器
波形频率不稳delay 抖动,改硬件定时器驱动
要 12 位精度外置 MCP4725(I2C),内置只有 8 位
LED 调光该用 DAC 吗不,PWM 足够且任意引脚可用

七、延伸阅读


版权声明:本文采用 CC BY-SA 4.0 协议授权。转载与二创请注明出处:ESPDIY 创客工坊 - espdiy.com

ESP32 DAC True Analog Output Guide: dacWrite vs “Fake PWM”

Prerequisite: PWM Complete Guide. PWM dimming is really “switching fast enough to fool the load” — the pin only ever sits at 0V or 3.3V. This article covers the DAC: genuine continuous voltage output.


1. DAC vs PWM: one letter apart, fundamentally different

AspectPWM (duty cycle)DAC (true analog)
Output levelsOnly 0V / 3.3V (fast switching)Any intermediate voltage (continuous)
PrincipleTime-averaging “fools” the loadResistor ladder divides directly
PinsAny GPIOGPIO25/26 only (classic ESP32)
ResolutionUp to 16 bits theoretically8 bits (256 steps)
Filtering neededDepends on the loadNo
Typical usesLED brightness, motor speedWaveform generation, bias voltage, audio

One-liner: PWM is duty-cycle art; DAC is voltage direct out. LEDs want PWM; sine waves and op-amp bias voltages want a DAC.


2. Per-chip availability (important)

ChipDACNotes
Classic ESP32✅ 2 channels (GPIO25/26)8-bit
ESP32-S2✅ 2 channels (GPIO17/18)8-bit
ESP32-S3❌ no DACUse an external DAC (e.g. MCP4725 over I2C)
ESP32-C3/C6❌ no DACSame

New project on S3/C3 that truly needs analog out: the MCP4725 module (12-bit, I2C, ~¥3) is the standard answer — wiring covered in the buses guide.


3. dacWrite in five minutes

#define DAC_PIN 25   // must be 25 or 26!

void setup() { /* DAC needs no pinMode setup */ }

void loop() {
  dacWrite(DAC_PIN, 0);     // 0V
  delay(1000);
  dacWrite(DAC_PIN, 128);   // ~1.65V
  delay(1000);
  dacWrite(DAC_PIN, 255);   // ~3.3V
  delay(1000);
}
  • 8 bits = 0–255, ~12.9mV per step
  • The output impedance is high (don’t drive low-impedance loads directly); buffer with an op-amp follower
  • Voltages are “approximately” — calibrate if you need precision

4. Project: generating a sine wave

#define DAC_PIN 25

void setup() {
  Serial.begin(115200);
}

void loop() {
  // 100Hz sine: 100 points per cycle, 100µs each
  for (int i = 0; i < 100; i++) {
    float v = (sinf(i * 2 * PI / 100) + 1) / 2 * 255;
    dacWrite(DAC_PIN, (int)v);
    delayMicroseconds(100);
  }
}

Replacing delayMicroseconds with a hardware timer yields a rock-stable frequency — the four-layer selection from the timers guide applies directly.

Ceiling: DAC conversion takes ~8µs → theoretical max square wave ~1MHz, practical sines in the tens of kHz. Voice-grade audio: fine. HiFi: no.


5. Primer: audio in half a page

DAC + amp (MAX98357A) is the simplest ESP32 audio chain. The modern approach is I2S digital audio (higher precision, doesn’t consume the DAC) — an L3 topic with its own article. DAC audio’s value is understanding the principle: looping dacWrite over PCM samples at the sample rate is bare-metal audio output.


6. Pitfall cheat sheet

ScenarioVerdict
Calling dacWrite on S3/C3No DAC — may compile but outputs nothing; use MCP4725
Wanting ADC on GPIO25/26These are also ADC2 channels — conflict once Wi-Fi starts
DAC can’t drive the loadHigh output impedance — add an op-amp follower
Wobbly waveform frequencydelay jitter — drive from a hardware timer
Need 12-bit precisionExternal MCP4725 (I2C); the built-in one is 8-bit
Should LEDs use the DAC?No — PWM is enough and works on any pin

7. Further reading


License: CC BY-SA 4.0. Repost & remix with attribution: ESPDIY Maker Lab - espdiy.com