Новая жизнь для ИЖЦ5-4/8 Или контроллер ЖКИ с (soft) IIC

Очередной раз разгребая свои Авгиевы конюшни, нашел я замечательный такой совковый ЖК индикатор на четыре разряда. Имя ему — ИЖЦ5-4/8. Тут же захотелось его куда-то присобачить… Но посмотрев на количество ног — пыл мой сразу поубавился. Посему, решил сделать к нему контроллер, да ещё с интерфейсом IIC.


При выборе контроллера я руководствовался его ценой (ну как-то не хотелось ставить туда что-то дороже 1 евро) и минимумом выводов. Поэтому, выбор пал (из доступных мне) на PIC12F629. Но у него не было аппаратного модуля IIC, пришлось реализовывать софтово. Собственно, от чего процесс стал ещё более занимательным :)

Немного о прошивке
Сперва, как сознательный ламер, решил делать все через таймеры-прерывания. То бишь, управлять сменой управляющих напряжений на подложке и соответствующих сегментах (кто не в курсе работы ЖКИ — ниже объясняется что и к чему) с помощью прерывания от таймера. Соответственно, следить за событием START на шине IIC тоже с помощью внешнего прерывания, а в остальное время — спать! Как я радовался этой идее… Даже успел написать какую-то часть кода. При этом меня не покидало чувство, что это ну уж сли-иишком медленно — частота ядра у 12F629 всего-то 1 МГц.
И не зря. Гугление привело меня на какой-то забытый форум, прочитав который, я уяснил, что софтовый IIC Slave — штука медленная и капризная… Прерывания посему здесь не прокатят… Но тогда как управлять ЖКИ и ещё реализовать IIC Slave?.. Идею подкинул мне аппноут AN541 от Microchip. Пытаясь вникнуть в индусский код древнего МК, мне пришла мысль, что в качестве таймера можно использовать… WDT! И период его по умолчанию как раз подходящий ~18 мс. В общем, алгоритм программы выглядит следующим образом:

Из рисунка должно явствовать следующее. Включаем WDT — делается это с помощью команды __CONFIG _WDT_ON. При этом формируется соответствующее значение конфигурационного слова, которое записывается в ячейку с адресом 0x2007 при программировании FLASH МК.
list	p=12f629
#include <p12f629.inc>
__CONFIG	_INTRC_OSC_NOCLKOUT & <strong>_WDT_ON</strong> & _PWRTE_OFF & _MCLRE_OFF & _BODEN_OFF & _CP_OFF & _CPD_OFF

В начале программы проверяем, произошел ли сброс по включению питания или по WDT. В последнем случае — бит "-TO" в регистре STATUS сброшен. Если бит установлен — значит произошло одно из: POR/выполнена команда CLRWDT/выполнена команда SLEEP.
org	0x000
		btfsc	STATUS, NOT_TO	;Если STATUS.TO=0,
		goto	Start			;пропустить следующую команду
		goto	StartWDT		;

Да, важный момент для PIC. Эти МК требуют перед началом основной программы загружать значение калибровочной константы для внутреннего RC-генератора, которая по умолчанию находится во флеше по адресу 0x33F. Тут и кроются грабли, ведь при программировании это значение теряется… То бишь, перед тем как записывать программу, необходимо считать флеш МК, запомнить значение константы по адресу 0x33F, а затем записать его как значение константы CONST_RC в программе:
;=Определение констант================
CONST_RC		set		0x3F	;Сюда необходимо подставить СВОЕ значение
калибровочной константы внутреннего RC-генератора
...
org	0x33F
		retlw	CONST_RC          ;Так выглядит запись калибровочной константы

Сама константа выглядит так:
0x34yy        ;где '34' - код команды retlw, а 'yy' - значение константы

После настройки регистров МК (в основном тут — отключение всего лишнего), выполняем запись информации в сдвиговые регистры. Сначала инвертируем состояние вывода, подключенного к подложке индикатора (GP2). Далее, если текущее значение на выводе GP2 равняется «0», в регистры 74HC164D записываем все как есть, если же «1» — инвертируем.

;=Определение переменных==============
LCDRAM1			equ		0x20	;Первый разряд	LCD
LCDRAM2			equ		0x21	;Второй разряд	LCD
LCDRAM3			equ		0x22	;Третий разряд LCD
LCDRAM4			equ		0x23	;Четвертый разряд LCD
...
;======================================
;=Запись данных в регистры			  =
;======================================
		;====Формируем меандр для подложки индикатора на выходе FF
		movfw	GPIO			;Копируем содержимое регистра GPIO
		movwf	temp			;в буфер
		btfsc	temp, FF		;Если выход FF сброшен в 0, пропускаем следующую команду,
		bcf		GPIO, FF		;иначе FF=0
		btfss	temp, FF		;Если выход FF установлен в 1, пропускаем следующую команду,
		bsf		GPIO, FF		;иначе FF=1
		;
		movlw	LCDRAM1			;Косвенная адресация
		movwf	FSR				;к ячейке LCDRAM1
		;
		clrwdt
		;====Процедура записи данных в сдвиговые регистры
SENDBYTE
		clrwdt
		;
		movfw	INDF			;Загрузить из индексного регистра значение регистра по адресу в FSR
		;
		call	Table			;Табличное конвертирование
		;
		movwf	temp			;Сохраняем полученное значение в temp
		btfsc	GPIO, FF		;Если FF=0, пропустить следующую команду,
		comf	temp			;иначе инвертировать содержимое temp
SENDBIT
		clrwdt
		;
		bcf		GPIO, CP		;Строб CP=0
		rlf		temp, F			;Циклический сдвиг влево через перенос С
		btfsc	STATUS, C		;Если С сброшен в 0, пропустить следующий шаг,
		bsf		GPIO, DTOUT		;иначе DTOUT=1
		btfss	STATUS, C		;Если С установлен в 1, пропустить следующий шаг,
		bcf		GPIO, DTOUT		;иначе DTOUT=0
		nop						;Задержка перед стробом
		bsf		GPIO, CP		;Строб CP=1 (запись в регистры)
		incf	k				;Счетчик переданных битов i=i+1
		btfss	k, ENDSBIT		;Если бит 3 установлен, пропустить следующий шаг,
		goto	SENDBIT			;иначе продолжить передавать текущий байт
		;
		clrwdt
		;
		clrf	k				;Очищаем счетчик переданных битов
		bcf		GPIO, CP		;Строб CP=0
		;
		incf	FSR				;Косвенная адресация к следующей ячейке памяти LCD
		movlw	LCDRAM4+1		;Загрузить адрес последней ячейки + 1,
		subwf	FSR, W			;вычесть полученное значение из регистра косвенной адресации FSR и сохранить в W
		btfss	STATUS, Z		;Если результат операции 0, пропустить следующую операцию,
		goto	SENDBYTE		;иначе продолжить пересылать данные
		;
		bcf		GPIO, DTOUT		;Сбрасываем DTOUT в 0
		;====Передача завершена========
		;
		clrwdt					;Крайний сброс WDT до обнаружения состояния START на шине IIC
		;

После этого возможно выполнение некоторого кода пользователя, который будет выполнятся один раз за период работы программы.
;======================================
;=Программа пользователя              =
;======================================
Main	nop						;Максимум 8 мс
;		
;

А дальше просто — ждем состояния START на шине IIC. НО! Мы не выполняем команды сброса WDT. То бишь, если до окончания счета сторожевого таймера, START не будет обнаружен, МК перезагружается по переполнению WDT, и программа начинает новый цикл работы. Этим и обеспечивается необходимая частота обновления сигналов на выводах ЖКИ.
Если состояние START обнаружено, начинает работать автомат IIC Slave, который обильно пересыпан командами CLRWDT — соответственно, пока он (автомат) работает, МК не перезагрузится.
Формат общения с контроллером таков:
— передаем старт, выдаем адрес устройства (у меня установлен 0х55);
— получаем ACK;
— последовательно передаем четыре байта символов, начиная с того, что будет высвечен крайним справа;
— при получении первых трех байтов автомат IIC Slave отвечает ACK, при получении крайнего слева (4-го) — отвечает NACK.
Внимание ! Master должен понимать, когда Slave прижимает линию SCL к земле.
После получения 4-го символа, автомат IIC Slave перестает выполнять команды CLRWDT и ждет состояний START/STOP. Так что, даже если последнего не случится — МК всеравно сбросится по WDT. Если подать на шину опять START, автомат снова начнет свою работу, но лучше этого не делать — надо же оставить немного времени и на обновления для ЖКИ.

Таблица символов
Реализована по аналогии с HD44780 и для тех символов, что 7-сегментник не может реализовать, заполнена от балды =) Так что, если кому надо — редактируем сами =)

Сама таблица, как видно — в половину меньше от HD44780 (0x00...0x7F). Старший бит отдан под признак команды, и в случае передачи символа должен равняться нулю. Если же он равен единице — автомат воспринимает принятый байт как команду и… ничего не делает :) Оставлено для модернизации (если захочется) :)
Таблица в памяти МК физически располагается в начале флеша. Нелогично, да? Ну тут ничего не поделаешь, такие особенности у данного семейства PIC-ов…

;=====================================
;====    Таблица символов    =========
;=====================================
org		0x005
Table	addwf	PCL, F
		retlw	0			;Адрес внутри таблицы 0x00
		retlw	0			;0x01
...
;
		retlw	b'01111110'			;0x30	"0"
		retlw	b'01000010'			;0x31	"1"
		retlw	b'11101100'			;0x32	"2"
		retlw	b'11100110'			;0x33	"3"
		retlw	b'11010010'			;0x34	"4"
		retlw	b'10110110'			;0x35	"5"
		retlw	b'10111110'			;0x36	"6"
		retlw	b'01100010'			;0x37	"7"
		retlw	b'11111110'			;0x38	"8"
		retlw	b'11110110'			;0x39	"9"

Кодируются символы согласно следующего рисунка:

Синими цифрами обозначены номера битов, которым соответствуют сегменты. Например, для того, чтобы засветить сегмент 'G', нужно в бит №7 записать единичку.

Проект реализован в MPLAB на ассемблере и обильно пересыпан комментариями на каждый чих (ну или почти на каждый :) ). Кому интересно об автомате IIC Slave — про него немного написано ниже. Скажу лишь, что максимальная частота работы у меня получилась что-то около 11 кГц. Частота, при которой автомат работал стабильно ~10 кГц. Как видите, довольно-таки мало…
И ещё. Девайс отказался работать при напряжении менее 3,6 В :(
Кстати, работать лучше на максимальной частоте (10 кГц), поскольку если ставить частоту меньше ЖКИ начинает неприятно «мигать»...
Схема
Ниже схема девайса, фотки платы со стороны элементов. Для дрыганья ногами ЖКИ использовал сдвиговые регистры 74HC164D. В конце статьи приведены ссылки на архив с проектом в MPLAB (варнинг, ассемблер!) и проектом платы в P-CAD 2006.

Резисторы R4, R5 — подтяжка для шины IIC. Разъем для подключения питания и шины совмещен с разъемом программирования для удобства. В качестве программатора выступал самодельный PICkit 2, от распиновки его разъема и отталкивался.

Плата немного доработана напильником уже по ходу написания прошивки, поскольку выяснилось, что вывод GP3 (он же вход для высоковольтного программирования) может работать только как вход.

А теперь позволю себе немного теории
Кратенько о способе управления ЖК-индикатором.
О физических принципах работы ЖКИ индикатора я здесь писать не буду — Wiki знает больше. Нам нужно знать лишь то, что под действием электрического поля, ЖК-структура перестает пропускать свет определенной поляризации — поэтому сегмент становится виден. В данном случае, это касается позитивных ЖКИ к которым и относится ИЖЦ5-4/8.
Но, так как постоянное напряжение подавать нельзя (это приводит к деградации ЖК-структуры), нужно формировать меандр с частотой где-то 120 Гц (ИМХО). Тогда, если нам нужно, например, на семисегментном ЖК индикаторе засветить цифру '3'

где FF — электрод, к которому подключена подложка, общая для всех сегментов.
Тогда форма напряжений на соответствующих электродах должна иметь вид:

Из рисунка должно быть понято что:
— Для того чтобы сегмент стал виден, нужно на него подавать меандр в противофазе от сигнала на подложке FF (нарисовано синим);
— Для того чтобы сегмент не был виден — соответственно нужно подавать на него меандр синфазный с сигналом на подложке FF (нарисовано красным).

Софтовый IIC Slave реализован с помощью детерминированного автомата состояний.
Кому интересно — отсканировал свой рабочий черновик :D Жестоко, да… Но думаю, описывать его не имеет смысла, т.к. реализацию протоколов в софте уже можно назвать анахронизмом :)
Ссылка на черновик

P.S. Видео
  • +11
  • 13 февраля 2012, 00:55
  • abigsam
  • 1
Файлы в топике: pic12.zip

Комментарии (82)

RSS свернуть / развернуть
А ЖК не вредят сбои генерации управляющего напряжения во время работы I2C? Тем более что сбои эти приводят к генерации несимметричного сигнала, что приводит к возникновению вредной для ЖК постоянной составляющей.
0
  • avatar
  • Vga
  • 13 февраля 2012, 04:57
ага, а кроме того желательно если и управлять ЖК при помощи регистров, то с использованием защелки, ибо в момент «пропихивания» всех данных через регистры на их выводах, в данной реализации, происходит процес «управляемого хаоса», что может тоже внести свою лепту в несимметричность управляющих напряжений. Но это не так существенно, если учитывать то, что вы и так, судя по схеме, управляете ЖКИ при помощи постоянного напряжения, хоть и считаете его переменным, долго оно не проработает…
0
хотя нет. управляете вы все-таки переменкой и если учитываете фазу при смене информации на сегментах, то тогда в этом отношении проблем нет.
0
ну и ладушки =D
0
да, както об несеметричности я неподумал…
хотя, не считаю, что уж настолько там все плохо :) а осцила или лог. анализатора у меня нет, чтобы проверить.
0
А какое минимальное (чтобы было видно) и максимальное (чтобы не сдохло) напряжение можно подавать на сегменты?
0
ЖК вроде до 11 В держит, микрухи явно до 5 В
я ж вначеле статьи паспорт на него привел :)
0
коммент без содержания, но не мог удержаться. Огромное спасибо за статью давно искал подобное. СПАСИБО. утащу к себе, не возражаете? вот сюда petro-ewlab.com/viewforum.php?f=106
0
а обязательно было говорить куда утянули?
0
Да, обязательно. У автора статьи могут быть претензии по написанию, может попросить что нибудь добавить.
0
или просто попросить убрать нафик. такое тоже бывает.
0
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
Карма-дрочеры!, Карма-дрочеры everywhere. А-бы обосрать, честно. Впрочем не вникал, но осуждаю.
Кстате, скажу лиш «Большое спасибо за разработку, вполне нужный девайс»
+1
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
По устройству имеются следующие замечания/отзывы:
В последнее время некоторую популярность приобретают STM8L, у ниж имеется встроенный контроллер дисплея. И честно говоря его и ожидал увидеть при открытии статьи. Был удивлен. Применение стандартных компонентов — плюс за реализацию.
Те же STM8 имеют встроенный I2C контроллер. Применение мк без встроенной перефирии — плюс за реализацию.
Как уже отметил про STM8L, имеющий хардварную реализацию всей требуемой переферии и близкую по стоимости с полученной системой — минус за выбор платформы.
Указанный минус вполне можно негилировать возможностью «сбора из того что есть под рукой», «необходимостью изучения новой архетиктуры» и «желанием понять 'как же оно работает'». Однако рекомендую по возможности применять аппаратные возможности систем.
Спасибо за интересную статью.

P.S.: Ну и насрали же в комментах не по теме. К автору просьба не обращать внимания на эти придирки. Ошибаются все, тем более что не родной язык. Для меня родной, но при прочтении поста у меня ошибки не вызвали ни каких негативных эмоций. И непониманий ни каких не повлекло. По замечанию исправили и разговаривать больше не о чём. В прочем даже исправлять не обязательно, потому как… Во-первых, это ваш личных блог. Вы вольны излагать мысли в удобной для вас форме. Во-вторых, вы вольны излагать свои мысли в удобной для вас форме. Кому тема интересна — прочтут суть, кому нет — насрут в любом случае.
+1
Если уж говорить про готовую периферию, то можно было просто заюзать PCA751xx, из I2C Industrial Promo Pack например. Или свежей автомобильной акции.
Правда, то, что заюзано тут — доступнее, но специализированное решение надежнее.
0
дада, тут я виноват. Забыл что у самого есть :)
А какая у них цена, кстати, не в курсе? я что-то по магазинам их так и не встречал (правда и не искал).
0
ну эта конструкция для меня скажем «выходного дня», поэтому максимальная простота и дешевизна :)
а про STM8L — я думал, да. Вот поднакоплю деньжат, обязательно прикуплю STM8L-DISCOVERY

p.s. характер у меня вспыльчивый, а так бы «лучшая месть — игнор» :) ну а в реальной жизни, этот человек давно был бы послан на х#@, как неадекватный.
0
У AVR тоже камни с контролем стекляхи. Правда я не помню в каком они там виде. Возможно, что только в виде COG
0
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
комментарий был удален
как правильно сказано — хабр детектед. в самом негативном смысле, к сожалению. в смысле, что народ детектит общий эмоциональный фон и форму, но упускает смысл и содержание.
имхо, прискорбно как посетителю. но с т.з. основателя положительно…
в общем, однозначной оценки такому характерному (но в общем и целом характеризующему) развитию событий дать сложно. +++/--- а в итоге… хз что в итоге. создателю плюшки, пользователям срач. смешно за форму/идею и больно за идею/форму.
0
Не забывайте, что как минимум по -4 я дал собственноручно. А выбесил меня тот факт, что на вполне добротную по содержанию статью (на которую автор потратил, по моим прикидкам, не менее 4-5 часов) начали наезжать по грамматическим ошибкам, при том, что русский для чела не родной. И засрали тем все комменты, да так, что мне пришлось все зачищать. А сам автор подрывался статью вообще удалить нахрен. Правда я не дал.

Писали бы в личку по таким вопросам не было бы никаких претензий. И впредь тоже будет так. За оффтопный срач — сливаю с ресурса.
+4
Можно также посмотреть в сторону AY0438. Но, по мне, лучше один более ногастый контроллер. Например, MSP430F133-обслуживает 4,5 десятичный LCD ITS-E0811, а AT90S4414(mega8515) 3,5 десятичный LCD ITS-E0803 и спецсимволы. При этом, платы выполняют свои основные функции измерения, обслуживания кнопок, то да сё.
+1
  • avatar
  • akl
  • 17 февраля 2012, 10:46
Тоже валяется куча ИЖЦшек.
Но городить софтовый I²С чтобы потом переделать его в SPI ИМХО полный изврат. С таким же успехом можно было сразу использовать хардовый SPI.
И сам драйвер ЖКИ я делал бы на жёсткой логике (регистры + инвертирующие и неинвертирующие буферы с третьем состоянием) чтобы не было перекосов управляющего напряжения.
Ну и совсем шикарно было бы добавить ещё интерфейсов, например UART.
0
полный изврат
ага, кто спорит ))

Я хотел сделать законченное устройство, кот. можно было бы подключить к платам типа STM32-Discovery (что собственно и сделал) для вывода отладочной информации.
Поначалу тоже была мысль сделать тупо на сдвиговых регистрах… Но я подумал, что мне будет лень каждый раз писать процедуру запихивания в них данных… ктому же, нужно постоянно помнить таблицу кодирования символов. А так намного проще — сказал переслать символ 'A' — на тебе, получи на экране символ А :) Так что, лично мне — так показалось немного более удобней.

регистры + инвертирующие и неинвертирующие буферы с третьем состоянием
Что за звери? В смысле, маркировка?
У меня первой мыслью было применить советские К176ИЕ4 — но их в смд достать мне нереал, а их забугорные аналоги отсутствуют в наших магазинах

шикарно было бы
слишком шикарно для копеечных ЖКИ)
0
Что за звери? В смысле, маркировка?
Я смотрел только импортные микросхемы. Поначалу думал обойтись одной — буфером с переключающим выводом с прямого сигнала на инверсный. Но такой ИМС в природе, как я понял, не существует, поэтому был вариант взять инвертирующий буфер с 3 состоянием и неинвертирующий, запараллелить их выходы и входы, а сигнал управления 3 состоянием подавать на них противофазный. Но в этом случае будут сложности с разводкой в SMD исполнении. В ДИПе можно было бы воткнуть эти буферы бутербродом в панельку, отогнув вывод управления.
Ну, или сделать всё на ПЛИСине =)
0
Ну, или сделать всё на ПЛИСине
кстати, да — я считаю был бы самый оптимальный вариант :) но в них я полный zero…
0
А я начал уже осваивать (собрал программатор и тестовую платку), но могу сказать что ПЛИСина в 44-х выводном корпусе стоит под 150 руб. =)
0
Прочитал с большим запозданием :) Хорошо что админ весь срач удалил.
Собственно к теме: я тут заканчиваю поделку с подобным управлением ЖКИ. Только у меня всем управляет Mega8515L — ног достаточно и спряталась она (DIP) под стекляхой, которая просто огромна (50х30). Так вот все это «ногодрыгание» я отдал таймерному прерыванию, что работает в режиме CTC. Меандр получается абсолютный, поскольку СТС-режим можно сравнить с чистым аппаратным генератором, а других прерываний нет.
Была и у меня мысль использовать эти же сдвиговые регистры и МК по-проще. Но из-за боязни деградации кристаллов (как уже замечено выше) отбросил ее.
Кстати о частоте переключений, производитель использованного мною ЖКИ рекомендует диапазон 30-100 Гц.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.