单SPI总线驱动双物理屏:LVGL下副屏横屏显示画面异常
问题:双屏LVGL横屏显示异常
在Adafruit Feather ESP32-S3上使用LVGL驱动两块ILI9341屏幕时遇到问题:基础Adafruit_GFX驱动单独工作正常,但接入LVGL后,主屏显示正常,副屏设置为横屏(旋转角度3)时画面损坏。将副屏旋转角度改为0或2,或者移除LVGL仅用Adafruit驱动时,副屏显示恢复正常。Arduino IDE编译无内存报错,下图右侧为主屏,左侧为异常的副屏。
#include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #include <lvgl.h> // 验证可用的SPI + ILI9341引脚 #define TFT_SCK 12 #define TFT_MOSI 11 // 上方屏幕(ILI9341)引脚 - 已验证 #define UPPER_CS 10 #define UPPER_DC 9 #define UPPER_RST 6 // 下方屏幕引脚 #define LOWER_CS 14 #define LOWER_DC 8 #define LOWER_RST 5 Adafruit_ILI9341 upper(UPPER_CS, UPPER_DC, UPPER_RST); Adafruit_ILI9341 lower(LOWER_CS, LOWER_DC, LOWER_RST); inline void selectUpper() { digitalWrite(LOWER_CS, HIGH); digitalWrite(UPPER_CS, LOW); } inline void deselectUpper() { digitalWrite(UPPER_CS, HIGH); } inline void selectLower() { digitalWrite(UPPER_CS, HIGH); digitalWrite(LOWER_CS, LOW); } inline void deselectLower() { digitalWrite(LOWER_CS, HIGH); } #define UPPER_TFT_HOR_RES 320 #define UPPER_TFT_VER_RES 240 #define LOWER_TFT_HOR_RES 320 #define LOWER_TFT_VER_RES 240 static void flush_upper(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) { const uint32_t w = area->x2 - area->x1 + 1; const uint32_t h = area->y2 - area->y1 + 1; selectUpper(); upper.startWrite(); upper.setAddrWindow(area->x1, area->y1, w, h); upper.writePixels((uint16_t*)px_map, w * h, true); upper.endWrite(); deselectUpper(); lv_display_flush_ready(disp); } static void flush_lower(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) { const uint32_t w = area->x2 - area->x1 + 1; const uint32_t h = area->y2 - area->y1 + 1; selectLower(); lower.startWrite(); lower.setAddrWindow(area->x1, area->y1, w, h); lower.writePixels((uint16_t*)px_map, w * h, true); lower.endWrite(); deselectLower(); lv_display_flush_ready(disp); } static uint32_t my_tick_cb(void) { return millis(); } void setup() { Serial.begin(115200); delay(200); pinMode(UPPER_CS, OUTPUT); pinMode(LOWER_CS, OUTPUT); pinMode(UPPER_DC, OUTPUT); pinMode(LOWER_DC, OUTPUT); digitalWrite(UPPER_CS, HIGH); digitalWrite(LOWER_CS, HIGH); /*初始化LVGL*/ lv_init(); /*为LVGL设置基于毫秒的时钟源,用于时间追踪*/ lv_tick_set_cb(my_tick_cb); lv_display_t * upperDisplay = lv_display_create(UPPER_TFT_HOR_RES, UPPER_TFT_VER_RES); lv_display_t * lowerDisplay = lv_display_create(LOWER_TFT_HOR_RES, LOWER_TFT_VER_RES); static lv_color_t upperBuf[UPPER_TFT_HOR_RES * UPPER_TFT_VER_RES / 10 ]; lv_display_set_buffers(upperDisplay, upperBuf, NULL, sizeof(upperBuf), LV_DISPLAY_RENDER_MODE_PARTIAL); static lv_color_t lowerBuf[LOWER_TFT_HOR_RES * LOWER_TFT_VER_RES / 10 ]; lv_display_set_buffers(lowerDisplay, lowerBuf, NULL, sizeof(lowerBuf), LV_DISPLAY_RENDER_MODE_PARTIAL); lv_display_set_flush_cb(upperDisplay, flush_upper); lv_display_set_flush_cb(lowerDisplay, flush_lower); SPI.begin(TFT_SCK, -1, TFT_MOSI); // --- 初始化上方屏幕 --- selectUpper(); upper.begin(); upper.setSPISpeed(8000000); upper.setRotation(3); upper.fillScreen(ILI9341_BLACK); deselectUpper(); // --- 初始化下方屏幕 --- selectLower(); lower.begin(); lower.setSPISpeed(8000000); lower.setRotation(3); Serial.print("lower width = "); Serial.println(lower.width()); Serial.print("lower height = "); Serial.println(lower.height()); lower.fillScreen(ILI9341_BLACK); delay(500); lower.fillScreen(ILI9341_RED); deselectLower(); lv_obj_t * upperScreen = lv_display_get_screen_active(upperDisplay); lv_obj_t * lowerScreen = lv_display_get_screen_active(lowerDisplay); lv_obj_t * upperLabel = lv_label_create(upperScreen); lv_label_set_text(upperLabel, "Hello world"); lv_obj_center(upperLabel); lv_obj_t * lowerLabel = lv_label_create(lowerScreen); lv_label_set_text(lowerLabel, "Hi"); lv_obj_center(lowerLabel); } void loop() { lv_timer_handler(); delay(5); }

内容的提问来源于stack exchange,提问作者Collin




