先确认编译的是哪个框架,保存第一个错误
看到ledcSetup未声明,先记录Arduino CLI/IDE版本、esp32:esp32 core版本、完整FQBN、实际选中的库路径和第一条错误。Arduino core自带IDF,但这仍是Arduino接口;直接复制ESP-IDF的ledc_timer_config并不能替代一轮有依据的迁移。
迁移说明中的3.0基于IDF5.1,是那次大版本变化的起点;本篇目标3.3.12内置IDF5.5.5。不要因此把每个3.x都标成5.1,也不要把某篇2021年的编译截图当成当前版本结果。先在独立目录留住原稿,避免同时改库、板型和引脚后无从定位。
arduino-cli version
arduino-cli core list
# 完整FQBN和实际命令见下载README;保留第一条error及其前后的文件路径。- 做到这里,你应该看到
- 错误报告能指出core、目标板和首个出错符号,且原始代码有备份。
参考:[1] Arduino-ESP32 3.3.12固定迁移说明:2.x到3.0[2] Arduino-ESP32 2.0.17 LEDC头文件:通道式接口[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值
用最小旧代码复现,而不是盲目降级所有库
下面是本站写的2.x风格最小例子:配置通道0,再把GPIO4接到通道0。下载中的legacy_pwm.ino.txt故意不以可自动构建的.ino后缀存放;按README复制到独立LegacyPWM目录再编译,目标仍固定3.3.12。
预期错误是ledcSetup和ledcAttachPin未声明。这个失败是需要保存的版本差异证据;不能以“退出码不是0”就说网络、USB或LED接线坏了。本站只核对2.0.17头文件曾提供这些声明,没有安装旧core或声称旧版实板测试通过。
// SPDX-License-Identifier: MIT
// Deliberately uses Arduino-ESP32 2.x APIs. Expected to fail with core 3.3.12.
#include <Arduino.h>
constexpr uint8_t LED_PIN = 4, PWM_CHANNEL = 0;
void setup() {
Serial.begin(115200);
ledcSetup(PWM_CHANNEL, 1000, 8);
ledcAttachPin(LED_PIN, PWM_CHANNEL);
ledcWrite(PWM_CHANNEL, 128);
}
void loop() { delay(1000); }
参考:[1] Arduino-ESP32 3.3.12固定迁移说明:2.x到3.0[2] Arduino-ESP32 2.0.17 LEDC头文件:通道式接口[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值
把通道改成引脚:同一个整数可能仍能编译
在所锁3.3.12中,ledcAttach(GPIO4,1000,8)同时申请资源并关联引脚,普通ledcWrite的第一个参数也变为GPIO。若只改初始化、仍写ledcWrite(0,128),C++类型检查可能通过,但现在是在访问GPIO0对应资源,不再表示旧通道0。检查返回值才能看见这类失败,不能只看编译器。
显式通道需求另有ledcAttachChannel与ledcWriteChannel,不应该靠把变量名改成channel就恢复旧语义。本例只有一盏灯,使用自动通道即可。频率1000Hz、8位和0/128/255是本例固定输入;占空比档位不是线性的肉眼亮度或光通量标定。
| 2.0.17旧意图 | 3.3.12本例 | 必须检查 |
|---|---|---|
| ledcSetup(channel,freq,bits) + ledcAttachPin(pin,channel) | ledcAttach(pin,freq,bits) | bool attach结果 |
| ledcWrite(channel,duty) | ledcWrite(pin,duty) | 参数语义及bool结果 |
| 旧资料的ledcDetachPin(pin) | ledcDetach(pin) | 当前声明及资源归属 |
参考:[1] Arduino-ESP32 3.3.12固定迁移说明:2.x到3.0[2] Arduino-ESP32 2.0.17 LEDC头文件:通道式接口[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值[4] Arduino-ESP32 3.3.12 LEDC实现:资源映射、写入与读回
完整迁移程序:失败时停止PWM,输出回到LOW
先断电接GPIO4(J1-4)→330Ω→WP7113ID阳极,阴极→GND;只用USB-to-UART供电。板上GPIO38是可寻址RGB,不接入本例,换成它不是修API错误的方法。电源孔组和LED极性按基础课检查。
程序先attach,成功才写128;串口0/1/2分别请求0/128/255。write失败时记录错误、解绑并将GPIO4设为普通LOW,不继续输出一串“成功”日志。驱动读回和频率API提供软件上下文,不是示波器或光学测量。
所锁实现会把8位满档255转为硬件全开计数,因此driver_duty可能与请求值不同;ledcReadFreq在duty读回为0时返回0,也不能据此说时钟频率变成0。对照固定实现理解日志,再用仪器检验真实信号。
// SPDX-License-Identifier: MIT
// F08: Arduino-ESP32 3.3.12; DevKitC-1 v1.1 N8R8; external LED on GPIO4.
#include <Arduino.h>
constexpr uint8_t LED_PIN = 4, RESOLUTION = 8;
constexpr uint32_t FREQUENCY = 1000;
bool pwmReady = false;
void stopPwm() {
ledcDetach(LED_PIN);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
pwmReady = false;
}
bool setDuty(uint32_t duty) {
if (!pwmReady) return false;
if (!ledcWrite(LED_PIN, duty)) {
Serial.println("WRITE_FAILED: detached; GPIO4 forced LOW");
stopPwm();
return false;
}
Serial.printf("F08 pin=%u requested_duty=%lu driver_duty=%lu driver_hz=%lu; not a waveform measurement\n",
LED_PIN, (unsigned long)duty, (unsigned long)ledcRead(LED_PIN),
(unsigned long)ledcReadFreq(LED_PIN));
return true;
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
pwmReady = ledcAttach(LED_PIN, FREQUENCY, RESOLUTION);
Serial.printf("F08 core=3.3.12 attach=%u; commands 0=off 1=128 2=255\n", pwmReady);
if (pwmReady) setDuty(128);
else Serial.println("ATTACH_FAILED: check pin, resource ownership, frequency and resolution");
}
void loop() {
if (Serial.available()) {
const char key = Serial.read();
if (key == '0') setDuty(0);
else if (key == '1') setDuty(128);
else if (key == '2') setDuty(255);
}
delay(1);
}
- 做到这里,你应该看到
- 能够解释请求值、驱动读回和真实波形三者的区别;没有依据不填写实测频率。
参考:[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值[4] Arduino-ESP32 3.3.12 LEDC实现:资源映射、写入与读回[5] DevKitC-1 v1.1固定板级资料:排针与GPIO38 RGB[6] Kingbright WP7113ID V.14A:普通LED极性与额定
先比较构建记录,再上传并逐档检查
在MigratedPWM目录按README完整FQBN编译;8MB/QIO、OPI PSRAM、CDC关闭和桥接口保持与F06一致。保存旧稿失败与新稿Exit0的命令、源SHA和日志。若仍报旧API,优先检查编译路径是否指向了另一个副本,而不是同时升级全部依赖。
具备实板后才上传,115200监视,记录attach结果并依次发送0、1、2。每档同时保存程序回报与普通LED观察;需要频率/占空比结论时另记测点、仪器和波形。RESET后应重新进入默认128,这仍是待实际执行的验收,不是本站已采到的日志。
编译已过但灯不亮时,先发0并断电检查LED、电阻和共地,再核对GPIO4;attach失败则查引脚已有外设占用及参数组合。恢复到下载中未改的MigratedPWM重建,必要时回F06最小串口程序,不靠删除SDK头文件或绕过返回值。
参考:[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值[4] Arduino-ESP32 3.3.12 LEDC实现:资源映射、写入与读回[5] DevKitC-1 v1.1固定板级资料:排针与GPIO38 RGB
I2S和BLE另做小范围迁移,不套用这张LEDC表
迁移指南也列出了I2S驱动重构、BLE返回类型以及其他接口变化;它们不是改一个头文件名就一定修好。先把报错归入对应组件,在相同core tag下查声明和随版本例程,保持原硬件与数据格式,再独立构建和验收。
不要为了让旧教程编译而把所有依赖降到一个未知组合。若项目确实必须保留旧版本,在隔离环境中固定完整依赖并写清维护范围;本篇不为该路径提供运行保证。这里可交付的是可追踪的迁移过程和固定3.3.12成品,实板结果继续单独记录。
参考:[1] Arduino-ESP32 3.3.12固定迁移说明:2.x到3.0[3] Arduino-ESP32 3.3.12 LEDC头文件:引脚、通道与bool返回值[4] Arduino-ESP32 3.3.12 LEDC实现:资源映射、写入与读回
资料来源与版本说明
迁移总览说明2.x到3.0的起点变化;当前3.3.12的准确声明和行为另查固定tag源码,不能把整个3.x都说成IDF5.1。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。