esp32驱动带字库芯片TFT屏幕
#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() {}