Easy_I2C AVR ASM практикум PCF8574 и немного мыслей о жк дисплеях + I2C-GPIO

AVR
Отредактировано 23.12.2013
PCF8574 это 8-битный расширитель ввода – вывода. Другими словами у нас появляется еще 8 ног
Эта микросхема проста как 3 копейки… и стоит так же. PCF8574 и PCF8574A отличаются «заголовочными» адрессами причем PCF8574 имеет тот же самый «заголовочный» адресс что и MCP23016 (я как то сразу и не подумал об этом поэтому у меня совпали сетевые адреса но слава богу переделал малой кровью)
Итак я взял 2-е PCF8574 и подключил одну на вход (8 кнопок на землю и подтяжка +5V на каждую ногу Р0-Р7), а другую на выход (8 светодиодов одной ногой к Р0-Р7 а другой через токоограничительные резисторы к +5V )
Здорово! теперь надо определится с тех. заданием. Ну чего-то больно уж сложного не придумаешь поэтому я решил его сформулировать так: За каждой кнопкой у PCF8574key закрепим соответствующий ей светодиод у PCF8574led те P0_key->P0_led итд. Каждое нажатие на кнопочку должно менять состояние соответствующего этой кнопочке светодиода те нажали — загорелся, нажали — погас. Таким образом мы должны запросить у PCF8574key состояние клавиш, инвертировать соответствующий бит и отправить результат в PCF8574led.
В схемотехнике я не силен, а с красочном их оформлении тем более. Вот что получилось
ВНИМАНИЕ!!! А1 У PCF8574 led НА СХЕМЕ УКАЗАНО НЕ ВЕРНО ПО ОТНОШЕНИЮ К МОЕМУ ПРОЕКТУ (РИСОВАЛ НА РАБОТЕ А ВСПОМНИТЬ НЕ СМОГ)


Как я уже говорил (в предыдущем посте) у PCF8574 есть нога INT которая предназначена для формирования прерывания по изменению на ногах Р0-Р7 а точнее по ЛЮБОМУ ИЗМЕНЕНИЮ ЛОГИЧЕСКОГО СИГНАЛА т.е если например нога Р2 была 0V а стала 5V или же была 5V а стала 0V то наша нога INT выдаст 0V. А чтобы это увидеть мы сделали подтяжку через резистор к 5V. Как только PCF8574key увидит что на шине I2C прозвучал ее адрес да еще и с запросом на чтение (младший бит в адрессе =1) то она успокоит ногу INT и там опять будет 5V от нашей подтяжки, однако PCF8574key успокоит ногу INT и в том случае если мы не успели у нее спросить «че случилось» а кнопочку уже отпустили т.е когда все ноги Р0-Р7 поднялись к 5V нога INT тоже станет 5V. Я не случайно выделил слово ЛЮБОМУ да потому что прерывание (при нажатии на кнопочку) возникнет 2 раза: когда нажали и когда отпустили. Теперь логично то что мы связали ногу PD2(INT0) у нашей МЕГИ16 и INT у PCF8574key. Дальше в программе нам необходимо инициализировать внешнее прерывание на PD2(INT0) по спадающему фронту. У меня это макрос int0_high_low

                CLRB	ddrd,2,temp
		SETB	portD,2,temp
		SETB	GICR,INT0,temp
		CLRB	MCUCR,ISC00,temp
		SETB	MCUCR,ISC01,temp

Теперь пропишем само прерывание. Я уже говорил про регистр в оперативе с незаурядным названием i2c_want_job в котором каждый бит это флаг-запрос на запуск I2C определенного задания. Бит №0 закреплен за PCF8574key. Вот именно этот бит и надо установить в прерывании INT0. Вот что получилось:
PUSHF    ;SREG +R16 в стек
SETB i2c_want_job,key_flag,temp    ;установить бит № key_flag.         key_flag это ничто иное как ноль и прописано в файле имен проэкта    
POPF     ;SREG +R16 достать из стека
RETI

Итак при нажатии и отпускании кнопочки у нас будет загораться нужный бит. Идем дальше. Теперь та самая программка которая запускает шину I2C на опрос PCF8574key для получения кода состояния клавиатуры. Ах да пока не забыл: нам понадобятся 2 регистра в оперативе. Один для принятого байта от PCF8574key и один для отправляемого байта в PCF8574led
.DSEG
		Key_status:		.byte	1	;
		Led_light:		.byte	1	;	

Итак програмка чтения PCF8574key
Key_opros:		
		lds temp,i2c_want_job	;проверяем флаги заданий по и2ц
		sbrs temp,key_flag	;начинаем с флага клавиатуры который формируется по спадающему фронту внешнего прерывания входящего от ноги INT микросхемы PCF8574key на ногу (INT0) PD2 нашей Меги16
		rjmp Led_opros	;если флаг нулевой то переходим к опросу следующего флага а иначе
		lds temp,i2c_busy	;сначала проверим флаг занятости и2ц и если он =0 то запускаем нашу и2ц, иначе прыгаем в начало или можно еще куданибудь но не надолго иначе просрем наше счастье ведь кнопку уже нажали
		tst temp
		brne Key_opros
		;ура шина свободна
		CLRB i2c_want_job,key_flag,temp		;сразу очистим key_flag поскольку шина стартанет после макроса
		I2C_GO_START_in 	PCF8574key, i2c_sarp, Key_status, 1,400 ;Макрос на прием данных : Имя микросхемы, задание, регистр приемник данных, число байт на прием, и последнее это скорость в кГц
		SETB i2c_want_job,led_flag,temp			;установим флаг нового значения для ледов т.е. Led_opros теперь заработает
		rjmp Key_opros	;просто как вариант перейдем в начало опроса - все равно пока прерывание и2ц не закончится мы ничего не отправим и не примим

Дальше идет програмка записи в PCF8574led — опрос флага led_flag в регистре i2c_want_job
Led_opros:	;теперь проверим а установлен ли флаг отправки нового значения в PCF8574led
		lds temp,i2c_want_job	
		sbrs temp,led_flag
		rjmp Key_opros			;перейдем в начало опроса если пусто					
		lds temp,i2c_busy	;проверяем флаг занятости и2ц
		tst temp
		brne Key_opros	;если что то на начало
		CLRB i2c_want_job,led_flag,temp		; сразу очистим флаг ледов
		;теперь проверим какое значение мы получили от клавиатуры и логично если там 0b11111111 то это прерывание вызвано тем что
		;мы отпустили клавишу и что-то делать нет необходимости тобиш в игнор такое задание
		lds temp, Key_status
		cpi temp,0xFF
		breq Lo1
		;прошли дальше значит шлем в PCF8574led
		;как вариант мы будем инвертировать тот лед клавиша которого была нажата для этого возмем последнее состояние ледов и проEОРим его по новому состоянию клавишь
		lds temp,Led_light
		lds temp2,Key_status
		com temp2					
		eor temp,temp2					
		sts Led_light,temp						
		I2C_GO_START_out	PCF8574led, i2c_sawp,Led_light, 1,400		;Макрос на отправку данных : Имя микросхемы, задание, регистр передатчик данных, число байт на отправку, и последнее это скорость в кГц
Lo1:		rjmp Key_opros ;шилио да мачало....


А все приехали программа кончилась описывать включение стека, очистку оперативы, sei я думаю не надо
Теперь просто покажу скриншот процесса опроса PCF8574key и записи в PCF8574led
канал 0 — сигналы по SDA зелененький кружек это стартовая команда а красный квадрат это стоповая команда
канал 1 — сигналы по SCL
канал 2 — сформированное прерывание INT в PCF8574key по нажатию кнопочки и погасшее по АСКу от PCF8574key
канал 3 — прерывание по I2C в МЕГЕ16 те высокий уровень сигнала это как раз таки и есть работа нашего прерывания (из цифр: прием отнимает 111 машинных тактов а отправка 125)
канал 4 — это работа вот тех 4 строчек обработки внешнего прерывания INT0 в МЕГЕ16
Да не так крупно как может быть хотелось.



Как и полагается в архиве проект под названием i2c_key_to_led_pcf8574 написан в студии6 (для студии4 наверно надо вручную перетащить все .asm .inc файлы в свой проект).

Так теперь выскажу немного мыслей о спаривании жк дисплеев и I2C-GPIO обсуждалось здесь
Сам процесс спаривания может быть интересен но наверное недостаточно практичен. Тем не менее у меня в планах прикрутить ГРАФИЧЕСКИЙ 128х64 дисплей к MCP23016 (там вроде 14 IO надо) и подурачится с графиками температуры.
Если кто знаком с последовательностью работы с дисплеем (неважно знакосинтезирующий или графический) и понимает то насколько не проста шина I2C — 150 раз подумает а стоит ли спаривать не только их но и себе мозг. Наверное 60% проблем начинаются когда думаешь о ноге «Е» (строб записи) которая заставляет тебя по нескольку раз отправлять одни и те же данные в I2C-GPIO. Проанализировав порядок действий у меня получилось что для записи 8 пикселов в дисплей мне прибется передать 3 раза по 2 байта причем 2 раза из-за гр… ебаного «Е». В схемотехнике я реально далеко не спец и ничего придумать не смог… Зато я смог нагрузить своего электронщика этим заданием — мол так и так надо вот получить строб, есть 2 свободных ноги у I2C-GPIO там как нибудь чето надо сделать. Выслушав меня и со словами «Тоже мне шарада, ты как школу закончил?» рисует мне вот такую схему
Потом он мне объяснил как там заряжается-разряжается и я понял что не все уж так и плохо. И в результате почитав в 100 раз даташит я понял что мне этот строб надо сдвинуть чуточку те пустить с опозданием. Есть формула Время строба = 0.7*R*C и вот родилось такое чудо схемотехники

Кондеры я беру одинаковые 1нФ, а резисторы один 4700 другой 1500 Ом. В результате на каждом элементе XOR у нас формируется импульс. Для первой это 3мк секунды (Т1) а для второй 1мк секунда (Т3). Дальше пройдя через третий XOR они вычитаются и в реальности получается задержка обозначенная Т3 а время импульса Т2=Т1-Т3
Таким образом получается что для записи 8 пикселов мне надо лишь 1 раз отправить 2 байта (в которых бит«Е»допустим =1), для записи следующих 8 пикселов надо тоже отправить 2 байта но бит «Е» необходимо ИНВЕРТИРОВАТЬ и так далее. В результате выстраивается поток данных (всего 2048 +-) и во время передачи следующей пары байт дисплей съедает принятые а это уже достаточно легкий код. Для знакосинтезирующего дисплея (не важно как писать — по 4+4 PCF8574 или сразу 8 MCP23016) данный подход тоже должен работать, а если так то например выгрузка «видеопамяти» 80байт в дисплей 20х4 проста как никогда. Кстати эта 4хXOR микросхема мне обошлась 15 руб. И если она оправдает мои ожидания то это здорово. Прилагаю снимок с лог анализатора реальных сигналов и по названиям каналов вроде все должно быть понятно
В ближайшее время подготовлю статью о часикак DS1307 все на том же прерывании.
  • +1
  • 19 декабря 2013, 12:57
  • deses
  • 1
Файлы в топике: i2c_key_to_led_pcf8574.zip

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

RSS свернуть / развернуть
Вот что получилось
так верстают только мудаки(с)
0
Выслушав меня и со словами «Тоже мне шарада, ты как школу закончил?»
ты у него спроси, как он быдловуз закончил и как его на работу взяли с таким подходом
укорачивать код за счет добавления целой мелкасхемы и рц цепочек? так может делать только идиот
что тебе мешает выставлять е и строб без этих соплей? управление жк индикатором работает по двум проводам через 1 простой регистр + у меня там еще несколько кнопок
-2
Калыч, у тебя самого ни одной нормальной публикации, тока и можешь срать в комментах, иди лучше дальше подорожник жуй…
+2
Ну насчет текста он прав же. Правда, текст страдает не только и не столько оформлением, сколько нечитабельностью.
Да и подобные фокусы с лишними корпусами и RC-цепочками я тоже не одобряю. Лучше уж вывести лишнюю линию от строба в обход расширителя.
0
Да это понятно, просто бесит подобный тон… «Вы все талпайопы а я Прынц»
0
советую принимать баттхертин в анальных свечах, дабы не беситься
не все люди ведут себя как ты привык видеть в своем сферическом вакууме
0
тематика моих занятий не совпадает с тематикой сего сообщества
25 лет я нюхал канифоль, теперь вот другим занимаюсь
0
А своих или других мыслей нет? от канифоли не отошел? Ты если такой умный взял бы и «нарисовал» правильную схему а я бы ее подменил на свою. А я понял, я же у тебя корочку хлеба отобрал или чо. Вообще я уже начинаю привыкать что комментарии в «СООБЩЕСТВЕ» сводятся к СКОТСКОМУ отношению к работе других… вместо того чтобы поправить, помочь сделать красочно или просто промолчать. Я предлагаю открыть отдельную тему «ЗДЕСЬ ОБСУЖДАЕМ МУДАКОВ» а то моя тема затрется и через пару недель твоя пена у рта не будет доставлять столько кайфа.
0
ты воспринимаеш все слишком близко к жопе, в то время как я не имел никакого желания обосрать тебя или твою работу
я просто написал прикольный камент и дал тебе понять, что не твоя схема неправильна, а нарисована она не по общим стандартам

А я понял, я же у тебя корочку хлеба отобрал или чо.
какую ты корочку хлеба у меня отобрал? я вообще не понял тебя
у меня нельзя отобрать корку хлеба, т.к. тут не биржа фрилансеров

вместо того чтобы поправить, помочь сделать красочно или просто промолчать
я тебе дал понять, что твоя схема нарисована нет и ты мог бы сам догадаться
ты же видел схемы других людей? где ты видел там цветные провода? где ты видел там линии под углами?
я тебе просто словами классика дал понять и все, а ты понял так, что я тебя обосрал
можеш порадоваться — я с 14 лет ассемблер учил и за 20 лет не умею писать на нем, я тупой быдлокодер и не умею программировать и никогда не смогу
ну и это… смысл клиавитурной обезьяны в электронике сводится к тому, чтобы обезьяне с паяльником было как можно меньше работы, чтобы дрессировщик смог потратить на быдлодевайс как можно меньше бабла и поиметь как можно больше профита без поднятия конечной цены

поэтому в схему не нужно вводить дополнительных деталей, а нужно оптимизировать быдлокод
и упаси б-г использовать в цифровой цепи аналоговые компоненты
я посылал данные по одному проводу в индикатор на 4х регистрах и изменение температуры на 10-15 градусов уводило параметры рц цепочки и схема переставала работать
это был чисто прикол и он описан у меня на сцайте, поэтому используется всегда линия тактирования или же временные интервалы формируются на базе кварцевого генератора, как это в термометре 1wire, где параметры генератора не уходят даже при колебаниях температуры -50 до 125, типа задержки там формируются не аналоговыми цепями

поэтому я про быдловуз и спросил
конечно твои исследования прикольны, но на практике так не надо делать — это и был смысл моего камента
ну а если он тебе не понравился, то вон можно нажать на кнопочку и опустить меня
+1
подключил одну на вход (8 кнопок на землю и подтяжка +5V на каждую ногу Р0-Р7)
Насколько я помню, у этих расширителей «квази-двунаправленный порт» а-ля 8051. Т.е. подтяжка уже есть встроенная. Хотя внешняя хуже не сделает, внутренняя довольно слабая. Аналогично INT можно было подтянуть встроенной подтяжкой атмеги, хотя если линия до нее длинная, то встроенной может и не хватить.

Ну и так схемы рисуют только мудаки.
0
  • avatar
  • Vga
  • 20 декабря 2013, 01:34
Ну и так схемы рисуют только мудаки.
Или человек «программист» и банально пока не въехал в рисование схем, не участвовал в обсуждениях чужих схем, и просто не знает как противно читать «кривульки»… А в будущем возьмет sPlan хотябы для начала и назберется…
0
и просто не знает как противно читать «кривульки»
Ну, теперь знает)
0
хотелось бы увидеть обратную сторону этой платки…
0
Хочется острых ощущений? )
0
Key_opros:              
                lds temp,i2c_want_job   ;проверяем флаги заданий по и2ц
                  ..........
                lds temp,i2c_busy       ;сначала проверим флаг занятости и2ц 
                

Чем они отличаются?
Key_opros:              
                lds temp,i2c_want_job   ;проверяем флаги заданий по и2ц

И буквально на следующем шаге
Led_opros:      ;теперь проверим а установлен ли флаг отправки нового значения в PCF8574led
                lds temp,i2c_want_job

Зачем?
И и2ц глаза режет
0
i2c_busy это регистр который отвечает за то что в данный момент идет передача по шине и2с те как только началась передача или прием то он =1, когда передача завершится (те все получили или отправили, с ошибкой или без неё) он станет равным 0. И только теперь можно запускать шину на новое задание. А сами задания хранятся в i2c_want_job т.е. каждый бит этого регистра закреплен за каким-то заданием. Если например бит № 0 =1 то это значит что необходимо запустить шину на опрос клавиатуры и тд.
И и2ц глаза режет
ну… сам не в восторге
0
Т.е i2c_busy — целый регистр отвечает за то, что шина занята? Или в нем есть разбивка, кем занята?
Судя по команде tst — всё таки целый.
Я бы использовал флаг T регистра SREG для которого есть набор команд для установки, снятия и проверки его состояния.
0
Да целый.
Конкретно в этом случае можно хоть как поскольку программа пустая, места много и тд а так в программах побольше лично мне флаг Т жалко тратить ради «мелкого» контроля, часто пользуюсь BLD BST
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.