網(wǎng)站創(chuàng)建風(fēng)格網(wǎng)站優(yōu)化排名哪家性價比高
前言
學(xué)習(xí)esp32單片機開發(fā),前段時間在網(wǎng)上買了一塊2.0寸TFT屏幕。
長這個樣子,這個屏幕帶漢字字庫的硬件模塊。我仔細(xì)看了一下這個字庫模塊上面寫的字是25Q32FVSIG 1336
![]() | ![]() |
---|
文檔
賣家也發(fā)來了開發(fā)文檔,是個doc文檔,張這個樣子。
開發(fā)準(zhǔn)備
下面開始根據(jù)文檔進(jìn)行開發(fā),調(diào)用這個字庫文件內(nèi)的漢字,并且把它顯示出來。
這個是我的接線,沒有走硬件spi,這樣直接插上去,就免去了接線線。
引腳對應(yīng)
ST7789_GND GND
ST7789_VCC 15 VCC
ST7789_SCL 2 (SCLK)
ST7789_SDA 4 (MOSI)
ST7789_SDO 16 (MISO)
ST7789_RST 17
ST7789_DC 5
ST7789_CS 18
ST7789_CSF 19
ST7789_BLK 21 VCC
創(chuàng)建工程 PlatformIO工程
配置和引用
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps = bodmer/TFT_eSPI@^2.5.43tikaflow/UTF8ToGB2312@^1.1.52
1.引入TFT_eSPI.h 下載地址:https://github.com/Bodmer/TFT_eSPI
2.在User_Setup.h中放開注釋: #define TFT_WIDTH 240放開注釋: #define TFT_HEIGHT 320放開注釋: #define ST7789_DRIVER 注釋掉:默認(rèn)的#define ILI9341_DRIVER#define TFT_MOSI 4
#define TFT_SCLK 2
#define TFT_CS 18 // Chip select control pin
#define TFT_DC 5 // Data Command control pin
#define TFT_RST 17 // Reset pin (could connect to RST pin)
#define TFT_BL 21 // LED back-light
源碼實現(xiàn)
根據(jù)上面文檔,實現(xiàn)讀取模塊中漢字并且渲染到屏幕上。下面是源碼
main.cpp
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include "UTF8ToGB2312.h"
TFT_eSPI tft;
// 字庫芯片引腳
#define FLASH_CS 19
#define FLASH_MISO 16// 字庫結(jié)構(gòu)體
struct FontInfo {uint8_t fontSize; // 字號uint32_t byteSize; // 字庫占用字節(jié)數(shù) 實際占用是 byteSize * fontSizeuint32_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);
}// 讀取字庫數(shù)據(jù)
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);}}}}
}// 顯示字符串 (兼容漢字、英文字符和數(shù)字)
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 GB2312const 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, "CSDN關(guān)注:雨季余靜", TFT_GREEN, 26);
}void loop() {}
最終效果如下
總結(jié)
雖然源碼沒多少行,但是真的折騰了我一整天。
主要是這模塊是gb2312的字庫,然而程序代碼中的漢字是UTF-8漢字。顯示出來就是亂碼,開始我還以為是我弄錯了,后來才發(fā)現(xiàn)代碼中的文字是UTF-8編碼。引入了UTF8ToGB2312.h 問題就迎刃而解了。
如果解決了你的問題希望給個關(guān)注,謝謝。