LCD1602: Парочка вопросов.
- Войдите на сайт для отправки комментариев
Втр, 18/06/2019 - 22:47
Ребята, встретился в проекте с тем фактом что модем Sim800L серет в эфир так, что экран на I2C виснет каждые несколько минут. При этом, так получается, что приходится его располагать достаточно далеко - сантиметров 15 от платы, а I2C шина такого не терпет даже без модема. Но, вот пинов на нано осталось свободных немножко, решил его без I2C расширителя подцепить.
Поэтому возникло два вопроса:
1) Кто-то использовал А0-А5 для подключения этого дисплея? Как оно, работать будет?
2) Кто-то видел либу - руссификатор для такого типа подключения , по аналогии с такой либой LCD_1602_RUS.h для I2C дисплея? Русский нужен обязательно.
Кстати, сли кому надо, перепахал либу LCD_1602_RUS, уменьшив ее объем при компиляции приблизительно в два раза.
Пришлось пожертвовать маленькими буквами, выводить русский можно только в верхнем регистре (хотя бы так, лучше чем ~3,5кБ компиллированого пространства только под эту либу) к тому же добавил украинские "Є" , "Ї", "І" и апостроф, для совместимости с укр.языком.
Содержимое LCD_1602_RUS.h
#ifndef _LCD_1602_RUS #define _LCD_1602_RUS #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #include <avr/pgmspace.h> #include <LiquidCrystal_I2C.h> #include <Print.h> #define BYTE 0 #ifdef ARDUINO_ARCH_AVR typedef uint32_t _uint_farptr_t; #else typedef uint8_t* _uint_farptr_t; #ifndef memcpy_PF #define memcpy_PF(dest, src, len) memcpy((dest), (src), (len)) #endif #endif class LCD_1602_RUS : public LiquidCrystal_I2C { public: LCD_1602_RUS(uint8_t, uint8_t, uint8_t, uint8_t = 0); void print(const wchar_t[]); void print(const char[]); void print(int, int = DEC); void print(unsigned int, int = DEC); void print(long, int = DEC); void print(unsigned long, int = DEC); void print(const String &); void print(char, int = BYTE); void print(unsigned char, int = BYTE); void print(double, int = 2); void clear(); void setCursor(uint8_t, uint8_t); uint8_t getCursorCol(); uint8_t getCursorRow(); wchar_t *asciiutf8(unsigned char); private: void CharSetToLCD(uint8_t *, uint8_t *); void ResetAllIndex(); void printwc(const wchar_t); uint8_t mbtowc(wchar_t *, char *, uint8_t); uint8_t max_symbol_count; //Максимальное количество переназначаемых символов (по умолчанию 8: от 0 до 7) int symbol_index;//Индекс символа (от 0 до 7) uint8_t cursor_col; uint8_t cursor_row; //===Буквы==== uint8_t index_rus_B; uint8_t index_rus_G; uint8_t index_rus_D; uint8_t index_rus_ZH; uint8_t index_rus_Z; uint8_t index_rus_I; uint8_t index_rus_II; uint8_t index_rus_L; uint8_t index_rus_P; uint8_t index_rus_U; uint8_t index_rus_F; uint8_t index_rus_TS; uint8_t index_rus_CH; uint8_t index_rus_SH; uint8_t index_rus_SCH; uint8_t index_rus_tverd; uint8_t index_rus_Y; uint8_t index_rus_myagk; uint8_t index_rus_EE; uint8_t index_rus_YU; uint8_t index_rus_YA; uint8_t index_rus_YI; // uint8_t index_rus_YE; // }; extern const uint8_t rus_B[]; extern const uint8_t rus_G[]; extern const uint8_t rus_D[]; extern const uint8_t rus_ZH[]; extern const uint8_t rus_Z[]; extern const uint8_t rus_I[]; extern const uint8_t rus_II[]; extern const uint8_t rus_L[]; extern const uint8_t rus_P[]; extern const uint8_t rus_U[]; extern const uint8_t rus_F[]; extern const uint8_t rus_TS[]; extern const uint8_t rus_CH[]; extern const uint8_t rus_SH[]; extern const uint8_t rus_SCH[]; extern const uint8_t rus_tverd[]; extern const uint8_t rus_Y[]; extern const uint8_t rus_myagk[]; extern const uint8_t rus_EE[]; extern const uint8_t rus_YU[]; extern const uint8_t rus_YA[]; extern const uint8_t rus_YI[]; // extern const uint8_t rus_YE[]; // extern wchar_t char_utf8[]; #endifСодержимое LCD_1602_RUS.cpp
#include "LCD_1602_RUS.h" wchar_t char_utf8[] = L" "; //user_custom_symbols - количество символов, доступное пользователю для использования в своих целях (не более 8) //Всего переопределяемых символов в LCD - 8. //Символы с индексом от 0 до (7 - user_custom_symbols) используются библиотекой //Символы с индексом от (8 - user_custom_symbols) до 7 - можно переопределять пользователю //По умолчанию количество переопределяемых символов равно 0 LCD_1602_RUS :: LCD_1602_RUS(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t user_custom_symbols) : LiquidCrystal_I2C (lcd_Addr, lcd_cols, lcd_rows) { max_symbol_count = 8 - user_custom_symbols; symbol_index = 0; cursor_col = 0; cursor_row = 0; ResetAllIndex();//Сброс значений индексов (неинициализированы = 255) } void LCD_1602_RUS::clear() { LiquidCrystal_I2C::clear(); ResetAllIndex(); } void LCD_1602_RUS::setCursor(uint8_t col, uint8_t row) { cursor_col = col; cursor_row = row; LiquidCrystal_I2C::setCursor(cursor_col, cursor_row); } uint8_t LCD_1602_RUS::getCursorCol() { return cursor_col; } uint8_t LCD_1602_RUS::getCursorRow() { return cursor_row; } uint8_t LCD_1602_RUS::mbtowc(wchar_t *_chr, char *_str, uint8_t mb_num) { if (mb_num != 2) return 0; if ((_str[0] & 0xC0) == 0xC0 && (_str[1] & 0x80) == 0x80) { *_chr = ((_str[0] & 0x1F) << 6) + (_str[1] & 0x3F); return 2; } else { *_chr = _str[0]; return 1; } } void LCD_1602_RUS::print(const char *c_str) { wchar_t _str; int current_char = 0; int size = strlen(c_str); while (current_char < size) { current_char += mbtowc(&_str, (char *)c_str + current_char, 2); printwc(_str); cursor_col++; } } void LCD_1602_RUS::print(int val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(unsigned int val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(long val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(unsigned long val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(char val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(unsigned char val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(const String &str) { wchar_t _str; const char *c_str = str.c_str(); int current_char = 0; int size = str.length(); while (current_char < size) { current_char += mbtowc(&_str, (char*)c_str + current_char, 2); printwc(_str); cursor_col++; } } void LCD_1602_RUS::print(double val, int base) { cursor_col += LiquidCrystal_I2C::print(val, base); } void LCD_1602_RUS::print(const wchar_t *_str) { int current_char = 0; int size = 0; //Определяем длину строки (количество символов) while (_str[size] != 0) { size++; } while (current_char < size) { printwc(_str[current_char]); current_char++; cursor_col++; } } void LCD_1602_RUS::CharSetToLCD(uint8_t *array, uint8_t *index) { uint8_t x, y; if (*index == 255) // Если символ еще не создан, то создаем { x = getCursorCol(); y = getCursorRow(); createChar(symbol_index, (uint8_t *)array);// Создаем символ на текущем (по очереди) месте в знакогенераторе (от 0 до MAX_SYMBOL_COUNT) setCursor(x, y); write(symbol_index);// Выводим символ на экран //Запомианем, что букве соответствует определенный индекс *index = symbol_index; symbol_index++; if (symbol_index >= max_symbol_count) { symbol_index = 0; ResetAllIndex(); } } else //Иначе печатаем уже существующий write(*index); } void LCD_1602_RUS::ResetAllIndex() { symbol_index = 0; index_rus_B = 255; index_rus_G = 255; index_rus_D = 255; index_rus_ZH = 255; index_rus_Z = 255; index_rus_I = 255; index_rus_II = 255; index_rus_L = 255; index_rus_P = 255; index_rus_U = 255; index_rus_F = 255; index_rus_TS = 255; index_rus_CH = 255; index_rus_SH = 255; index_rus_SCH = 255; index_rus_tverd = 255; index_rus_Y = 255; index_rus_myagk = 255; index_rus_EE = 255; index_rus_YU = 255; index_rus_YA = 255; index_rus_YE = 255; index_rus_YI = 255; } void LCD_1602_RUS::printwc(const wchar_t _chr) { uint8_t rus_[8]; switch (_chr) { //Русский алфавит, требующий новых символов //Единовременно может быть заменено только 8 символов case 1028: //Є укр. memcpy_PF(rus_, (_uint_farptr_t)rus_YE, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_YE); break; case 1031: //Ї укр. memcpy_PF(rus_, (_uint_farptr_t)rus_YI, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_YI); break; case 1041: //Б memcpy_PF(rus_, (_uint_farptr_t)rus_B, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_B); break; case 1043: //Г memcpy_PF(rus_, (_uint_farptr_t)rus_G, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_G); break; case 1044: //Д memcpy_PF(rus_, (_uint_farptr_t)rus_D, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_D); break; case 1046: //Ж memcpy_PF(rus_, (_uint_farptr_t)rus_ZH, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_ZH); break; case 1047: //З memcpy_PF(rus_, (_uint_farptr_t)rus_Z, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_Z); break; case 1048: //И memcpy_PF(rus_, (_uint_farptr_t)rus_I, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_I); break; case 1049: //Й memcpy_PF(rus_, (_uint_farptr_t)rus_II, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_II); break; case 1051: //Л memcpy_PF(rus_, (_uint_farptr_t)rus_L, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_L); break; case 1055: //П memcpy_PF(rus_, (_uint_farptr_t)rus_P, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_P); break; case 1059: //У memcpy_PF(rus_, (_uint_farptr_t)rus_U, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_U); break; case 1060: //Ф memcpy_PF(rus_, (_uint_farptr_t)rus_F, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_F); break; case 1062: //Ц memcpy_PF(rus_, (_uint_farptr_t)rus_TS, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_TS); break; case 1063: //Ч memcpy_PF(rus_, (_uint_farptr_t)rus_CH, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_CH); break; case 1064: //Ш memcpy_PF(rus_, (_uint_farptr_t)rus_SH, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_SH); break; case 1065: //Щ memcpy_PF(rus_, (_uint_farptr_t)rus_SCH, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_SCH); break; case 1066: //Ъ memcpy_PF(rus_, (_uint_farptr_t)rus_tverd, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_tverd); break; case 1067: //Ы memcpy_PF(rus_, (_uint_farptr_t)rus_Y, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_Y); break; case 1068: //Ь memcpy_PF(rus_, (_uint_farptr_t)rus_myagk, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_myagk); break; case 1069: //Э memcpy_PF(rus_, (_uint_farptr_t)rus_EE, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_EE); break; case 1070: //Ю memcpy_PF(rus_, (_uint_farptr_t)rus_YU, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_YU); break; case 1071: //Я memcpy_PF(rus_, (_uint_farptr_t)rus_YA, 8); CharSetToLCD((uint8_t *)rus_, &index_rus_YA); break; //Русский алфавит, использующий одинаковые с английским алфавитом символы case 700: // LiquidCrystal_I2C::print("'"); break; case 1030: //x LiquidCrystal_I2C::print("I"); break; case 1040: //А LiquidCrystal_I2C::print("A"); break; case 1042: //В LiquidCrystal_I2C::print("B"); break; case 1045: //Е LiquidCrystal_I2C::print("E"); break; case 1025: //Ё LiquidCrystal_I2C::print("E"); break; case 1050: //К LiquidCrystal_I2C::print("K"); break; case 1052: //M LiquidCrystal_I2C::print("M"); break; case 1053: //H LiquidCrystal_I2C::print("H"); break; case 1054: //O LiquidCrystal_I2C::print("O"); break; case 1056: //P LiquidCrystal_I2C::print("P"); break; case 1057: //C LiquidCrystal_I2C::print("C"); break; case 1058: //T LiquidCrystal_I2C::print("T"); break; case 1061: //X LiquidCrystal_I2C::print("X"); break; //Английский алфавит без изменения default: LiquidCrystal_I2C::print((char)_chr); break; } } //Перевод символа из кодировки ASCII в UTF-8 (для печати расширенных русских символов на LCD) wchar_t *LCD_1602_RUS::asciiutf8(unsigned char ascii) { if (ascii == 168) *char_utf8 = 0x401; //код ASCII буквы Ё else if (ascii == 184) *char_utf8 = 0x451; //код ASCII буквы ё else if (ascii >= 192) //остальные буквы русского алфавита { *char_utf8 = ascii + 848; } else *char_utf8 = ascii; return char_utf8; } //Б const byte rus_B[8] PROGMEM = { 0b11111, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110, 0b00000 }; //Г const byte rus_G[8] PROGMEM = { 0b11111, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b00000 }; //Д const byte rus_D[8] PROGMEM = { 0b00110, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b11111, 0b10001 }; //Ж const byte rus_ZH[8] PROGMEM = { 0b10101, 0b10101, 0b10101, 0b01110, 0b10101, 0b10101, 0b10101, 0b00000 }; //З const byte rus_Z[8] PROGMEM = { 0b01110, 0b10001, 0b00001, 0b00110, 0b00001, 0b10001, 0b01110, 0b00000 }; //И const byte rus_I[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b00000 }; //Й const byte rus_II[8] PROGMEM = { 0b10101, 0b10001, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b00000 }; //Л const byte rus_L[8] PROGMEM = { 0b00111, 0b01001, 0b01001, 0b01001, 0b01001, 0b01001, 0b10001, 0b00000 }; //П const byte rus_P[8] PROGMEM = { 0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b00000 }; //У const byte rus_U[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b01111, 0b00001, 0b10001, 0b01110, 0b00000 }; //Ф const byte rus_F[8] PROGMEM = { 0b00100, 0b01110, 0b10101, 0b10101, 0b10101, 0b01110, 0b00100, 0b00000 }; //Ц const byte rus_TS[8] PROGMEM = { 0b10010, 0b10010, 0b10010, 0b10010, 0b10010, 0b10010, 0b11111, 0b00001 }; //Ч const byte rus_CH[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b01111, 0b00001, 0b00001, 0b00001, 0b00000 }; //Ш const byte rus_SH[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b10101, 0b11111, 0b00000 }; //Щ const byte rus_SCH[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b10101, 0b11111, 0b00001 }; //Ъ const byte rus_tverd[8] PROGMEM = { 0b11000, 0b01000, 0b01000, 0b01110, 0b01001, 0b01001, 0b01110, 0b00000 }; //Ы const byte rus_Y[8] PROGMEM = { 0b10001, 0b10001, 0b10001, 0b11101, 0b10011, 0b10011, 0b11101, 0b00000 }; //Ь const byte rus_myagk[8] PROGMEM = { 0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110, 0b00000 }; //Э const byte rus_EE[8] PROGMEM = { 0b01110, 0b10001, 0b00001, 0b00111, 0b00001, 0b10001, 0b01110, 0b00000 }; //Ю const byte rus_YU[8] PROGMEM = { 0b10010, 0b10101, 0b10101, 0b11101, 0b10101, 0b10101, 0b10010, 0b00000 }; //Я const byte rus_YA[8] PROGMEM = { 0b01111, 0b10001, 0b10001, 0b01111, 0b00101, 0b01001, 0b10001, 0b00000 }; //Ї укр. const byte rus_YI[8] PROGMEM = { 0b01010, 0b00000, 0b01110, 0b00100, 0b00100, 0b00100, 0b01110, 0b00000 }; //Є укр. const byte rus_YE[8] PROGMEM = { 0b01110, 0b10001, 0b10000, 0b11100, 0b10000, 0b10001, 0b01110, 0b00000 };Ребята, встретился в проекте с тем фактом что модем Sim800L серет в эфир так, что экран на I2C виснет каждые несколько минут.
Он у тебя не в эфир серет, а в питание
да и шину I2C можно прокидывать на метров 15 а может и поболее
Возможно и в питание, возможно и на 15 пробросить можно. Но ведь тема сисек осталась не раскрытой! Вопросы то мои были не об этом.
К тому же, мне экран на I2C - помеха, мне быстрый доступ к 24C512 нужен, а из за него ещё и шину на 400кГц, вместо 800-та, держать нужно. SoftWire уже во флеш не лезет. А ноги свободные есть, практически все А0-А7. Минус А4 и А5 под Wire.
Хорошо. ответ на твой вопрос: Аналоговые пины А0-А5 МОГУТ работать как цифровые выходы, А6, А7 - НЕТ
Хорошо. ответ на твой вопрос: Аналоговые пины А0-А5 МОГУТ работать как цифровые выходы, А6, А7 - НЕТ
Да это он пиарится, неужели Дед ты веришь, что человек перелопативший библиотеку LCD не в состоянии взглянуть на картинку разводки пинов ардуины нано )))
Да это он пиарится
Похоже на то.
Костя, какого решения Вы от нас ждете? Дисплей I2C, но к аппаратному Wire вы его цеплять не хотите - ибо медленно, к программному - слишком код большой... И что остается? - взять другой дисплей или написать свою Wire. на произвольных пинах?
О! При чем тут "пиарится", и при чем тут распиновка (знаюя ее, и понимаю). Я спросил - делал ли кто подключение этого экрана к ногам А0-А5, то что А6-7 не умеют в таком режиме работать помню. Ответ может звучать - да, делал и работает; да, делал и не работает.
И второй вопрос был - кто-то руссификатор для такого типа подключения где-то видел?
Блин, вроде ж на форум програмистов пишу , а ответы как у заядлых филологов.
kostyamat - я может вопроса не понял, но если это экран I2C, то подключить его можно только к пинам I2C - то есть А4 А5 на ардуино
Какие вопросы - такие и ответы. A* - в режиме выхода такие же, как и D*. Хотите узнать на предмет того подключал ли кто-то один в один по ваше распиновке - опубликуйте её. "Русификация" со способом подключения ничего общего не имеет.
kostyamat - я может вопроса не понял, но если это экран I2C, то подключить его можно только к пинам I2C - то есть А4 А5 на ардуино
если от этого экрана модуль I2C отпаять, то можно подключать к пинам, вот так http://zelectro.cc/LCD1602
Какие вопросы - такие и ответы. A* - в режиме выхода такие же, как и D*. Хотите узнать на предмет того подключал ли кто-то один в один по ваше распиновке - опубликуйте её. "Русификация" со способом подключения ничего общего не имеет.
Ок, про выводы понятно. А на счет руссификатора - как это так "не имеет"?
Выше гляньте, там руссификатор как объект от I2C либы экрана. Че, опять эту же либу пахать, или может где готовая есть?
Ок, про выводы понятно. А на счет руссификатора - как это так "не имеет"?
Ну вот так выходит, что не имеет. Экспандер что делает? Ставит свои ноги в соответствии с командой, которая пришла на I2C. А LCD пофигу, как ему на 4-битную шину сигнализируют - напрямую или через expander.
Давайте не смешивать "русификацию" и метод передачи данных на LCD. Подмените функции I2C-вывода на прямую манипуляцию выходами и вся "русификация" останется в прежнем виде, не изменившись ни на пиксель.