Диагностический модуль по интерфейсу I2C.

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Димон Безпарольный
Встал на лапы
Сообщения: 97
Зарегистрирован: Пн мар 08, 2010 20:48:51

Диагностический модуль по интерфейсу I2C.

Сообщение Димон Безпарольный »

Десять лет безупречной работы. Решил поделится и спросить.
Часто возникает такая ситуация - куча дешевых изделий без индикации. Но индикация и управление все - таки нужно. Двенадцать лет назад искал решение - нашел. CE110.
http://electronix.ru/forum/index.php?ac ... post&id=10

Интерфейс - 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);					//выводимого канала
Схема подключения модуля и пример кода для 8051(ассемблер)

http://electronix.ru/forum/index.php?ac ... t&id=91990

http://electronix.ru/forum/index.php?ac ... t&id=91997

Теперь вопрос. CE110 - это PIC16C63, который КТЦ МК прошивает своим кодом. Ездить и покупать это чудо мне изрядно надоело. Есть идея реализовать все это на 89с2051, которых у меня навалом. Но I2C slave писать влом. Если у кого есть ссылки или код для 8051 I2C slave - поделитесь пожалуйста. Ну а я выложу все что получилось.
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15570
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Диагностический модуль по интерфейсу I2C.

Сообщение BOB51 »

А чего в том "сверхестественного"? :roll:
Обычная практика создания собственных устройств на МК, которая должна быть сегодня доступно-повсеместной.
И не обязательно I2C - любой самодельный протокол, удовлетворяющий пользователя/программиста и обеспечивающий работу всей системы.
:beer:
Реклама
Димон Безпарольный
Встал на лапы
Сообщения: 97
Зарегистрирован: Пн мар 08, 2010 20:48:51

Re: Диагностический модуль по интерфейсу I2C.

Сообщение Димон Безпарольный »

BOB51 писал(а):И не обязательно I2C - любой самодельный протокол, удовлетворяющий пользователя/программиста и обеспечивающий работу всей системы.
:beer:
I2C для меня предпочтительней - полно готовых изделий которые по этому протоколу выдают / принимают данные и команды.
BVG_15
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Ср фев 11, 2015 20:50:17
Откуда: центр Урала

Re: Диагностический модуль по интерфейсу I2C.

Сообщение BVG_15 »

писал,недавно, чисто програмный slave под AVR 2313.
До ума не доведено,но работает. Нет проверки адреса,хотя он фиксируется программой.
С уважением Вл.Георг.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15570
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Диагностический модуль по интерфейсу I2C.

Сообщение BOB51 »

Для "горячего подключения" в самоделках больше чего похожего на микроLAN подходит или аппаратный RS232 /модифицированные его аналогии.
Но там могут быть проблемы с уже имеющимися в устройстве прерываниями.
I2C в программном исполнении хорош для ведущего устройства только возможностью полной приостановки обмена в любое время /непостоянства скорости обмена.
:dont_know:
Реклама
Димон Безпарольный
Встал на лапы
Сообщения: 97
Зарегистрирован: Пн мар 08, 2010 20:48:51

Re: Диагностический модуль по интерфейсу I2C.

Сообщение Димон Безпарольный »

BVG_15 писал(а):писал,недавно, чисто програмный slave под AVR 2313.
До ума не доведено,но работает. Нет проверки адреса,хотя он фиксируется программой.
Если не жалко - киньте код.
Реклама
Ответить

Вернуться в «Разные вопросы по МК»