基于U8G2库调用GT20L16S1Y字库芯片实现中文字符显示(Arduino平台)
近期开发中涉及一块集成GT20L16S1Y字库芯片的LCD显示屏,因此决定测试其显示中文字符的能力。
GT20L16S1Y是一款广泛应用的16×16点阵中文字库芯片,支持GB2312编码体系中的简体汉字,字符点阵排列方式为竖列横排。
借助U8G2图形库调用该字库芯片,能够显著提升开发效率。以下为已通过验证的Arduino程序代码,说明GT20L16S1Y通过SPI接口与LCD屏通信的实现方式。
代码中使用片选(CS)引脚控制字库芯片与显示屏的数据通道。
#include #include #include // 硬件接口定义#define PIN_LCD_CS 7#define PIN_LCD_DC 6#define PIN_LCD_RST 11#define PIN_FONT_CS 5// U8G2库对象初始化U8G2_ST7565_NHD_C12864_1_4W_HW_SPI u8g2(U8G2_R0, PIN_LCD_CS, PIN_LCD_DC, PIN_LCD_RST);// 中文字符点阵缓冲区uint8_t fontBuffer[32];// 英文字符点阵缓冲区uint8_t asciiBuffer[16];void setup() { Serial.begin(115200); pinMode(PIN_FONT_CS, OUTPUT); digitalWrite(PIN_FONT_CS, HIGH); SPI.begin(); u8g2.begin();}// 从GT20L16S1Y读取16x16中文点阵数据void readFontData(uint8_t msb, uint8_t lsb, uint8_t *buffer) { unsigned long address; // 字符在芯片中的地址计算 if (msb >= 0xA1 && msb <= 0xA3 && lsb >= 0xA1) { address = ((msb - 0xA1) * 94 + (lsb - 0xA1)) * 32; } else if (msb >= 0xB0 && msb <= 0xF7 && lsb >= 0xA1) { address = ((msb - 0xB0) * 94 + (lsb - 0xA1) + 846) * 32; } else if (msb == 0xA9 && lsb >= 0xA1) { address = (282 + (lsb - 0xA1)) * 32; } else { address = 0; } SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); digitalWrite(PIN_FONT_CS, LOW); SPI.transfer(0x03); SPI.transfer((address >> 16) & 0xFF); SPI.transfer((address >> 8) & 0xFF); SPI.transfer(address & 0xFF); for (int i = 0; i < 32; i++) { buffer[i] = SPI.transfer(0x00); } digitalWrite(PIN_FONT_CS, HIGH); SPI.endTransaction();}// 从GT20L16S1Y读取ASCII字符点阵数据void readASCIIData(uint8_t asciichar, uint8_t *buffer) { unsigned long address = (asciichar - 0x20) * 16 + 0x3cf80; SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); digitalWrite(PIN_FONT_CS, LOW); SPI.transfer(0x03); SPI.transfer((address >> 16) & 0xFF); SPI.transfer((address >> 8) & 0xFF); SPI.transfer(address & 0xFF); for (int i = 0; i < 16; i++) { buffer[i] = SPI.transfer(0x00); } digitalWrite(PIN_FONT_CS, HIGH); SPI.endTransaction();}// 绘制中文字符void drawChineseChar(int x, int y, uint8_t msb, uint8_t lsb) { readFontData(msb, lsb, fontBuffer); for (int i = 0; i < 32; i++) { uint8_t byteData = fontBuffer[i]; for (int bit = 0; bit < 8; bit++) { if (byteData & (0x01 << bit)) { u8g2.drawPixel(x + (i % 16), y + (i / 16) * 8 + bit); } } }}// 绘制ASCII字符void drawASCIIChar(int x, int y, uint8_t asciichar) { readASCIIData(asciichar, asciiBuffer); for (int i = 0; i < 16; i++) { uint8_t byteData = asciiBuffer[i]; for (int bit = 0; bit < 8; bit++) { if (byteData & (0x01 << bit)) { u8g2.drawPixel(x + (i % 8), y + (i / 8) * 8 + bit); } } }}// 绘制包含中英文的字符串void drawExternalFontString(int x, int y, const uint8_t *str) { int cursorX = x; while (*str) { if (*str < 128) { drawASCIIChar(cursorX, y + 2, *str); cursorX += 8; str++; } else { uint8_t msb = *str; uint8_t lsb = *(str + 1); if (lsb == 0) break; drawChineseChar(cursorX, y, msb, lsb); cursorX += 16; str += 2; } }}void loop() { u8g2.firstPage(); do { const uint8_t textCN[] = {0xB5, 0xB7, 0xB9, 0xC4, 0xD2, 0xD7, 0xD7, 0xE5, 0x00}; // “捣鼓易族” const uint8_t textMix[] = {'H', 'e', 'l', 'l', 'o', 0xCA, 0xC0, 0xBD, 0xE7, 0xA1, 0xA3, 0x00}; // “Hello世界” drawExternalFontString(0, 0, textCN); drawExternalFontString(0, 20, textMix); } while (u8g2.nextPage()); delay(1000);} 程序运行后显示效果如下。