1.圖檔轉換工具:先把圖檔轉換成LVGL格式
https://lvgl.io/tools/imageconverter
2.選擇RGB565產生一個.c的圖檔,例子是animation2.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #ifdef __has_include #if __has_include("lvgl.h") #ifndef LV_LVGL_H_INCLUDE_SIMPLE #define LV_LVGL_H_INCLUDE_SIMPLE #endif #endif #endif #if defined(LV_LVGL_H_INCLUDE_SIMPLE) #include "lvgl.h" #else #include "lvgl/lvgl.h" #endif #ifndef LV_ATTRIBUTE_MEM_ALIGN #define LV_ATTRIBUTE_MEM_ALIGN #endif #ifndef LV_ATTRIBUTE_IMAGE_TILE000 #define LV_ATTRIBUTE_IMAGE_TILE000 #endif const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_TILE000 uint8_t tile000_map[] = { /*圖檔資料太, 省略*/ }; const lv_image_dsc_t tile000 = { .header.cf = LV_COLOR_FORMAT_RGB565, .header.magic = LV_IMAGE_HEADER_MAGIC, .header.w = 320, .header.h = 240, .data_size = 76800 * 2, .data = tile000_map, }; |
3.把檔案切割成animation2.h和animation2.c
animation2.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #pragma once #include <Arduino.h> #ifdef __cplusplus extern "C" { #endif extern const uint8_t animation2_map[]; #ifdef __cplusplus } #endif static const uint16_t ANIM2_W = 320; static const uint16_t ANIM2_H = 240; static const uint32_t ANIM2_SIZE = (uint32_t)ANIM2_W * (uint32_t)ANIM2_H * 2u; |
1 2 3 4 | #include <stdint.h> const uint8_t animation2_map[] = { /*圖檔資料太, 省略*/ } |
4. arduino主檔程式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /* ESP32 + Adafruit_ST7789(240x320) 顯示 animation2.c 的 RGB565 圖 (320x240) TFT pins (你前面驗證可用那組): MOSI=19, SCLK=18, CS=5, DC=16, RST=23 重要: - tft.setRotation(1) 讓螢幕座標變成 320x240,剛好完整顯示 - animation2.c 需移除底部 lv_image_dsc_t descriptor(只留 animation2_map 陣列) */ #include <Arduino.h> #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ST7789.h> #include "animation2.h" // extern animation2_map + W/H // ===== TFT pins ===== #define TFT_MOSI 19 #define TFT_SCLK 18 #define TFT_CS 5 #define TFT_DC 16 #define TFT_RST 23 Adafruit_ST7789 tft(TFT_CS, TFT_DC, TFT_RST); // 320 像素一行的暫存(RAM 640 bytes) static uint16_t lineBuf[ANIM2_W]; // 你的 animation2.c 是 RGB565 的 bytes // 多數 LVGL 匯出 RGB565 會是 little-endian:低位元組在前 // 若你顏色不對(例如整體偏紫/偏綠),把這個改成 0 試試 static const bool SOURCE_IS_LITTLE_ENDIAN = true; static inline uint16_t read565(const uint8_t *p) { if (SOURCE_IS_LITTLE_ENDIAN) { return (uint16_t)p[0] | ((uint16_t)p[1] << 8); } else { return ((uint16_t)p[0] << 8) | (uint16_t)p[1]; } } void drawRGB565_320x240(const uint8_t *dataBytes) { // dataBytes 長度必須 = 320*240*2 = 153600 tft.startWrite(); tft.setAddrWindow(0, 0, ANIM2_W, ANIM2_H); const uint32_t rowBytes = (uint32_t)ANIM2_W * 2u; for (uint16_t y = 0; y < ANIM2_H; y++) { const uint8_t *row = dataBytes + (uint32_t)y * rowBytes; for (uint16_t x = 0; x < ANIM2_W; x++) { lineBuf[x] = read565(row + (uint32_t)x * 2u); } // 一次推一行 // Adafruit_ST7789(Adafruit_SPITFT) 提供 writePixels tft.writePixels(lineBuf, ANIM2_W, true); } tft.endWrite(); } void setup() { Serial.begin(115200); delay(200); // 用你穩定的 SPI begin(Adafruit_ST7789 會使用預設 SPI instance) SPI.begin(TFT_SCLK, -1, TFT_MOSI, TFT_CS); tft.init(240, 320); tft.setRotation(1); // 變成 320x240 tft.fillScreen(ST77XX_BLACK); Serial.printf("TFT size: %d x %d\n", tft.width(), tft.height()); Serial.printf("Expect: %u bytes\n", (unsigned)ANIM2_SIZE); // 顯示一次 drawRGB565_320x240(animation2_map); // 顯示文字提示 tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.setCursor(8, 8); tft.print("animation2.c RGB565"); } void loop() { // 你這份 animation2.c 只有單張圖,所以 loop 不會動 delay(1000); } |
沒有留言:
張貼留言