减少用于 3.5" TFT 显示器和 Arduino 的 KeDei TFT 库所需的内存

reducing memory required for KeDei TFT library used with 3.5" TFT display with Arduino

我需要减少 KeDei TFT library used with the Osoyoo 3.5" TFT touch screen display shield for Arduino Uno and ATmega 2560 所需的内存。当我尝试编写一个使用 TFT 显示器和 KeDei 库的简单 Arduino 应用程序时,Arduino 上的大部分可用内存都被库本身占用了。

不幸的是,我发现虽然 ATmega 2560 确实具有必要的内存量,但当 TFT 显示器与该设备一起使用时,KeDei TFT 库无法提供正确的触摸坐标,因此 ATmega 2560 不可行,除非 Osoyoo客户支持附带解决方案。

调查库源代码,我在文件 KeDei_font.cpp 中发现一个位图字体 table 用于生成显示的字符。此位图字体 table 是一个数组,unsigned char font16_B[96][16] 并且似乎是主内存占用。该数组包含从 space 字符 0x20 到波浪字符 0x7e.

的 ASCII 字符的位图字体

我做过的一件事是通过消除小写字母并将小写字母转换为大写字母来减少字符数。这导致 table const unsigned char font16_B[59][16] 比原始 table.

的一半多一点

通过这种方法,我还消除了一些其他标点符号类型的字符,但只要我只显示字母数字字符和 spaces,这就可以了。

#if defined(SMALLER_FONT_TABLE)
    static const unsigned char font16_B[59][16] = {
#else
    static const unsigned char font16_B[95][16] = {
#endif
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
            {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x38,0x38,0x00,0x00},/*"!",1*/
            {0x00,0xD8,0xFC,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
            {0x00,0x00,0x00,0x6C,0x6C,0x6C,0xFF,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x00,0x00},/*"#",3*/
            {0x00,0x00,0x18,0x3C,0x7E,0x7E,0x1E,0x1C,0x38,0x78,0x78,0x7E,0x7E,0x3C,0x18,0x18},/*"$",4*/
            {0x00,0x00,0x00,0x66,0x6F,0x3F,0x3F,0x3F,0x7E,0xF8,0xFC,0xFC,0xFC,0x66,0x00,0x00},/*"%",5*/
            {0x00,0x00,0x00,0x1C,0x36,0x36,0x36,0x1E,0xFE,0x6F,0x7B,0x33,0xB3,0xFE,0x00,0x00},/*"&",6*/
            {0x00,0x0E,0x0E,0x0C,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
            {0x00,0xC0,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x18,0x30,0x30,0x60,0xC0,0x00},/*"(",8*/
            {0x00,0x06,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x06,0x00},/*")",9*/
            {0x00,0x00,0x00,0x00,0x18,0x18,0xFF,0x3C,0x3C,0xFF,0x18,0x18,0x00,0x00,0x00,0x00},/*"*",10*/
            {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x00,0x00,0x00},/*"+",11*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0C,0x07},/*",",12*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x00,0x00},/*".",14*/
            {0x00,0x00,0x80,0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x06,0x00},/*"/",15*/
            {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00},/*"0",16*/
            {0x00,0x00,0x00,0x18,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00},/*"1",17*/
            {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x60,0x60,0x30,0x18,0x0C,0xC6,0xFE,0x00,0x00},/*"2",18*/
            {0x00,0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x60,0xC0,0xC0,0xC6,0x66,0x3C,0x00,0x00},/*"3",19*/
            {0x00,0x00,0x00,0x60,0x70,0x78,0x6C,0x6C,0x66,0x66,0xFE,0x60,0x60,0xF8,0x00,0x00},/*"4",20*/
            {0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x3E,0x6E,0xC0,0xC0,0xC6,0x66,0x3C,0x00,0x00},/*"5",21*/
            {0x00,0x00,0x00,0x78,0x6C,0x06,0x06,0x3E,0x6E,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00},/*"6",22*/
            {0x00,0x00,0x00,0xFE,0x66,0x66,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00},/*"7",23*/
            {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0xC6,0x7C,0x00,0x00},/*"8",24*/
            {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xEC,0xF8,0xC0,0xC0,0x6C,0x3C,0x00,0x00},/*"9",25*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00,0x00,0x00,0x00,0x38,0x38,0x00,0x00},/*":",26*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0C},/*";",27*/
            {0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00},/*"<",28*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00},/*"=",29*/
            {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00},/*">",30*/
            {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xC0,0x60,0x30,0x30,0x00,0x38,0x38,0x00,0x00},/*"?",31*/
            {0x00,0x00,0x00,0x3C,0x66,0xFE,0xFF,0xFF,0xFF,0xFF,0x7F,0xC6,0x66,0x3C,0x00,0x00},/*"@",32*/
            {0x00,0x00,0x00,0x18,0x18,0x38,0x3C,0x3C,0x6C,0x7C,0x66,0xC6,0xC6,0xEF,0x00,0x00},/*"A",33*/
            {0x00,0x00,0x00,0x3F,0x66,0x66,0x66,0x3E,0x66,0xC6,0xC6,0xC6,0x66,0x3F,0x00,0x00},/*"B",34*/
            {0x00,0x00,0x00,0xFC,0xC6,0xC6,0x03,0x03,0x03,0x03,0x03,0xC6,0x66,0x3C,0x00,0x00},/*"C",35*/
            {0x00,0x00,0x00,0x3F,0x66,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x66,0x3F,0x00,0x00},/*"D",36*/
            {0x00,0x00,0x00,0x7F,0xC6,0x36,0x36,0x3E,0x36,0x36,0x06,0xC6,0xC6,0x7F,0x00,0x00},/*"E",37*/
            {0x00,0x00,0x00,0x7F,0xC6,0x36,0x36,0x3E,0x36,0x36,0x06,0x06,0x06,0x0F,0x00,0x00},/*"F",38*/
            {0x00,0x00,0x00,0x7C,0x66,0x66,0x03,0x03,0x03,0xF3,0x63,0x66,0x66,0x3C,0x00,0x00},/*"G",39*/
            {0x00,0x00,0x00,0xEF,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xEF,0x00,0x00},/*"H",40*/
            {0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00},/*"I",41*/
            {0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x33,0x1F},/*"J",42*/
            {0x00,0x00,0x00,0xFF,0x66,0x36,0x1E,0x1E,0x1E,0x36,0x36,0x66,0x66,0xFF,0x00,0x00},/*"K",43*/
            {0x00,0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xC6,0xFF,0x00,0x00},/*"L",44*/
            {0x00,0x00,0x00,0xFF,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0xFF,0x00,0x00},/*"M",45*/
            {0x00,0x00,0x00,0xE7,0xCE,0xCE,0xDE,0xDE,0xF6,0xF6,0xF6,0xE6,0xE6,0xCF,0x00,0x00},/*"N",46*/
            {0x00,0x00,0x00,0x3C,0x66,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0x66,0x3C,0x00,0x00},/*"O",47*/
            {0x00,0x00,0x00,0x7F,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x06,0x0F,0x00,0x00},/*"P",48*/
            {0x00,0x00,0x00,0x3C,0x66,0xC3,0xC3,0xC3,0xC3,0xC3,0xDF,0xF7,0x76,0x3C,0xE0,0x00},/*"Q",49*/
            {0x00,0x00,0x00,0x7F,0xC6,0xC6,0xC6,0x7E,0x36,0x36,0x66,0x66,0xC6,0xCF,0x00,0x00},/*"R",50*/
            {0x00,0x00,0x00,0xFC,0xC6,0xC6,0x06,0x0C,0x38,0x60,0xC0,0xC6,0xC6,0x7E,0x00,0x00},/*"S",51*/
            {0x00,0x00,0x00,0xFF,0xDB,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00},/*"T",52*/
            {0x00,0x00,0x00,0xEF,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00},/*"U",53*/
            {0x00,0x00,0x00,0xEF,0xC6,0xC6,0x66,0x6C,0x6C,0x3C,0x3C,0x38,0x18,0x18,0x00,0x00},/*"V",54*/
            {0x00,0x00,0x00,0xFF,0xDB,0xDB,0xDB,0xDB,0xFF,0xFF,0x7E,0x66,0x66,0x66,0x00,0x00},/*"W",55*/
            {0x00,0x00,0x00,0xEF,0xC6,0x6C,0x6C,0x38,0x38,0x38,0x6C,0x6C,0xC6,0xEF,0x00,0x00},/*"X",56*/
            {0x00,0x00,0x00,0xFF,0x66,0x66,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00},/*"Y",57*/
            {0x00,0x00,0x00,0xFE,0x63,0x60,0x30,0x30,0x18,0x0C,0x0C,0xC6,0xC6,0x7F,0x00,0x00},/*"Z",58*/
#if !defined(SMALLER_FONT_TABLE)
            // In the interest of reducing the memory requirements for the TFT library, we
            // allow for the use of a smaller font table which eliminates the lower case letters
            // as well as a few symbols. See below conversion of lower case letters to upper case.
            //    Richard Chambers, 04-25-2021
            {0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00},/*"[",59*/
            {0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x30,0x30,0x60,0x60,0x60,0xC0,0xC0},/*"\",60*/
            {0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E,0x00},/*"]",61*/
            {0x00,0x78,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"_",63*/
            {0x00,0x0E,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xF8,0xCC,0xC6,0xC6,0xFC,0x00,0x00},/*"a",65*/
            {0x00,0x00,0x00,0x07,0x06,0x06,0x06,0x3E,0x6E,0xC6,0xC6,0xC6,0x6E,0x3E,0x00,0x00},/*"b",66*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xCC,0x06,0x06,0x06,0xCC,0x78,0x00,0x00},/*"c",67*/
            {0x00,0x00,0x00,0xE0,0xC0,0xC0,0xC0,0xF8,0xCC,0xC6,0xC6,0xC6,0xEC,0xF8,0x00,0x00},/*"d",68*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0x06,0x06,0xC6,0x7C,0x00,0x00},/*"e",69*/
            {0x00,0x00,0x00,0xF0,0x98,0x18,0x18,0xFE,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00},/*"f",70*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x3C,0x06,0x7C,0xC6,0xC6,0x7C},/*"g",71*/
            {0x00,0x00,0x00,0x07,0x06,0x06,0x06,0x7E,0xCE,0xC6,0xC6,0xC6,0xC6,0xEF,0x00,0x00},/*"h",72*/
            {0x00,0x00,0x00,0x1C,0x1C,0x00,0x00,0x1E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00},/*"i",73*/
            {0x00,0x00,0x00,0x70,0x70,0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x3E},/*"j",74*/
            {0x00,0x00,0x00,0x07,0x06,0x06,0x06,0xF6,0x36,0x1E,0x3E,0x36,0x66,0xFF,0x00,0x00},/*"k",75*/
            {0x00,0x00,0x00,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00},/*"l",76*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xB6,0xB6,0xB6,0xB6,0xB6,0xFF,0x00,0x00},/*"m",77*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xCE,0xC6,0xC6,0xC6,0xC6,0xEF,0x00,0x00},/*"n",78*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00},/*"o",79*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x6E,0xC6,0xC6,0xC6,0x66,0x3E,0x06,0x0F},/*"p",80*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xCC,0xC6,0xC6,0xC6,0xCC,0xF8,0xC0,0xE0},/*"q",81*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xDC,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00},/*"r",82*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xC6,0x06,0x7C,0xC0,0xC6,0x7E,0x00,0x00},/*"s",83*/
            {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0x70,0x00,0x00},/*"t",84*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xC6,0xC6,0xC6,0xC6,0xE6,0xFC,0x00,0x00},/*"u",85*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xC6,0x6C,0x6C,0x3C,0x18,0x18,0x00,0x00},/*"v",86*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xDB,0xDB,0xFF,0xFF,0x66,0x66,0x00,0x00},/*"w",87*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x38,0x38,0x38,0x6C,0xFE,0x00,0x00},/*"x",88*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xC6,0x6C,0x6C,0x3C,0x38,0x18,0x18,0x0F},/*"y",89*/
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x66,0x30,0x18,0x18,0xCC,0xFE,0x00,0x00},/*"z",90*/
            {0x00,0xC0,0x60,0x60,0x60,0x60,0x60,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x00},/*"{",91*/
            {0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30},/*"|",92*/
            {0x00,0x0E,0x18,0x18,0x18,0x18,0x18,0x30,0x18,0x18,0x18,0x18,0x18,0x18,0x0E,0x00},/*"}",93*/
            {0x1C,0x76,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/
#endif
        };

然后在生成字符并逐像素显示它们的函数中,如果启用较小的 table,我有以下代码将小写字符转换为大写字符。

#if defined(SMALLER_FONT_TABLE)
    // Lets translate the character to one of the printable
    // characters in our font table. What we are doing is
    // to translate lower case letters to upper case letters
    // since in order to have a smaller font table taking up
    // less memory we remove the lower case letters.
    //    Richard Chambers, 04-25-2021
    if (_data < ' ' || _data > 'z') return;
    if (_data >= 'a') _data = _data - 'a' + 'A';
#endif
    char_i=(int)_data - ' ';

使用这种方法,当我使用定义的 SMALLER_FONT_TABLE 编译我的 Arduino 草图时,编译完成并出现以下警告:

Sketch uses 12844 bytes (39%) of program storage space. Maximum is 32256 bytes.
Global variables use 1556 bytes (75%) of dynamic memory, leaving 492 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

如何进一步减少显示字体所需的内存?是否有另一种使用更少内存的位图字体?

我研究的第一种方法是对位图字体 table 使用某种压缩,例如 运行 长度编码,因为很多条目都是二进制零。我测试了这种方法,它确实减少了内存量,同时增加了一点复杂性。然而,使用我测试的简单方法,节省的内存量约为 200 字节。

我研究的第二种方法是通过首先消除小写字母然后同时更改位图字体来减小数组的大小。将位图字体从 16x16 大小的字体更改为 8x8 大小的字体会对内存使用产生显着影响。

然而,将 table 的大小从 const unsigned char font16_B[96][16] 更改为 const unsigned char font16_B[96][8] 意味着 TFT 屏幕上显示的字符会变小。

因此在使用的内存量和字符显示大小之间存在权衡。更大的显示字符需要更多内存来描述字形。

快速搜索“8 位图字体”可找到 Daniel Hepper GitHub 存储库,https://github.com/dhepper/font8x8,字体大小为 8x8,许可证为 Public 域。

使用预处理器指令 select 要使用的字体 table 并 select 从 Hepper 的 GitHub 存储库中 font8x8_basic.h 文件的一个小节,我将以下内容添加到 KeDei TFT 库中。

#if defined(USE_FONT_8_B)
#define FONT_ROW_LEN  8
#if defined(SMALLER_FONT_TABLE)
    static const unsigned char font8_B[59][8] = {
#else
    static const unsigned char font8_B[96][8] = {
#endif
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // U+0020 (space)
        { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00 },   // U+0021 (!)
        { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // U+0022 (")
        { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00 },   // U+0023 (#)
        { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00 },   // U+0024 ($)
        { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00 },   // U+0025 (%)
        { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00 },   // U+0026 (&)
        { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 },   // U+0027 (')
        { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00 },   // U+0028 (()
        { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00 },   // U+0029 ())
        { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00 },   // U+002A (*)
        { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00 },   // U+002B (+)
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06 },   // U+002C (,)
        { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 },   // U+002D (-)
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00 },   // U+002E (.)
        { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00 },   // U+002F (/)
        { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00 },   // U+0030 (0)
        { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00 },   // U+0031 (1)
        { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00 },   // U+0032 (2)
        { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00 },   // U+0033 (3)
        { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00 },   // U+0034 (4)
        { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00 },   // U+0035 (5)
        { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00 },   // U+0036 (6)
        { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00 },   // U+0037 (7)
        { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00 },   // U+0038 (8)
        { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00 },   // U+0039 (9)
        { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00 },   // U+003A (:)
        { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06 },   // U+003B (;)
        { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00 },   // U+003C (<)
        { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00 },   // U+003D (=)
        { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00 },   // U+003E (>)
        { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00 },   // U+003F (?)
        { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00 },   // U+0040 (@)
        { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00 },   // U+0041 (A)
        { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00 },   // U+0042 (B)
        { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00 },   // U+0043 (C)
        { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00 },   // U+0044 (D)
        { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00 },   // U+0045 (E)
        { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00 },   // U+0046 (F)
        { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00 },   // U+0047 (G)
        { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00 },   // U+0048 (H)
        { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 },   // U+0049 (I)
        { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00 },   // U+004A (J)
        { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00 },   // U+004B (K)
        { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00 },   // U+004C (L)
        { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00 },   // U+004D (M)
        { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00 },   // U+004E (N)
        { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00 },   // U+004F (O)
        { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00 },   // U+0050 (P)
        { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00 },   // U+0051 (Q)
        { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00 },   // U+0052 (R)
        { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00 },   // U+0053 (S)
        { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 },   // U+0054 (T)
        { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00 },   // U+0055 (U)
        { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00 },   // U+0056 (V)
        { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00 },   // U+0057 (W)
        { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00 },   // U+0058 (X)
        { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00 },   // U+0059 (Y)
        { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00 },   // U+005A (Z)
#if !defined(SMALLER_FONT_TABLE)
        // In the interest of reducing the memory requirements for the TFT library, we
        // allow for the use of a smaller font table which eliminates the lower case letters
        // as well as a few symbols. See below conversion of lower case letters to upper case.
        //    Richard Chambers, 04-25-2021
        { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00 },   // U+005B ([)
        { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00 },   // U+005C (\)
        { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00 },   // U+005D (])
        { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00 },   // U+005E (^)
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF },   // U+005F (_)
        { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 },   // U+0060 (`)
        { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00 },   // U+0061 (a)
        { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00 },   // U+0062 (b)
        { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00 },   // U+0063 (c)
        { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00 },   // U+0064 (d)
        { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00 },   // U+0065 (e)
        { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00 },   // U+0066 (f)
        { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F },   // U+0067 (g)
        { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00 },   // U+0068 (h)
        { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 },   // U+0069 (i)
        { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E },   // U+006A (j)
        { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00 },   // U+006B (k)
        { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 },   // U+006C (l)
        { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00 },   // U+006D (m)
        { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00 },   // U+006E (n)
        { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00 },   // U+006F (o)
        { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F },   // U+0070 (p)
        { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78 },   // U+0071 (q)
        { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00 },   // U+0072 (r)
        { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00 },   // U+0073 (s)
        { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00 },   // U+0074 (t)
        { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00 },   // U+0075 (u)
        { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00 },   // U+0076 (v)
        { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00 },   // U+0077 (w)
        { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00 },   // U+0078 (x)
        { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F },   // U+0079 (y)
        { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00 },   // U+007A (z)
        { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00 },   // U+007B ({)
        { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 },   // U+007C (|)
        { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00 },   // U+007D (})
        { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // U+007E (~)
#endif
    };
#else
#define FONT_ROW_LEN  16
#if defined(SMALLER_FONT_TABLE)
    static const unsigned char font16_B[59][16] = {
#else
    static const unsigned char font16_B[95][16] = {
#endif
            {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/

我还必须修改字符绘制循环,以便使用 8 列而不是 16 列。列数是一个硬编码常量,但现在由 class 变量指定 font_size 根据定义的常量 USE_FONT_8_B 是否被定义而设置为 16 或 8。

#if defined(USE_FONT_8_B)
        font_size = 8;
#else
        font_size = 16;
#endif

循环看起来像:

    for(char_m = 0; char_m < font_size; char_m++)
    {
        for(char_n = 0; char_n < 8; char_n++)
        {

#if defined(USE_FONT_8_B)
            if (font8_B[char_i][char_m] & 1 << char_n)
#else
            if(font16_B[char_i][char_m] & 1 << char_n)
#endif
            {
               TFT.set_area(now_x, now_y, ++now_x, now_y);
               TFT.w_data(font_color >> 8);
               TFT.w_data(font_color);
            }
            else
            {
              now_x++;
  
            }
         }
         now_y++;
         now_x -= 8;
    }
    now_y -= font_size;
    now_x += 8 + font_interval;

如果我打开同时使用 8x8 字体和 SMALLER_FONT_TABLE 定义,那么当我编译草图时,我会得到以下关于内存使用情况的编译器输出:

Sketch uses 12390 bytes (38%) of program storage space. Maximum is 32256 bytes.
Global variables use 1084 bytes (52%) of dynamic memory, leaving 964 bytes for local variables. Maximum is 2048 bytes.

这是连接到 Arduino Uno 的 3.5" TFT 显示器上两种不同尺寸的比较。按钮是 64 x 40 像素。

备注

我已经从 Osoyoo 的 GitHub fork 了 KeDei TFT 库源代码并开始修改源代码。叉子位于 https://github.com/RichardChambers/driver/tree/master/KeDeiTFT

其中一项更改是允许文本为双高 and/or 双宽。此图像是 scanner/scale 模拟器的当前版本,显示了双高和双宽文本以及双高文本之间的样式差异。

这张更新后的图片显示了目前预期的最终 GUI。它允许更改重量,还允许设置各种状态位以指示秤错误情况,例如容量不足。

为了支持按钮的数量,我重写了 Button class 这样我就可以拥有共享一些数据的按钮,从而为每个按钮节省大约 11 个字节。因此,这个带有八个按钮并使用数据共享功能的 GUI 节省了大约 77 字节的内存,这对 Arduino 来说是一个显着的节省。

Button class 现在派生自 ButtonShared class。 ButtonShared class 用于声明具有相同样式的相关按钮组。 ButtonShared class 包含所有按钮机制,Button 对象是一个 ButtonShared 对象,具有自己的 ButtonData 成员而不是共享 ButtonData会员.

struct ButtonData {
public:
    ButtonData(unsigned short sizeWidth = 64, unsigned short sizeHigh = 40)
    {
        //the  button size
        x_size = sizeWidth;
        y_size = sizeHigh;
        //the button  abort color
        edge_up_color = 0xffff;    // RGB565 value for white
        edge_down_color = 0x6b4d;
        button_color = 0x4898;
        font_color = 0xffff;    // RGB565 value for white
                                       //the  botton moder 0--cube_button  1--circle_button
        botton_moder = 0;
    }

    //the  button size
    unsigned char   x_size;
    unsigned char   y_size;
    //the  button  abort color
    TFTLCD::TftColor    edge_up_color;
    TFTLCD::TftColor    edge_down_color;
    TFTLCD::TftColor    button_color;
    TFTLCD::TftColor    font_color;
    //the  botton moder 0--cube_button , 1--circle_button
    bool            botton_moder;
};


class  ButtonShared
{
public:
    ButtonShared(ButtonData &buttonData) : myData(&buttonData)
    {
    }

    ButtonShared() : myData(nullptr)
    {
    }

    bool setSharedData(ButtonData &buttonData) { myData = &buttonData; return 1; }
    bool drawButton(unsigned short _x, unsigned short _y, bool _botton_moder, const char *str, Font & myFont);
    bool drawButton(TFTLCD::TftPos &p, bool _botton_moder, const char *str, Font & myFont);
    bool istouch(unsigned short _x, unsigned short _y);
    bool istouch(void);
    bool isTouchState(void);
    bool pendown(void);
    bool penup(void);
    /*if you want  to change the butom size or the color,you can use  the  follow function to achieve your purpose,
    but you  must do it before use the drawbutton() function;also  if you  always change the auto value ,you can change the button() function*/
    void resetsize(unsigned char _x_size, unsigned char _y_size);
    void resetcolor(TFTLCD::TftColor _edge_up_color, TFTLCD::TftColor _edge_down_color, TFTLCD::TftColor _button_color, TFTLCD::TftColor _font_color);

private:
    ButtonData *myData;

    // following data is unique to each button and can not be shared
    // between buttons.
    //the  position(x,y);
    unsigned short  x;
    unsigned short  y;
    unsigned char   penDownFlag;      // set by successful istouch() call or when the pendown() function is called. cleared when the penup() function is called.
};

class  Button : public ButtonShared
{
public:
    Button(unsigned short sizeWidth = 64, unsigned short sizeHigh = 40) : localData(sizeWidth, sizeHigh)
    {
        setSharedData(localData);
    }
    
private:
    ButtonData localData;
};