ESP32-S3播放音频时无法同步LCD显示屏的问题求助
ESP32-S3(SC01 Plus)AudioI2S与LVGL/LovyanGFX兼容问题解决
问题根源
你的问题核心是DMA通道资源冲突:ESP32-S3的AudioI2S库默认占用DMA通道0,而LovyanGFX的并行8位总线默认也会使用通道0。调用audio.setPinout()后,音频抢占了显示屏的DMA资源,导致屏幕无法正常刷新,最终冻结变黑,但音频不受影响。
解决方案步骤
- 指定LovyanGFX并行总线的DMA通道,避开AudioI2S使用的通道
- 调整任务优先级与核心绑定,确保LVGL任务拥有更高优先级,避免被音频任务抢占CPU
- 优化显示屏刷新回调,确保DMA操作的稳定性
- 调整初始化顺序,先完成音频初始化,再启动显示屏和LVGL
修改后的关键代码部分
1. 调整LovyanGFX总线配置,指定DMA通道
在LGFX类的总线配置块中添加DMA通道设置:
{ auto cfg = _bus_instance.config(); cfg.port = 0; cfg.freq_write = 40000000; cfg.pin_wr = 47; cfg.pin_rd = -1; cfg.pin_rs = 0; cfg.pin_d0 = 9; cfg.pin_d1 = 46; cfg.pin_d2 = 3; cfg.pin_d3 = 8; cfg.pin_d4 = 18; cfg.pin_d5 = 17; cfg.pin_d6 = 16; cfg.pin_d7 = 15; // 指定DMA通道1,避开AudioI2S默认的通道0 cfg.dma_channel = 1; _bus_instance.config(cfg); _panel_instance.setBus(&_bus_instance); }
2. 正确启用音频任务并设置优先级
取消setup()中playSound任务的注释,确保LVGL任务优先级高于音频任务:
// 在setup()中替换原注释的任务创建代码 xTaskCreatePinnedToCore( playSound, "playSound", 10240, NULL, 1, // 音频任务优先级设为1,低于LVGL的2 NULL, 0); // 绑定到核心0
3. 优化显示屏刷新回调
修改my_disp_flush函数,确保DMA传输完成后再标记刷新完成:
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { // 等待上一次DMA传输完成 while (tft.isDMA()) delay(1); tft.pushImageDMA(area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1, (lgfx::swap565_t *)&color_p->full); // 等待当前DMA传输完成再通知LVGL while (tft.isDMA()) delay(1); lv_disp_flush_ready(disp); }
4. 调整初始化顺序
将音频初始化步骤移到显示屏和LVGL初始化之前,确保音频先占用DMA通道0:
void setup() { Serial.begin(115200); // 先初始化音频相关 pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); if (!SD.begin(SD_CS)) { Serial.println("SD卡初始化失败!"); while (true); } audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); audio.setVolume(21); audio.connecttoFS(SD, "/Azahriah - 'FOUR MOODS' (OFFICIAL VISUALIZER).mp3"); xTaskCreatePinnedToCore(playSound, "playSound", 10240, NULL, 1, NULL, 0); // 再初始化显示屏和LVGL tft.init(); tft.initDMA(); tft.startWrite(); tft.setBrightness(255); lv_init(); if (!disp_draw_buf) { Serial.println("LVGL显示缓冲区分配失败!"); } else { lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, disp_draw_buf2, screenWidth * SCR); lv_disp_drv_init(&disp_drv); disp_drv.hor_res = screenWidth; disp_drv.ver_res = screenHeight; disp_drv.flush_cb = my_disp_flush; disp_drv.draw_buf = &draw_buf; lv_disp_drv_register(&disp_drv); static lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = my_touchpad_read; lv_indev_drv_register(&indev_drv); ui_init(); Serial.println("初始化完成"); } guiHandler(); }
验证要点
- 确认DMA通道设置正确:LovyanGFX用通道1,AudioI2S默认用通道0
- 任务优先级:LVGL任务优先级(2)高于音频任务(1),确保界面响应优先
- 刷新回调中等待DMA完成,避免冲突
内容的提问来源于stack exchange,提问作者Johny34
相关产品推荐
相关产品推荐

