Кириллица в китайском LCD 1602a

Кириллица в китайском LCD 1602a

Делая инкубатор столкнулся с тем что пользователи не знают английский. А дисплей из Китая не имеет русских символов.

Нашел тему на форуме из которой узнал, что дисплей имеет память в которой можно хранить собственные символы. Отправился изучать LCD1602A-Datasheet-v1.2.pdf. Мой дисплей на контроллере ST7066U-0A.

Из описания контроллера видно, что у нас всего 64 байта CGRAM. 1 символ размером 5x8 пикселей занимает 8 байт. Чтобы записать в память нужно передать команду 0x40 + адрес байта. При отправке байта адрес автоматически увеличивается, поэтому можно слать подряд все 64 байта.

Мы будем слать по 1 символу, то есть по 8 байт.

Размер символа 5x8 точек. 1 байт это одна строка в символе. Из байта используется 5 бит на строку из 5 пикселей.

Например как нарисовать "минус".

0b00000
0b00000
0b00000
0b11111
0b00000
0b00000
0b00000
0b00000

Чтобы не рисовать самому, я нашел уже готовые символы которые мне были нужны.

uint8_t chars[] = {
        0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0, // П
        0b01111, 0b10001, 0b10001, 0b01111, 0b00101, 0b01001, 0b10001, 0, // Я
        0b11, 0b111, 0b101, 0b101, 0b1101, 0b1001, 0b11001, 0, // Л
        0b10001, 0b10011, 0b10011, 0b10101, 0b11001, 0b11001, 0b10001, 0, // И
        0b01111, 0b00101, 0b00101, 0b01001, 0b10001, 0b11111, 0b10001, 0, // Д
        0b11111, 0b10001, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0, // Г
        0b01110, 0b00000, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0, // Й
        0b10101, 0b10101, 0b10101, 0b11111, 0b10101, 0b10101, 0b10101, 0, // Ж
        0b10001, 0b10001, 0b10001, 0b01010, 0b00100, 0b01000, 0b10000, 0, // У
        0b11110, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110, 0, // Б
        0b10001, 0b10001, 0b10001, 0b01111, 0b00001, 0b00001, 0b00001, 0, // Ч
        0b10001, 0b10001, 0b10001, 0b11001, 0b10101, 0b10101, 0b11001, 0, // Ы
        0b10010, 0b10010, 0b10010, 0b10010, 0b10010, 0b10010, 0b11111, 0b00001 // Ц
};

Другие буквы такие как "З" - можно использовать цифру 3. Да и для буквы "И" можно использовать "u". А для "У" - "Y" или "y".

У нас всего 8 байт памяти. А если определять длину строки по null символу, и того меньше... остается 7.

Функция записи в CGRAM может быть такой.

// передаем номер символа от 0 до 7 и номер символа (строки) из массива выше.
void LCDWriteCGRAM(uint8_t pos, uint8_t ch) {
    // Отправляем команду + адрес
    // смещение на 3 влево нужно для кратности 8
    // чтобы передавать сразу по 8 байт, то есть весь символ
    LCDCommand(0x40 | (pos << 3));
    for (uint8_t i = 0; i < 8; i++) {
        // шлем все 8 байт символа
        LCDSendByte(chars[ch * 8 + i]);
    }
}

Как я писал выше, адрес установленный командой Set CGRAM 0x40, автоматически увеличивается после каждого принятого байта.

Допустим мы хотим сохранить под номером 0 символ "Д".

LCDWriteCGRAM(0, 4);

0 - адрес первого байта символа.
4 - строка в массиве.

Для отправки первого байта нужно установить его адрес. Для 0-го будет 0. И после этого отправить данные, наш байт.

LCDCommand(0x40 | 0);
LCDSendByte(байт);

Чтобы передать второй байт, можно установить новый адрес и передать новый байт.

LCDCommand(0x40 | 1);
LCDSendByte(байт);

Но, так как адрес автоматически увеличивается после приема байта, мы можем слать просто подряд все 8 байт.

Для нулевого символа понятно. А что будет когда мы пошлем символ под номером 5.

Нужно 5 * 8  = 40. То есть первый байт нашего символа под номером 5 будет 40.

Умножение на 8 это тоже что сдвиг влево на 3. 5 << 3 = 40.

Поэтому когда мы напишем 

LCDWriteCGRAM(5, 9);

Мы запишем 8 байт, начиная с адреса 5 << 3 = 40. И там будет буква "Б".

Чтобы вывести на экран наши символы, просто пошлем на вывод номер символа.

LCDSendByte(0);

Выведет букву "Д", так как мы ее установили в нулевую ячейку.

Можно выводить так

LCDPrint("\0OM", 3);

Будет выведено на дисплей "ДOM". Или

LCDPrint("PO\5OT", 3);

Мы получим слово "POБOT".

А вот если мы не знаем заранее размер строки, уже лишаемся одного символа. Так как \0 - будет считаться концом строки.

LCDPrintLn("\5OPO\0A");

Выведет не "БOPOДA" а "БOPO".

При копировании материалов ссылка на https://terraideas.ru/ обязательна

Комментарии к статье: Кириллица в китайском LCD 1602a

Нет ни одного комментария. Будьте первым!