Интерфейс - 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; //Возвращаем только что принятый байт.
}
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 включили, установить флаг присутствия
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); //выводимого канала
PrintBuf_P(0xc0); //выводимого канала
Наомера строк для подключенного PC2004:
0x80 - первая
0xС0 - вторая
0x94 - третья
0xd4 - четвертая
Теперь вопрос. CE110 - это PIC16C63, который КТЦ МК прошивает своим кодом. Ездить и покупать это чудо мне изрядно надоело. Есть идея реализовать все это на 89с2051, которых у меня навалом. Но I2C slave писать влом. Если у кого есть ссылки или код для 8051 I2C slave - поделитесь пожалуйста. Ну а я выложу все что получилось.
Схема подключения модуля и пример кода для 8051(ассемблер)