esp32驱动带字库芯片TFT屏幕

时间:2025-03-07 17:34:27
#include <Arduino.h> #include <TFT_eSPI.h> #include <SPI.h> #include "UTF8ToGB2312.h" TFT_eSPI tft; // 字库芯片引脚 #define FLASH_CS 19 #define FLASH_MISO 16 // 字库结构体 struct FontInfo { uint8_t fontSize; // 字号 uint32_t byteSize; // 字库占用字节数 实际占用是 byteSize * fontSize uint32_t addr; // 字库偏移地址 }; // ASCII 字库信息 const FontInfo ASCII_FONTS[] = { {12, 1, 0X1000L}, // 6x12 {14, 1, 0X1600L}, // 7x14 {16, 1, 0X1D00L}, // 8x16 {18, 2, 0X2500L}, // 9x18 {20, 2, 0X3700L}, // 10x20 {22, 2, 0X4B00L}, // 11x22 {24, 2, 0X6100L}, // 12x24 {26, 2, 0X7900L} // 13x26 }; // GB2312 字库信息 const FontInfo GB2312_FONTS[] = { {12, 2, 0X9300L}, // 12x12 {14, 2, 0X39300L}, // 14x14 {16, 2, 0X71300L}, // 16x16 {18, 3, 0XB1300L}, // 18x18 {20, 3, 0X11D300L}, // 20x20 {22, 3, 0X195300L}, // 22x22 {24, 3, 0X219300L}, // 24x24 {26, 4, 0X2A9300L} // 26x26 }; // 初始化 SPI Flash void initFlash() { pinMode(FLASH_CS, OUTPUT); digitalWrite(FLASH_CS, HIGH); SPI.begin(TFT_SCLK, FLASH_MISO, TFT_MOSI, FLASH_CS); SPI.setFrequency(1000000); SPI.setDataMode(SPI_MODE0); } // 读取字库数据 uint8_t readFontData(uint32_t addr) { uint8_t data; digitalWrite(FLASH_CS, LOW); SPI.transfer(0x03); SPI.transfer((addr >> 16) & 0xFF); SPI.transfer((addr >> 8) & 0xFF); SPI.transfer(addr & 0xFF); data = SPI.transfer(0x00); digitalWrite(FLASH_CS, HIGH); return data; } // 显示一个汉字 (GB2312) void drawGB2312Char(uint16_t x, uint16_t y, uint16_t ch, uint16_t color, uint8_t fontSize) { if (fontSize < 12 || fontSize > 26 || (fontSize % 2) != 0) { return; // 无效的字体大小 } const FontInfo& fontInfo = GB2312_FONTS[(fontSize - 12) / 2]; uint32_t fontAddr = fontInfo.addr + (((ch >> 8) - 0xA1) * 94 + (ch & 0xFF) - 0xA1) * fontInfo.fontSize * fontInfo.byteSize; for (uint16_t i = 0; i < fontInfo.fontSize; i++) { for (uint16_t j = 0; j < fontInfo.byteSize; j++) { uint8_t data = readFontData(fontAddr + i * fontInfo.byteSize + j); for (uint8_t k = 0; k < 8; k++) { if (data & (0x80 >> k)) { tft.drawPixel(x + j * 8 + k, y + i, color); } } } } } // 显示一个 ASCII 字符 void drawASCIIChar(uint16_t x, uint16_t y, uint8_t ch, uint16_t color, uint8_t fontSize) { if (fontSize < 12 || fontSize > 26 || (fontSize % 2) != 0) { return; // 无效的字体大小 } const FontInfo& fontInfo = ASCII_FONTS[(fontSize - 12) / 2]; uint32_t fontAddr = fontInfo.addr + ch * fontInfo.byteSize * fontInfo.fontSize; for (uint16_t i = 0; i < fontInfo.fontSize; i++) { for (uint16_t j = 0; j < fontInfo.byteSize; j++) { uint8_t data = readFontData(fontAddr + i * fontInfo.byteSize + j); for (uint8_t k = 0; k < 8; k++) { if (data & (0x80 >> k)) { tft.drawPixel(x + j * 8 + k, y + i, color); } } } } } // 显示字符串 (兼容汉字、英文字符和数字) void drawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint8_t fontSize = 16) { String gbStr = GB.get(str); // UTF-8 to GB2312 const char *gbCharPtr = gbStr.c_str(); uint16_t xPos = x; while (*gbCharPtr) { uint8_t ch = (uint8_t)gbCharPtr[0]; if (ch >= 0xA1) { // 汉字 uint16_t gbCh = (ch << 8) | (uint8_t)gbCharPtr[1]; drawGB2312Char(xPos, y, gbCh, color, fontSize); xPos += fontSize; gbCharPtr += 2; } else if (ch >= 32 && ch <= 126) { // ASCII 字符 drawASCIIChar(xPos, y, ch, color, fontSize); gbCharPtr++; xPos += fontSize / 2; } else { // 其他字符或错误处理 gbCharPtr++; // 跳过未知字符 } } } void setup() { Serial.begin(115200); pinMode(15, OUTPUT); pinMode(21, OUTPUT); digitalWrite(15, HIGH); digitalWrite(21, HIGH); tft.init(); tft.fillScreen(TFT_BLACK); initFlash(); drawString(0, 0, "12号:你好,世界!123abc", TFT_GREEN, 12); drawString(0, 12, "14号:你好,世界!123abc", TFT_GREEN, 14); drawString(0, 26, "16号:你好,世界!123abc", TFT_GREEN, 16); drawString(0, 42, "18号:你好,世界!123abc", TFT_GREEN, 18); drawString(0, 60, "20号:你好,世界!123abc", TFT_GREEN, 20); drawString(0, 80, "22号:你好,世界!123abc", TFT_GREEN, 22); drawString(0, 102, "24号:你好,世界!123abc", TFT_GREEN, 24); drawString(0, 126, "26号:你好,世界!123abc", TFT_GREEN, 26); drawString(0, 180, "****关注:雨季余静", TFT_GREEN, 26); } void loop() {}