Wio Terminal LCD 中文显示

虽然在 Wio Terminal LCD 字体格式 中,我们学习了如何在 Wio Terminal 上显示不同格式的文本。但由于 Wio Terminal 并没有提供中文显示的支持,因此需要我们自己来实现。

本文介绍如何使用中文字模提取(Bitmap fonts)的方式,实现在 Wio-Terminal 的 LCD 液晶显示屏上显示中文内容。

字模提取

所谓的“字模提取”,就是把一个中文字体按照位图的组合方式提取像素的排列顺序。可以参考 字体取模软件 下载安装一款适合你的开发环境的软件,然后输入我们想要的中文,转换成十六进制的数组。

  • 默认一个文字的大小为 16×16 像素,可以根据需要进行调整。
  • 输出格式通常有 C51 和 A51 两种格式,对应 C 语言和 ASM 汇编语言,我们这里选择“C51”格式。
  • 取模方式通常有横向取模和纵向取模两种,对应文字排列成图像时的排列顺序,我们这里选择“纵向取模”。
  • 另外,还要注意字节倒序的问题,即一组像素在一个字节内的存储顺序,我们这里选择“不倒序”。

例如,输入“人人都懂物联网”,生成的数据如下:

/*--  文字:  人  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x30,0xC0,0x00,0x00,0x00,0xC0,0x30,0x08,0x04,0x02,0x01,0x00,

/*--  文字:  人  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x30,0xC0,0x00,0x00,0x00,0xC0,0x30,0x08,0x04,0x02,0x01,0x00,

/*--  文字:  都  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x04,0x24,0x24,0x25,0xFE,0x24,0x2C,0x14,0x64,0x04,0x7F,0x40,0x44,0x5B,0x60,0x00,
0x20,0x40,0xFF,0x92,0x92,0x92,0x92,0xFF,0x00,0x00,0xFF,0x10,0x08,0x10,0xE0,0x00,

/*--  文字:  懂  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x07,0x00,0xFF,0x08,0x04,0x44,0x55,0xF5,0x55,0x5F,0x55,0xF5,0x55,0x44,0x40,0x00,
0x80,0x00,0xFF,0x00,0x01,0x05,0xF5,0x55,0x55,0xFF,0x55,0x55,0xF5,0x05,0x01,0x00,

/*--  文字:  物  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x02,0x3C,0x08,0xFF,0x08,0x08,0x04,0x08,0xF1,0x1E,0x10,0x1F,0x10,0x1F,0x00,0x00,
0x40,0x60,0x40,0xFF,0x80,0x80,0x20,0x42,0x84,0x18,0x62,0x81,0x02,0xFC,0x00,0x00,

/*--  文字:  联  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x7F,0x49,0x49,0x7F,0x40,0x00,0x08,0x88,0x68,0x0F,0x28,0xC8,0x08,0x00,0x00,
0x08,0xF8,0x10,0x10,0xFF,0x20,0x81,0x82,0x8C,0xB0,0xC0,0xB0,0x8C,0x82,0x81,0x00,

/*--  文字:  网  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x7F,0x40,0x44,0x42,0x41,0x4E,0x40,0x44,0x42,0x41,0x4E,0x40,0x7F,0x00,0x00,
0x00,0xFF,0x08,0x10,0x60,0x80,0x70,0x08,0x10,0x60,0x80,0x72,0x01,0xFE,0x00,0x00,

绘制像素

有了像素点阵,接下来就是将它们描绘出来。可以利用位移运算符获取每一个像素内容,然后调用 LCD 库的 drawPixel() 函数将其绘制出来。大致代码如下:

for (i=0; i<8; i++) {
    if (w & 0x80) tft.drawPixel(x+t, y+i, color);
    w = w << 1;
}

完整代码

#include "TFT_eSPI.h"
#include "Free_Fonts.h"

TFT_eSPI tft;

unsigned char Words[]={
/*--  文字:  人  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x30,0xC0,0x00,0x00,0x00,0xC0,0x30,0x08,0x04,0x02,0x01,0x00,

/*--  文字:  人  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x30,0xC0,0x00,0x00,0x00,0xC0,0x30,0x08,0x04,0x02,0x01,0x00,

/*--  文字:  都  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x04,0x24,0x24,0x25,0xFE,0x24,0x2C,0x14,0x64,0x04,0x7F,0x40,0x44,0x5B,0x60,0x00,
0x20,0x40,0xFF,0x92,0x92,0x92,0x92,0xFF,0x00,0x00,0xFF,0x10,0x08,0x10,0xE0,0x00,

/*--  文字:  懂  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x07,0x00,0xFF,0x08,0x04,0x44,0x55,0xF5,0x55,0x5F,0x55,0xF5,0x55,0x44,0x40,0x00,
0x80,0x00,0xFF,0x00,0x01,0x05,0xF5,0x55,0x55,0xFF,0x55,0x55,0xF5,0x05,0x01,0x00,

/*--  文字:  物  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x02,0x3C,0x08,0xFF,0x08,0x08,0x04,0x08,0xF1,0x1E,0x10,0x1F,0x10,0x1F,0x00,0x00,
0x40,0x60,0x40,0xFF,0x80,0x80,0x20,0x42,0x84,0x18,0x62,0x81,0x02,0xFC,0x00,0x00,

/*--  文字:  联  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x7F,0x49,0x49,0x7F,0x40,0x00,0x08,0x88,0x68,0x0F,0x28,0xC8,0x08,0x00,0x00,
0x08,0xF8,0x10,0x10,0xFF,0x20,0x81,0x82,0x8C,0xB0,0xC0,0xB0,0x8C,0x82,0x81,0x00,

/*--  文字:  网  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x7F,0x40,0x44,0x42,0x41,0x4E,0x40,0x44,0x42,0x41,0x4E,0x40,0x7F,0x00,0x00,
0x00,0xFF,0x08,0x10,0x60,0x80,0x70,0x08,0x10,0x60,0x80,0x72,0x01,0xFE,0x00,0x00,
};

void ShowChinese(unsigned char x, unsigned char y, unsigned int index, unsigned int color)
{
    unsigned char t, i, addr = 0;
    unsigned char w = 0;

    for (t=0; t<16; t++) {

        w = Words[32 * index + t];

        for (i=0; i<8; i++) {
            if (w & 0x80) tft.drawPixel(x+t, y+i, color);
            w = w << 1;
        }
    }

    y = y + 8;

    for (t=0; t<16; t++) {

        w = Words[32 * index + t + 16];

        for (i=0; i<8; i++) {
            if (w & 0x80) tft.drawPixel(x+t, y+i, color);
            w = w << 1;
        }
    }
}

void setup()
{
    Serial.begin(115200);
    tft.begin();
    tft.setRotation(3);
    tft.fillScreen(TFT_BLACK);
    ShowChinese(90,  100, 0, TFT_RED);
    ShowChinese(110, 100, 1, TFT_ORANGE);
    ShowChinese(130, 100, 2, TFT_YELLOW);
    ShowChinese(150, 100, 3, TFT_GREEN);
    ShowChinese(170, 100, 4, TFT_BLUE);
    ShowChinese(190, 100, 5, TFT_CYAN);
    ShowChinese(210, 100, 6, TFT_MAGENTA);

    tft.setFreeFont(FM9);
    tft.setCursor((320 - tft.textWidth("www.getiot.tech"))/2, 150);
    tft.print("www.getiot.tech");
}

void loop() {}

GitHub 仓库:displayChinese

Leave a Reply