Русский шрифт для LCD AM-480272H3TMQW-T01H |
Добавил(а) microsin |
На плате разработчика STM32429I-EVAL1 (MB1045 Rev.B) установлен цветной WQVGA TFT LCD 4.3" типа AM-480272H3TMQW-T01H от компании Ampire, с разрешением 480x272 точек. В пакете библиотек STM32Cube_FW_F4_V1.24.0 есть отличные примеры для работы с этим индикатором, они запускаются без каких-либо модификаций. Но выводить можно только английские символы ASCII с кодами в диапазоне от 0x20 до 0x7E, русские символы не не поддерживаются. В этой статье описывается русификация вывода текста в 8-битной кодировке ANSI (или ASCII Windows-1251) на LCD индикатор платы STM32429I-EVAL1. Вывод русифицированный вывод на LCD был реализован в демонстрационном проекте веб-сервера LwIP_HTTP_Server_Socket_RTOS (находится в каталоге Projects\STM324x9I_EVAL\Applications\LwIP\ пакета библиотек STM32Cube). Но можно взять любой другой пример проекта STM324x9I_EVAL, где используется вывод на LCD-индикатор (почти все примеры это используют). На фотографии ниже показана попытка вывода на индикатор всей таблицы ASCII с использованием нерусифицированной версии библиотеки. Если Вы используете IAR (я экспериментировал с IAR 8.30 под 64-битной Windows 10), то для однобайтной кодировки русского текста ANSI проверьте настройку редактора кода. К однобайтной кодировке в IAR можно перейти только если установить в Tools -> Options... -> Editor -> Default Character encoding: System, и все файлы кода с русскими комментариями и строками сохранять в кодировке ANSI (ASCII-Windows1251). К сожалению, в IAR 8.30 при этом нельзя вводить в редакторе кода русские буквы - они заменяются знаками ?. Ввод русского текста надо делать во внешнем редакторе, например в notepad2 или notepad++. Вводить русский текст можно только если перейти на кодировку текста UTF-8 (двухбайтная кодирование русских символов), но тогда значительно усложняется программная обработка текста. Вывод на LCD в примерах реализован через перенаправление символов printf в функцию int fputc(int ch, FILE *f). На фунцию fputc указывает макрос LCD_LOG_PUTCHAR, который находится в модуле lcd_log.c. Функция LCD_LOG_PUTCHAR просто кладет символы в LCD_CacheBuffer, реализованный как массив строк. Растеризация и вывод на экран происходит в BSP_LCD_DisplayStringAtLine -> BSP_LCD_DisplayStringAt -> BSP_LCD_DisplayChar -> DrawChar. В функции BSP_LCD_DisplayChar надо делать перекодировку кода символа. В основную (среднюю) консоль LCD символы выводятся шрифтом Font12 (графика символов находится в Font12_Table). Всего в этой графической таблице 95 символов, от символа пробела (код 0x20) до символа ~ (0x7E). К этой таблице можно добавить в конец графику тех русских символов, начертание которых не совпадает с латинскими, а графику совпадающих по внешнему виду символов (таких как А, В, Е, К, М, О и т. п.) для экономии памяти можно брать из существующей таблицы латиницы. Для перекодировки потребуется дополнительная таблица ANSI_rus_decode_table, в который будут храниться индексы блоков графики символов. Начальный индекс (первый байт в этой таблице) соответствует коду символа - 0xA0. Код в таблице дает индекс начала графики в Font12_Table, т. е. новый код символа. const uint8_t ANSI_rus_decode_table [] = { 0x41, // A, по начертанию выглядит как русская А 0x20+95, // русская Б, первая в пользовательской таблице 0x42, // B, по начертанию выглядит как русская В 0x20+96, // русская Г 0x20+97, // русская Д 0x45, // E, по начертанию выглядит как русская Е 0x20+98, // русская Ж 0x33, // 3, по начертанию выглядит как русская З 0x20+99, // русская И 0x20+100, // русская Й 0x4B, // K, по начертанию выглядит как русская К 0x20+101, // русская Л 0x4D, // M, по начертанию выглядит как русская М 0x48, // H, по начертанию выглядит как русская Н 0x4F, // O, по начертанию выглядит как русская О 0x20+102, // русская П 0x50, // P, по начертанию выглядит как русская Р 0x43, // C, по начертанию выглядит как русская С 0x54, // T, по начертанию выглядит как русская Т 0x20+103, // русская У 0x20+104, // русская Ф 0x58, // X, по начертанию выглядит как русская Х 0x20+105, // русская Ц 0x20+106, // русская Ч 0x20+107, // русская Ш 0x20+108, // русская Щ 0x20+109, // русская Ъ 0x20+110, // русская Ы 0x20+111, // русская Ь 0x20+112, // русская Э 0x20+113, // русская Ю 0x20+114, // русская Я 0x61, // a, по начертанию выглядит как русская а 0x20+115, // русская б 0x20+116, // русская в 0x20+117, // русская г 0x20+118, // русская д 0x65, // e, по начертанию выглядит как русская е 0x20+119, // русская ж 0x20+120, // русская з 0x20+121, // русская и 0x20+122, // русская й 0x20+123, // русская к 0x20+124, // русская л 0x20+125, // русская м 0x20+126, // русская н 0x6F, // o, по начертанию выглядит как русская о 0x20+127, // русская п 0x70, // p, по начертанию выглядит как русская р 0x63, // c, по начертанию выглядит как русская с 0x20+128, // русская т 0x20+129, // русская у 0x20+130, // русская ф 0x78, // x, по начертанию выглядит как русская х 0x20+131, // русская ц 0x20+132, // русская ч 0x20+133, // русская ш 0x20+134, // русская щ 0x20+135, // русская ъ 0x20+136, // русская ы 0x20+137, // русская ь 0x20+138, // русская э 0x20+139, // русская ю 0x20+140 // русская я }; Здесь показаны только добавленные русские символы, полный код см. по ссылке [1]. const uint8_t Font12_Table[] = { // @0 ' ' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // ... // @1116 '}' (ширина 7 точек) 0x00, // 0x20, // # 0x10, // # 0x10, // # 0x10, // # 0x10, // # 0x08, // # 0x10, // # 0x10, // # 0x10, // # 0x20, // # 0x00, // // @1128 '~' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // 0x24, // # # 0x58, // # ## 0x00, // 0x00, // 0x00, // 0x00, // 0x00, // // индекс 95, русская 'Б' (ширина 7 точек) 0x00, // 0xFC, // ###### 0x80, // # 0x80, // # 0xF8, // ##### 0x84, // # # 0x84, // # # 0x84, // # # 0xF8, // ##### 0x00, // 0x00, // 0x00, // // индекс 96, русская 'Г' (ширина 7 точек) 0x00, // 0xFC, // ###### 0x80, // # 0x80, // # 0x80, // # 0x80, // # 0x80, // # 0x80, // # 0x80, // # 0x00, // 0x00, // 0x00, // // индекс 97, русская 'Д' (ширина 7 точек) 0x00, // 0x38, // ### 0x48, // # # 0x48, // # # 0x48, // # # 0x48, // # # 0x48, // # # 0x48, // # # 0xFC, // ###### 0x84, // # # 0x00, // 0x00, // // индекс 98, русская 'Ж' (ширина 7 точек) 0x00, // 0x92, // # # # 0x92, // # # # 0x92, // # # # 0x7C, // ##### 0x92, // # # # 0x92, // # # # 0x92, // # # # 0x92, // # # # 0x00, // 0x00, // 0x00, // // индекс 99, русская 'И' (ширина 7 точек) 0x00, // 0x84, // # # 0x84, // # # 0x84, // # # 0x8C, // # ## 0xB4, // # # # 0xA4, // # # # 0xC4, // ## # 0x84, // # # 0x00, // 0x00, // 0x00, // // индекс 100, русская 'И' (ширина 7 точек) 0x10, // # 0xA4, // # # # 0x84, // # # 0x84, // # # 0x8C, // # ## 0xB4, // # # # 0xA4, // # # # 0xC4, // ## # 0x84, // # # 0x00, // 0x00, // 0x00, // // индекс 101, русская 'Л' (ширина 7 точек) 0x00, // 0x3C, // #### 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0x84, // # # 0x00, // 0x00, // 0x00, // // индекс 102, русская 'П' (ширина 7 точек) 0x00, // 0xFC, // ###### 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x00, // 0x00, // 0x00, // // индекс 103, русская 'У' (ширина 7 точек) 0x00, // 0x84, // # # 0x84, // # # 0x84, // # # 0x44, // # # 0x3C, // #### 0x04, // # 0x84, // # # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 104, русская 'Ф' (ширина 7 точек) 0x00, // 0x10, // # 0x7E, // ##### 0x92, // # # # 0x92, // # # # 0x92, // # # # 0x92, // # # # 0x7E, // ##### 0x10, // # 0x00, // 0x00, // 0x00, // // индекс 105, русская 'Ц' (ширина 7 точек) 0x00, // 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0xFE, // ####### 0x02, // # 0x00, // 0x00, // // индекс 106, русская 'Ч' (ширина 7 точек) 0x00, // 0x84, // # # 0x84, // # # 0x84, // # # 0x84, // # # 0x7C, // ##### 0x04, // # 0x04, // # 0x04, // # 0x00, // 0x00, // 0x00, // // индекс 107, русская 'Ш' (ширина 7 точек) 0x00, // 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0xFC, // ###### 0x00, // 0x00, // 0x00, // // индекс 108, русская 'Щ' (ширина 7 точек) 0x00, // 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0xFE, // ####### 0x02, // # 0x00, // 0x00, // // индекс 109, русская 'Ъ' (ширина 7 точек) 0x00, // 0xC0, // ## 0x40, // # 0x40, // # 0x78, // #### 0x44, // # # 0x44, // # # 0x44, // # # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 110, русская 'Ы' (ширина 7 точек) 0x00, // 0x84, // # # 0x84, // # # 0x84, // # # 0xE4, // ### # 0x94, // # # # 0x94, // # # # 0x94, // # # # 0xE4, // ### # 0x00, // 0x00, // 0x00, // // индекс 111, русская 'Ь' (ширина 7 точек) 0x00, // 0x80, // # 0x80, // # 0x80, // # 0xF8, // ##### 0x84, // # # 0x84, // # # 0x84, // # # 0xF8, // ##### 0x00, // 0x00, // 0x00, // // индекс 112, русская 'Э' (ширина 7 точек) 0x00, // 0x78, // #### 0x84, // # # 0x04, // # 0x3C, // #### 0x04, // # 0x04, // # 0x84, // # # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 113, русская 'Ю' (ширина 7 точек) 0x00, // 0x98, // # ## 0xA4, // # # # 0xA4, // # # # 0xE4, // ### # 0xA4, // # # # 0xA4, // # # # 0xA4, // # # # 0x98, // # ## 0x00, // 0x00, // 0x00, // // индекс 114, русская 'Я' (ширина 7 точек) 0x00, // 0x7C, // ##### 0x84, // # # 0x84, // # # 0x84, // # # 0x7C, // ##### 0x24, // # # 0x44, // # # 0x84, // # # 0x00, // 0x00, // 0x00, // // индекс 115, русская 'б' (ширина 7 точек) 0x00, // 0x18, // ## 0x20, // # 0x40, // # 0x58, // # ## 0x64, // ## # 0x44, // # # 0x44, // # # 0x38, // ### 0x00, // 0x00, // 0x00, // // индекс 116, русская 'в' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x38, // #### 0x44, // # # 0x78, // #### 0x44, // # # 0x44, // # # 0x38, // #### 0x00, // 0x00, // 0x00, // // индекс 117, русская 'г' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x3C, // ##### 0x40, // # 0x40, // # 0x40, // # 0x40, // # 0x40, // # 0x00, // 0x00, // 0x00, // // индекс 118, русская 'д' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x3C, // #### 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0xFC, // ###### 0x84, // # # 0x00, // 0x00, // // индекс 119, русская 'ж' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x54, // # # # 0x54, // # # # 0x38, // ### 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x00, // 0x00, // 0x00, // // индекс 120, русская 'з' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x78, // #### 0x04, // # 0x38, // ### 0x04, // # 0x04, // # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 121, русская 'и' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x44, // # # 0x4C, // # ## 0x54, // # # # 0x64, // ## # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 122, русская 'й' (ширина 7 точек) 0x00, // 0x00, // 0x28, // # # 0x10, // # 0x44, // # # 0x4C, // # ## 0x54, // # # # 0x64, // ## # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 123, русская 'к' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x48, // # # 0x70, // ### 0x48, // # # 0x44, // # # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 124, русская 'л' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x1C, // ### 0x24, // # # 0x24, // # # 0x24, // # # 0x24, // # # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 125, русская 'м' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x44, // # # 0x6C, // ## ## 0x54, // # # # 0x54, // # # # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 126, русская 'н' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x44, // # # 0x7C, // ##### 0x44, // # # 0x44, // # # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 127, русская 'п' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x7C, // ##### 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0x44, // # # 0x00, // 0x00, // 0x00, // // индекс 128, русская 'т' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x7C, // ##### 0x10, // # 0x10, // # 0x10, // # 0x10, // # 0x10, // # 0x00, // 0x00, // 0x00, // // индекс 129, русская 'у' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x44, // # # 0x24, // # # 0x18, // ## 0x10, // # 0x60, // ## 0x00, // 0x00, // 0x00, // // индекс 130, русская 'ф' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x38, // ### 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x38, // ### 0x10, // # 0x00, // 0x00, // 0x00, // // индекс 131, русская 'ц' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x48, // # # 0x48, // # # 0x48, // # # 0x48, // # # 0x48, // # # 0x7C, // ##### 0x04, // # 0x00, // 0x00, // // индекс 132, русская 'ч' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x44, // # # 0x44, // # # 0x44, // # # 0x3C, // #### 0x04, // # 0x04, // # 0x00, // 0x00, // 0x00, // // индекс 133, русская 'ш' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x7C, // ##### 0x00, // 0x00, // 0x00, // // индекс 134, русская 'щ' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x54, // # # # 0x7E, // ###### 0x02, // # 0x00, // 0x00, // // индекс 135, русская 'ъ' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x60, // ## 0x20, // # 0x38, // ### 0x24, // # # 0x24, // # # 0x38, // ### 0x00, // 0x00, // 0x00, // // индекс 136, русская 'ы' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x84, // # # 0x84, // # # 0xE4, // ### # 0x94, // # # # 0x94, // # # # 0xE4, // ### # 0x00, // 0x00, // 0x00, // // индекс 137, русская 'ь' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x40, // # 0x40, // # 0x78, // #### 0x44, // # # 0x44, // # # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 138, русская 'э' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x78, // #### 0x04, // # 0x3C, // #### 0x04, // # 0x04, // # 0x78, // #### 0x00, // 0x00, // 0x00, // // индекс 139, русская 'ю' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x48, // # # 0x54, // # # # 0x74, // ### # 0x54, // # # # 0x54, // # # # 0x48, // # # 0x00, // 0x00, // 0x00, // // индекс 140, русская 'я' (ширина 7 точек) 0x00, // 0x00, // 0x00, // 0x3C, // #### 0x44, // # # 0x44, // # # 0x3C, // #### 0x24, // # # 0x44, // # # 0x00, // 0x00, // 0x00, // }; Аналогичным образом был русифицирован шрифт Font16 (модуль font16.c), и при необходимости можно доработать другие шрифты. Исправленная функция, которая выводит графику английских и русских символов: /** * @brief Отображение одного символа. * @param Xpos: Начальный адрес столбца.
* @param Ypos: Линия, откуда отображается картинка символа.
* @param Ascii: Код символа.
* В нерусифицированной версии функции этот параметр должен
* быть в диапазоне 0x20 .. 0x7E. Русифицированная версия
* допускает также коды в диапазоне 0xC0 .. 0xFF (русские
* буквы), а недопустимые символы выводит как знаки вопроса.
*/
void BSP_LCD_DisplayChar(uint16_t Xpos, uint16_t Ypos, uint8_t Ascii) { if ((Ascii != 0x0A)/* && (Ascii != 0x0D)*/ && (Ascii < 0x20)) Ascii = '?'; else if ((Ascii >= 0x7E) && (Ascii < 0xC0)) Ascii = '?'; else if (Ascii >= 0xC0) Ascii = ANSI_rus_decode_table[Ascii-0xC0]; DrawChar(Xpos, Ypos, &DrawProp[ActiveLayer].pFont->table[(Ascii-' ') *\ DrawProp[ActiveLayer].pFont->Height * ((DrawProp[ActiveLayer].pFont->Width + 7) / 8)]); } Есть также возможность вставить вместо символов с кодами 0x00 .. 0x1F и 0x80 .. 0xBF вывод специальных графических символов (псевдографики). Вывод на LCD AM-480272H3TMQW-T01H русского текста: [Ссылки] 1. 200212LwIP_HTTP_Server_Socket_RTOS-rus.zip - исходный код примера русификации вывода, документация на индикатор AM-480272H3TMQW-T01H. |