Программирование ps/2 клавиатуры и пищалки для AVR
Казалось бы чего проще – в средствах разработки для контроллеров стандартная PC клавиатура и пищалка всегда имеет свои готовые библиотеки. Так как я юзаю Bascom AVR то и буду писать на нем и о нем. Но реализация в конкретном устройстве попила мне не мало крови. Вроде задача простая- каждое нажатие клавиш сопровождается пиком. Очень удобная обратная связь для юзера Дивайса. Но на практике это глючит самым подлым образом – устройство то нормально воспринимает символы с клавы, то за место одних символов печатает другие, то замрет на некоторое время или вообще зависнет. Или само нажмет Enter два раза, когда не просят. Чего только я не делал – грешил на плохую развязку земли – динамик-пищалка потребляет значительный ток, и хотя развязана транзистором от контроллера, все равно по земле шумит наверняка. Наставил конденсаторов – не помогает. Дивайс питается по USB, на нем максимум 300 миллиампер можно взять – а на нем дисплей висит, одна подсветка которого жрет 160 миллиампер, 40 динамик, клавиатура да сам контроллер со светодиодами, хорошо, что все не одновременно мощу потребляет. Вооружась знаниями по разводке плат, сделал все по науке – нисколько не помогло. Даже запитывание Дивайса от дорогих пятивольтовых блоков питания.
В конце концов уперся рогом в программную часть. Чего я только не делал с многострадальной функцией B = Getatkbd()! Юзал ее с прерываниями и без, ставил всевозможные задержки. Не помогало НИЧЕГО! Вроде все нормально работает, но потом снова начинает безбожно глючить. Изучив матчасть начинаю понимать, что все не так просто с клавиатурой. Вся проблема по моему текущему мнению – рассинхронизация клавы и Дивайса. И самая главная проблема – быстроте обработки принятых символов. Чуть затянул с ней, отвлекся контроллер на генерение звука, прорисовку символов на экране, рассовывания принятого символа по переменным и обработке а здесь юзер уже новую кнопку нажал. Пошла синхронизация от клавы, а контроллер еще не готов его принять. Тупой клаве пофиг, она продолжает отдавать байт скан-кода, когда наконец контроллер, сделав свои дела, уходит на подпрограмму приема байта с клавы. Принимает остатки байта и гордо выводит его на экран и записывает эту чушь в переменные.
Казалось бы – надо юзать прерывания и будет ЩАСТЬЕ. Но не все так просто. Гад-обработчик прерывания лезет своим рылом в самый неподходящий момент:
Код:
B = 0
Enable Int0
Do
If B <> 0 Then
Cls
Locate 1 , 1
Lcd B
Printbin B
B = 0
Gosub Pik
End If
Loop
\'Обработчик прерывания клавиатуры – INT0
Kbd:
B = Getatkbd()
Return
В данном примере все вроде кучеряво, но прерывание может произойти ВНЕЗАПНО, когда контроллер рисует символ на экране например…
Естественно, реализация библиотеки с ps/2 клавой у BASCOM-а далека от идеала. Но она упрощенно адаптирована с мануала ATMEL где есть код, написанный на С, в чем разработчики честно сознаются. Хотелось все бросить и написать свой драйвер клавы, с блэкджеком и шлюхами, то есть с буфером, таймаутом по таймеру и контрольной суммой, но леееееень.
Из предыдущего примера ясно, что обработчик прерывания надо все-таки иногда запрещать. И вот дилемма – С одной стороны всегда работающий обработчик – гуд – не проворонишь начала приема символа. А с другой стороны плохо: пока что-нибудь долгое делаешь – он внезапно придет, как северная лиса, и все попортит.
Тогда пока остается один промежуточный вывод – разумно отключать все-таки прерывания иногда, но обработку символа делать максимально быстро, пока клава не сгенерила следующий. В том числе и пищать пищалкой . Сделал такой учебно-исследовательский пример: