Surfer-C3-1.14TFT 开发板适配实战:背光引脚改造与 ADC 电池电量检测)
小智AIxiaozhi-esp32Surfer-C3-1.14TFT 开发板适配实战背光引脚改造与 ADC 电池电量检测【免费下载链接】xiaozhi-esp32An MCP-based chatbot | 一个基于MCP的聊天机器人项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32本文面向使用立创·实战派 C3ESP32-C3衍生板——Surfer-C3-1.14TFT 的开发者系统讲解该板卡在小智AI 语音聊天机器人固件中的适配方式包括相对原版开发板的两处核心硬件改动TFT 背光引脚重映射、ADC 电池电量检测、16MB Flash 分区表选择、板级源码的初始化调用链以及省电模式与按键交互的实现细节。读完本文你将掌握该板卡的完整编译配置方法并能对照源码理解小智AI 板级驱动Board Driver的编写范式。一、板卡背景与 README 核心要点main/boards/surfer-c3-1.14tft/README.md是这份板卡适配的说明书全文虽然简短却点明了该板卡区别于立创·实战派 C3 原版的两个关键事实背光引脚改动基于立创·实战派 C3-ESP32C3 开发板修改了 TFT 屏幕背光引脚新增 ADC 电池检测增加了 ADC 电池电量检测功能Flash 规格约束该开发板 Flash 大小为 16MB编译时注意选择默认的分区表。这三条信息直接决定了固件能否在该板卡上正确编译与运行——尤其是16MB Flash 与默认分区表这一条若选择错误的分区表如 4MB/8MB轻则编译失败重则烧录后无法启动。下文将逐一结合源码展开。二、16MB Flash 与分区表选择2.1 为什么必须选默认分区表ESP32-C3 官方模组常见 Flash 规格为 4MB而 Surfer-C3-1.14TFT 板载 16MB Flash。小智AI 为不同 Flash 规格准备了独立分区表文件见 partitions/v24m.csv/8m.csv/16m.csv/16m_c3.csv/32m.csv其中 ESP32-C3 专用的是 partitions/v2/16m_c3.csv其内容如下# ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x4000, otadata, data, ota, 0xd000, 0x2000, phy_init, data, phy, 0xf000, 0x1000, ota_0, app, ota_0, 0x20000, 0x3f0000, ota_1, app, ota_1, , 0x3f0000, assets, data, spiffs, 0x800000, 4000K该分区表为双 OTA 镜像ota_0/ota_1各约 3.9MB预留了空间并将assets提示音、唤醒词等资源以 SPIFFS 形式放到 0x800000 偏移处、容量 4000K。这正对应该板卡 16MB Flash 的容量布局。在固件侧sdkconfig.defaults.esp32c3 已默认写入CONFIG_PARTITION_TABLE_CUSTOM_FILENAMEpartitions/v2/16m_c3.csv即 ESP32-C3 目标默认使用自定义分区表16m_c3.csv。README 中编译时注意选择默认的分区表指的就是保持该默认配置不要手动切换为 4MB/8MB 等分区方案。2.2 板卡类型如何被构建系统识别在 main/CMakeLists.txt 中构建系统通过 Kconfig 宏将板卡类型映射到源码目录elseif(CONFIG_BOARD_TYPE_SURFER_C3_1_14TFT) set(BOARD_DIR surfer-c3-1.14tft) set(BUILTIN_TEXT_FONT font_noto_sans_basic_20_4) set(BUILTIN_ICON_FONT font_material_symbols_20_4) set(DEFAULT_EMOJI_COLLECTION noto-color-emoji_32)而 main/boards/surfer-c3-1.14tft/config.json 则声明了板卡类型、芯片目标与附加 sdkconfig 项{ type: surfer-c3-1.14tft, target: esp32c3, builds: [ { name: surfer-c3-1.14tft, sdkconfig_append: [ CONFIG_PM_ENABLEy, CONFIG_FREERTOS_USE_TICKLESS_IDLEy, CONFIG_USE_ESP_WAKE_WORDy, CONFIG_ESP_CONSOLE_USB_SERIAL_JTAGy ] } ] }其中值得注意的几点target: esp32c3表明该板卡面向 ESP32-C3 芯片CONFIG_PM_ENABLEy与CONFIG_FREERTOS_USE_TICKLESS_IDLEy开启功耗管理配合下文介绍的省电定时器CONFIG_USE_ESP_WAKE_WORDy启用 ESP 官方唤醒词CONFIG_ESP_CONSOLE_USB_SERIAL_JTAGy将控制台日志重定向到 USB Serial/JTAG 口便于调试。此外docs/esp-idf-6-migration.md 的迁移矩阵中记录了esp32c3/surfer-c3-1.14tft在 IDF 6.0.1 下 Full build passed可作为该板卡在新版本 ESP-IDF 下可编译的参考依据。三、板级源码初始化流程与两处核心改动的落地板卡主程序位于 main/boards/surfer-c3-1.14tft/surfer-c3-1.14tft.cc类SurferC3114TFT继承自WifiBoard定义于 main/boards/common/wifi_board.h构造函数依次执行SurferC3114TFT() : boot_button_(BOOT_BUTTON_GPIO) { InitializePowerManager(); InitializePowerSaveTimer(); InitializeI2c(); InitializeSpi(); InitializeSt7789Display(); InitializeButtons(); GetBacklight()-RestoreBrightness(); // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); }最后一行esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO)是 ESP32-C3 上的关键操作将本用于给 SPI Flash 供电的 VDD_SPI 引脚释放为普通 GPIO。这是背光引脚改造能够成立的硬件前提——背光 PWM 信号正是从这类被释放的引脚输出。3.1 背光引脚改动从引脚定义到 PWM 背光README 提到的修改了 TFT 屏幕背光引脚在 config.h 中体现为#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 #define DISPLAY_BACKLIGHT_OUTPUT_INVERT false显示驱动 ST7789 的相关引脚同样集中在 config.h#define DISPLAY_SPI_SCK_PIN GPIO_NUM_3 #define DISPLAY_SPI_MOSI_PIN GPIO_NUM_5 #define DISPLAY_DC_PIN GPIO_NUM_6 #define DISPLAY_SPI_CS_PIN GPIO_NUM_4 #define DISPLAY_WIDTH 240 #define DISPLAY_HEIGHT 135 #define DISPLAY_MIRROR_X true #define DISPLAY_MIRROR_Y false #define DISPLAY_SWAP_XY true #define DISPLAY_OFFSET_X 40 #define DISPLAY_OFFSET_Y 53这是一块 240×135 的 1.14 英寸 TFTST7789 驱动且通过SWAP_XY/MIRROR与OFFSET_X40/OFFSET_Y53校正了屏幕方向与偏置——开发者若更换屏幕批次应优先核对这四个参数。背光在运行时由GetBacklight()提供virtual Backlight* GetBacklight() override { static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); return backlight; }即使用 PWM 方式驱动 GPIO_NUM_13 控制背光DISPLAY_BACKLIGHT_OUTPUT_INVERTfalse表示高电平点亮若硬件上用三极管反相驱动则需改为true。3.2 ADC 电池电量检测新增功能的源码实现README 提到的增加 ADC 电池电量检测功能其核心实现并非写在板级 cc 文件里而是封装在板卡目录下的 power_manager.h 中PowerManager类。初始化时power_manager_ new PowerManager(GPIO_NUM_NC);传入GPIO_NUM_NC表示没有独立的充电检测引脚硬件上未引出充放电状态脚因此充电状态只能依赖 ADC 数据间接判断。PowerManager内部实现要点以源码为准ADC 采样通道adc_oneshot_read(adc_handle_, ADC_CHANNEL_2, adc_value)使用 ADC1 的通道 2衰减ADC_ATTEN_DB_2_5位宽ADC_BITWIDTH_DEFAULT定时采样通过esp_timer每 1 秒触发一次CheckBatteryStatus()滑动平均维护最多 3 个 ADC 采样值队列取平均以抑制抖动分段线性插值使用 6 个标定点把 ADC 原始值映射为 0–100% 电量ADC 值电量百分比30600%320020%334040%348060%362080%3760100%低于 3060 记为 0%高于等于 3760 记为 100%中间值线性插值低电量阈值kLowBatteryLevel 20电量 ≤20% 时通过on_low_battery_status_changed_回调上报低电量事件充电判断由于充电引脚为GPIO_NUM_NCIsCharging()恒为 false除非电量恰好 100%IsDischarging()同样恒为 false。板级代码在GetBatteryLevel()中把 PowerManager 的电量接入系统virtual bool GetBatteryLevel(int level, bool charging, bool discharging) override { static bool last_discharging false; charging power_manager_-IsCharging(); discharging power_manager_-IsDischarging(); if (discharging ! last_discharging) { power_save_timer_-SetEnabled(discharging); last_discharging discharging; } level power_manager_-GetBatteryLevel(); return true; }注意由于本板未接线充电检测引脚discharging恒为 false因此power_save_timer_不会因开始放电而被动态启用详见下节。若读者在自己的硬件上接出了充电状态脚可将PowerManager的构造参数改为对应 GPIO即可启用充电/放电状态检测与低电量告警联动。四、省电模式modem-sleep 与屏幕降亮联动PowerManager之外板卡还集成了PowerSaveTimermain/boards/common/power_save_timer.h实现整机节能策略初始化代码power_save_timer_ new PowerSaveTimer(-1, 60, -1);三个参数分别表示CPU 最大频率上限-1 为不限制、进入休眠的静默秒数60 秒、关机等待秒数-1 为禁用自动关机。板卡注册了三个回调power_save_timer_-OnEnterSleepMode([this]() { ESP_LOGI(TAG, Enabling modem-sleep mode); GetDisplay()-SetPowerSaveMode(true); GetBacklight()-SetBrightness(1); esp_wifi_set_ps(WIFI_PS_MIN_MODEM); }); power_save_timer_-OnExitSleepMode([this]() { GetDisplay()-SetPowerSaveMode(false); GetBacklight()-RestoreBrightness(); esp_wifi_set_ps(WIFI_PS_NONE); // 关闭Wi-Fi省电恢复正常 }); power_save_timer_-OnShutdownRequest([this]() { ESP_LOGI(TAG, Shutting down display); GetBacklight()-SetBrightness(1); });其工作逻辑为设备静默 60 秒后进入省电态屏幕进入低功耗模式、背光降到最低亮度 1并将 Wi-Fi 切换到WIFI_PS_MIN_MODEMmodem-sleep以降低射频功耗检测到唤醒如唤醒词、按键时退出省电态恢复屏幕与背光并将 Wi-Fi 切回WIFI_PS_NONE保证低延迟响应OnShutdownRequest目前仅将背光调暗未真正断电相关esp_lcd_panel_disp_on_off与定时器禁用逻辑在源码中被注释保留可视为后续增强的预留位。同时config.json 中开启的CONFIG_PM_ENABLEy与CONFIG_FREERTOS_USE_TICKLESS_IDLEy为上述软件省电策略提供了底层支撑分别启用电源管理与空闲 tickless 机制。充电联动方面InitializePowerManager()中注册了充电状态回调充电时禁用省电定时器非充电时启用power_manager_-OnChargingStatusChanged(this { if (is_charging) { power_save_timer_-SetEnabled(false); } else { power_save_timer_-SetEnabled(true); } });五、外设初始化I2CES8311 音频、SPIST7789 显示与按键5.1 I2C 总线与 ES8311 音频编解码器InitializeI2c()创建 I2C 主机总线I2C_NUM_0SDA/SCL 来自 config.h#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_0 #define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 #define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR初始化后立即探测地址0x18ES8311 默认地址失败则循环打印错误并阻塞if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) ! ESP_OK) { while (true) { ESP_LOGE(TAG, Failed to probe I2C bus, please check if you have installed the correct firmware); vTaskDelay(1000 / portTICK_PERIOD_MS); } }这是一个很实用的固件-硬件匹配自检若烧录了错误的固件硬件探测不到 ES8311设备会通过日志明确提示而不是无声失败。音频通路由GetAudioCodec()返回Es8311AudioCodec实现见 main/audio/codecs/es8311_audio_codec.ccI2S 引脚定义#define AUDIO_INPUT_SAMPLE_RATE 24000 #define AUDIO_OUTPUT_SAMPLE_RATE 24000 #define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 #define AUDIO_I2S_GPIO_WS GPIO_NUM_12 #define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 #define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 #define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11音频采样率固定为 24kHz 双向AUDIO_CODEC_PA_PIN为GPIO_NUM_NC说明功放使能脚未单独控制或由编解码器内部管理。5.2 SPI 总线与 ST7789 显示InitializeSpi()以SPI2_HOST初始化 SPI 总线max_transfer_sz按整帧大小设置buscfg.max_transfer_sz DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, buscfg, SPI_DMA_CH_AUTO));InitializeSt7789Display()则依次完成创建 SPI 面板 IOpclk_hz 80MHz、SPI mode 0、lcd_cmd_bits/lcd_param_bits 8创建 ST7789 面板16bit 像素、RGB 顺序初始化后执行esp_lcd_panel_invert_color(panel_, true)ST7789 通常需要颜色反转以及swap_xy/mirror校正最终以SpiLcdDisplay封装为小智AI 的Display抽象见 main/display/lcd_display.h。5.3 按键交互板卡仅使用 BOOT 按键GPIO_NUM_9实现交互#define BOOT_BUTTON_GPIO GPIO_NUM_9 #define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC #define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC单次点击逻辑surfer-c3-1.14tft.ccboot_button_.OnClick([this]() { auto app Application::GetInstance(); if (app.GetDeviceState() kDeviceStateStarting) { EnterWifiConfigMode(); return; } app.ToggleChatState(); });设备处于启动未联网配置状态时单击 BOOT 键进入 Wi-Fi 配网模式正常运行状态下单击 BOOT 键切换聊天状态开始/结束一轮对话。该板未配置音量键与内置 LEDBUILTIN_LED_GPIO GPIO_NUM_NC音量调节依赖语音指令或上位机协议这是硬件本身决定的。六、编译与烧录指引结合 docs/custom-board_zh.md 中描述的构建方式编译该板卡固件可直接使用python scripts/build.py surfer-c3-1.14tft要点回顾保持分区表默认ESP32-C3 目标默认即使用 partitions/v2/16m_c3.csv与 16MB Flash 匹配请勿覆盖为 4MB/8MB 分区板卡标识唯一性config.json中的type: surfer-c3-1.14tft是 OTA 升级通道的唯一标识不要与其他板卡混用否则可能被错误固件覆盖详见 docs/custom-board_zh.md 中的警告确认硬件匹配烧录后如出现Failed to probe I2C bus循环报错说明 ES8311 未被探测到请检查音频电路与固件类型是否匹配串口日志CONFIG_ESP_CONSOLE_USB_SERIAL_JTAGy使日志从 USB 口输出TAG SURFERC3114TFT与PowerManager是排查初始化与电量检测问题时的关键日志标签。七、总结Surfer-C3-1.14TFT 作为立创·实战派 C3 的衍生板在小智AI 中的适配体现了两个典型实践硬件差异的软件化表达背光引脚改动、ADC 电量检测分别通过 config.h 的引脚宏与 power_manager.h 的采样-插值实现完成说明硬件改版只需更新板级目录即可无需触碰应用层代码资源约束的显式声明16MB Flash 对应16m_c3.csv分区表、省电策略对应PowerSaveTimer Wi-Fi modem-sleep这些都集中体现在config.json的sdkconfig_append与板级初始化代码中。如需自行验证或扩展可沿着main/boards/surfer-c3-1.14tft/目录下的三个文件.cc/.h/.json出发对照 docs/custom-board_zh.md 的板卡定制流程将该板卡的适配经验迁移到自己的硬件上。【免费下载链接】xiaozhi-esp32An MCP-based chatbot | 一个基于MCP的聊天机器人项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考