Часто возникает такая ситуация - куча дешевых изделий без индикации. Но индикация и управление все - таки нужно. Двенадцать лет назад искал решение - нашел. CE110.

PDF

Интерфейс - I2C. Хоть он и не допускает Hot Plug, все - таки изловчился и сделал. Алгоритм простой - отправляем 0x78 в интерфейс I2C. При наличии ACK - выставляем признак наличия и отправляем инициализируюшие байты. Выставляем бит прошедшей инициализации. И в дальнейшем - выводим на дисплей все что нужно. Наигрались - выдернули шнур. I2C вполне гуманно относится к такому извращению даже при наличии других слейвов - DS1307, DS1621 и т.д.

Работает под 89с2051(ассемблер), SAM7S256, Mega 1284. Кому надо - код под AVR:
Код
//Функции I2C
extern unsigned char ResI2c(unsigned char LastByte);//Приём байта с шины I2C. ACK не используется
extern unsigned char Sendi2c(unsigned char DATA);//Передача байта на шину I2C
extern void Strti2c(void);                        //Подача старт - условия на шину I2C
extern void Stopi2c(void);                        ///Подача стоп - условия на шину I2C
extern char BUF[20];                            //Буфер для функции PrintBuf

//--------------------------------------------------------------------------------
unsigned char KeyPollingCE110(void)         {        //Опрос наличия CE110 на шине I2C
unsigned char Temp=0;                            //
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Temp=Sendi2c(0x78);                         //Пеpедать адpес CE110
        Stopi2c();                                //Выдать стоп - условие на шину I2C
        return !Temp;                     }        //Возвращаем только что принятый байт. 0 - отсутствие CE110 на шине
//--------------------------------------------------------------------------------
void iniCE110(void)    {                            //Инициализация дисплея
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                            //Строка инициализации клавиатуры: 78h - адрес, 3 (Rg = 1, бит 0) - доступ
        Sendi2c(0);                                 //к регистру управления клавиатурой, 0 - выдавать коды только нажимаемых
        Sendi2c(0x38);                            //клавиш (бит 1), буфер клавиатуры - 1 байт (бит 2), проверку флага
        Sendi2c(0x0c);                            //BF драйвера ЖКИ осуществлять (бит 3), 60h - пауза перед автоповтором
        Sendi2c(0x06);                            //(6.5мс * 60h = 624мс), 1Eh - скорость автоповтора (6.5мс * 1Eh = 195мс)
        Sendi2c(0x01);                            //1 - очистка экpана
        Stopi2c();                                //Выдать стоп - условие на шину I2C
    
//Клавиатура:
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                            //Строка инициализации клавиатуры: 78h - адрес, 3 (Rg = 1, бит 0) - доступ
        Sendi2c(0x03);                            //к регистру управления клавиатурой, 0 - выдавать коды только нажимаемых
        Sendi2c(0x00);                            //клавиш (бит 1), буфер клавиатуры - 1 байт (бит 2), проверку флага
        Sendi2c(0x60);                            //BF драйвера ЖКИ осуществлять (бит 3), 60h - пауза перед автоповтором
        Sendi2c(0x1e);                            //(6.5мс * 60h = 624мс), 1Eh - скорость автоповтора (6.5мс * 1Eh = 195мс)
        Stopi2c();                                //Выдать стоп - условие на шину I2C
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                            //Строка инициализации клавиатуры: 78h - адрес
        Sendi2c(0x11);                            //Строка инициализации клавиатуры: доступ к регистрам маски, разрешающие
        Sendi2c(0xff);                            //автоповтор кнопок. 89h - C0 = 1(ст. бит, многобайтовая передача),
        Sendi2c(0xff);                            //начальный регистр маски 8 (бит 3), Rg = 1, бит 0. FFh - разрешить
        Sendi2c(0xff);                            //автоповтор всех кнопок.
        Sendi2c(0xff);                            //
        Sendi2c(0xff);                            //
        Sendi2c(0xff);                            //
        Sendi2c(0xff);                            //
        Sendi2c(0xff);                            //
        Stopi2c();    }                             //Выдать стоп - условие на шину I2C
//--------------------------------------------------------------------------------
void WrDAT(unsigned char DATA) {                //Запись данных
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                            //Передть адрес CE110    на шине I2C
        Sendi2c(0x40);                            //Доступ - в регистр данных микросхемы CE110
        Sendi2c(DATA);                            //Передать байт данных
        Stopi2c();             }                    //Выдать стоп - условие на шину I2C
//--------------------------------------------------------------------------------
void WrCOM(unsigned char DATA) {                //Запись комманд
        Strti2c();                                //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                            //Передть адрес CE110    на шине I2C
        Sendi2c(0x00);                            //Доступ - в регистр команд микросхемы CE110
        Sendi2c(DATA);                            //Передать байт данных
        Stopi2c();             }                    //Выдать стоп - условие на шину I2C
//--------------------------------------------------------------------------------
char table[] = {
    0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4,0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,
0xA8, //8Fh
//    А,    Б,    В,    Г,    Д,    Е,    Ж,    З,    И,    Й,    К,    Л,    М,    H,    О,    П
    0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,0xAC,0xE2,0xAD,0xAE,0xC4,0xAF,0xB0,
0xB1, //9Fh
//    Р,    С,    Т,    У,    Ф,    Х,    Ц,    Ч,    Ш,    Щ,    Ъ,    Ы,    Ь,    Э,    Ю,    Я
    0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,
0xBE, //AFh
//    а,    б,    в,    г,    д,    е,    ж,    з,    и,    й,    к,    л,    м,    н,    о,    п
    0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20, //BFh
//---------------------------------------------------------------------------------
    0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4,0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,
0xA8, //CFh
//    А,    Б,    В,    Г,    Д,    Е,    Ж,    З,    И,    Й,    К,    Л,    М,    H,    О,    П
    0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,0xAC,0xE2,0xAD,0xAE,0xC4,0xAF,0xB0,
0xB1, //DFh
//    Р,    С,    Т,    У,    Ф,    Х,    Ц,    Ч,    Ш,    Щ,    Ъ,    Ы,    Ь,    Э,    Ю,    Я
    0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,
0xBE, //EFh
//    а,    б,    в,    г,    д,    е,    ж,    з,    и,    й,    к,    л,    м,    н,    о,    п
    0x70,0x63,0xBF,0x79,0x5C,0x78,0xE5,0xC0,0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,
0xC7};//FFh
//    p,    с,    т,    у,    ф,    х,    ц,    ч,    ш,    щ,    ъ,    ы,    ь,    э,    ю,    я

//--------------------------------------------------------------------------------
void PrintBuf(unsigned char POS) {            //Вывод строки символов, оканчивающейся кодом 0xA
    char i;                                     //Сам код 0xA не выводится
    char K;                                     //
    WrCOM(POS);                                 //Установить курсор
    for (i = 0; i < 20; i++) {                //Первоначальная длинна выводимой строки 20 символов
        K = BUF[i];                             //Загрузить символ
        if (K>127) K=table[K-128];            //Перекодировка русских букв
        if (K==9) K = 32;                    //Заменить ТАВ на пробел
        if (K==0xa) break;                    //Загруженный код 0xA - конец цикла
    WrDAT(K);        }}                        //Вывести символ на дисплей
//--------------------------------------------------------------------------------

unsigned char CE110KN(void) {                //Опрос нажатия кнопок
unsigned char Temp;                            //
        Strti2c();                            //Выдать стаpт - условие на шину I2C
        Sendi2c(0x78);                        //Передть адрес CE110    на шине I2C
        Sendi2c(0x01);                        //Доступ - к регистру клавиатуры
        Strti2c();                            //Повторно выдать старт - условие на шину I2C
        Sendi2c(0x79);                        //Передть адрес CE110    на шине I2C с битом чтения
        Temp=ResI2c(0);                        //Принять байт с буфера клавиатуры. Выдать NAK.
        Stopi2c();                        //Выдать стоп - условие на шину I2C
        return Temp;                        //Возвращаем только что принятый байт.
            }

В основной цикл добавляем код:
Код
//--------------------------------------------------------------------------------
if (CE110_Present) {                                //Если CE110 присутствует на шине
    if (!KeyPollingCE110()) {CE110_Present = 0;}}    //Если CE110 выключили, обнулить флаг присутствия
    else {                                                //Если CE110 не присутствует на шине
        if (KeyPollingCE110()) {iniCE110(); CE110_Present = 1;}}//Если CE110 включили, установить флаг присутствия

Таблица - для перекодировки русских букв. Основное - это конечно функция PrintBuf. Вывод останавливается при наличии символа 0xA(\n). WrCOM - запись байта в регистр команд, WrDAT - запись байта в регистр данных. Для подключенных по схеме кнопок функция CE110KN выдает коды:
0x80 - первая кнопка
0x88 - вторая кнопка
0x90 - третья кнопка
0x98 - четвертая кнопка
0xa0 - пятая кнопка


Пользоваться так:
Код
sprintf (LCDBuf,"%d из %d\n",ChMemory+1, MaxCh);//Вывод номера(осчет от 1)
PrintBuf_P(0xc0);                    //выводимого канала

Наомера строк для подключенного PC2004:
0x80 - первая
0xС0 - вторая
0x94 - третья
0xd4 - четвертая

Теперь вопрос. CE110 - это PIC16C63, который КТЦ МК прошивает своим кодом. Ездить и покупать это чудо мне изрядно надоело. Есть идея реализовать все это на 89с2051, которых у меня навалом. Но I2C slave писать влом. Если у кого есть ссылки или код для 8051 I2C slave - поделитесь пожалуйста. Ну а я выложу все что получилось.
Схема подключения модуля и пример кода для 8051(ассемблер)