使用U8G2库调用GT20L16S1Y字库芯片显示中文字符(Arduino)

来源:Freak嵌入式 嵌入式开发 2 次阅读
摘要:手中有一块LCD显示屏上自带GT20L16S1Y字库芯片,索性拿来试一下该字库芯片的使用。 GT20L16S1Y字库芯片比较常用,是16*16点阵的汉字库芯片,支持GB2312国标简体汉字,排列格式为竖置横排。 使用U8G2库调用字库芯片,会更加方便一点,把调试通过的Arduino代码记录一下。接线方面字库芯片和LCD屏共用SPI接口,以CS引脚控制数据传输。以下是手册中引脚说明。

手中有一块LCD显示屏上自带GT20L16S1Y字库芯片,索性拿来试一下该字库芯片的使用。

Image

GT20L16S1Y字库芯片比较常用,是16*16点阵的汉字库芯片,支持GB2312国标简体汉字,排列格式为竖置横排。

Image

使用U8G2库调用字库芯片,会更加方便一点,把调试通过的Arduino代码记录一下。接线方面字库芯片和LCD屏共用SPI接口,以CS引脚控制数据传输。以下是手册中引脚说明。

示例代码如下。

#include<Arduino.h>#include<U8g2lib.h>#include<SPI.h>// --- 硬件定义 ---#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);// 汉字点阵缓冲区 (16x16点阵 = 32字节)uint8_t fontBuffer[32];// 英文字符点阵缓冲8*16uint8_t asciiBuffer[16];voidsetup(){// 初始化串口 (调试用)  Serial.begin(115200);// 初始化字库芯片引脚pinMode(PIN_FONT_CS, OUTPUT);digitalWrite(PIN_FONT_CS, HIGH); // 默认拉高,取消选中// 初始化 SPI  SPI.begin();// 初始化屏幕  u8g2.begin();}// 从GT20L16S1Y读取16x16汉字点阵数据voidreadFontData(uint8_t msb, uint8_t lsb, uint8_t *buffer){unsignedlong address;// GT20L16S1Y GB2312 地址计算公式:// BaseAddr + ((MSB - 0xB0) * 94 + (LSB - 0xA1)) * 32if (msb >= 0xA1 && msb <= 0xA3 && lsb >= 0xA1) {     address = ((unsignedlong)(msb - 0xA1) * 94 + (lsb - 0xA1)) * 32;  } elseif (msb >= 0xB0 && msb <= 0xF7 && lsb >= 0xA1) {     address = ((unsignedlong)(msb - 0xB0) * 94 + (lsb - 0xA1) + 846) * 32;  } elseif (msb == 0xA9 && lsb >= 0xA1) {     address = (282 + (lsb - 0xA1)) * 32;   } else {     address = 0;   }// 开始SPI事务读取字库  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // GT20L16S1Y支持高达30MHz+digitalWrite(PIN_FONT_CS, LOW);// 发送读取命令 0x03  SPI.transfer(0x03);// 发送地址 (24位地址,高位在前)  SPI.transfer((address >> 16) & 0xFF);  SPI.transfer((address >> 8) & 0xFF);  SPI.transfer(address & 0xFF);// 读取32个字节的点阵数据for (int i = 0; i < 32; i++) {    buffer[i] = SPI.transfer(0x00);  }digitalWrite(PIN_FONT_CS, HIGH);  SPI.endTransaction();}// 从GT20L16S1Y读取ASCII8x16点阵数据voidreadASCIIData(uint8_t asciichar, uint8_t *buffer){unsignedlong address = (asciichar-0x20)*16 + 0x3cf80;// 开始SPI事务读取字库  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // GT20L16S1Y支持高达30MHz+digitalWrite(PIN_FONT_CS, LOW);// 发送读取命令 0x03  SPI.transfer(0x03);// 发送地址 (24位地址,高位在前)  SPI.transfer((address >> 16) & 0xFF);  SPI.transfer((address >> 8) & 0xFF);  SPI.transfer(address & 0xFF);// 读取32个字节的点阵数据for (int i = 0; i < 16; i++) {    buffer[i] = SPI.transfer(0x00);  }digitalWrite(PIN_FONT_CS, HIGH);  SPI.endTransaction();}// 手动打点绘制汉字voiddrawChineseChar(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)) {// 根据具体的排列方式计算 x, y         u8g2.drawPixel(x + (i % 16) , y + (i / 16) * 8 + bit);        }    }  }}// 手动打点绘制ascii字符voiddrawASCIIChar(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)) {// 根据具体的排列方式计算 x, y        u8g2.drawPixel(x + (i % 8) , y + (i / 8) * 8 + bit);       }    }  }}voiddrawExternalFontString(int x, int y, constuint8_t *str){int cursorX = x;while (*str) {if (*str < 128) {// ASCII// 英文字体向下压2个像素,与汉字基本取齐。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;    }  }}voidloop(){  u8g2.firstPage();do {// 由于 Arduino IDE 是 UTF-8,我们不能直接写 "你好World"。// 我们需要用 16进制 来表示 GB2312 编码。constuint8_t textCN[] = {0xB5, 0xB7, 0xB9, 0xC4, 0xD2, 0xD7, 0xD7, 0xE5, 0x00}; //捣鼓易族constuint8_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);}

运行效果如下。

评论区

登录后即可参与讨论

立即登录