Автор Тема: Программирование ps/2 клавиатуры и пищалки для AVR  (Прочитано 17593 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Программирование 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 где есть код, написанный на С, в чем разработчики честно сознаются. Хотелось все бросить и написать свой драйвер клавы, с блэкджеком и шлюхами, то есть с буфером, таймаутом по таймеру и контрольной суммой, но леееееень.

Из предыдущего примера ясно, что обработчик прерывания надо все-таки иногда запрещать. И вот дилемма – С одной стороны всегда работающий обработчик – гуд – не проворонишь начала приема символа. А с другой стороны плохо: пока что-нибудь долгое делаешь – он внезапно придет, как северная лиса,  и все попортит. 

Тогда пока остается один промежуточный вывод – разумно отключать все-таки прерывания иногда, но обработку символа делать максимально быстро, пока клава не сгенерила следующий.    В том числе и пищать пищалкой . Сделал такой учебно-исследовательский пример:
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Цитировать
Код:
$regfile = "m32def.dat"
$baud = 9600
$crystal = 11059200


 \'- - - - - - - - - - - - - - - - - - - - -
    LSD:
$lib "lcd4.lbx"                                             \'используем 4-х битное подключение дисплея с помощью альтернативной библиотеки
Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.2 , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7
Config Lcd = 16 * 2
 \'- - - - - - - - - - - - - - - - - - - - -
Config Keyboard = Pind.2 , Data = Pind.4 , Keydata = Keydata
Speaker Alias Portd.6
 \'- - - - - - - - - - - - - - - - - - - - -
Dim B As Byte
Dim Bsimvol As String * 1
Dim Bznac As Byte

Print "OK"

Enable Interrupts

On Int0 Kbd


Cls

B = 0
Disable Int0


Do
Gosub Kbdinput
If B <> 0 Then
Cls
Locate 1 , 1
Lcd B
End If
Loop




Pik:
Sound Speaker , 10 , 947
Return


Kbd:
B = Getatkbd()
Return


Kbdinput:
B = 0
Enable Int0
Do
Loop Until B <> 0
Disable Int0
Bsimvol = Chr(b)
Bznac = Val(bsimvol)
Printbin B
Gosub Pik
Return


Keydata:

\'normal keys lower case
Data 0 , 0 , 0 , 0 , 0 , 200 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , &H5E , 0       \'
Data 0 , 0 , 0 , 0 , 0 , 113 , 49 , 0 , 0 , 0 , 122 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 0 , 0 , 32 , 118 , 102 , 116 , 114 , 53 , 0       \'
Data 0 , 110 , 98 , 104 , 103 , 121 , 54 , 7 , 8 , 44 , 109 , 106 , 117 , 55 , 56 , 0       \'
Data 0 , 44 , 107 , 105 , 111 , 48 , 57 , 0 , 0 , 46 , 45 , 108 , 48 , 112 , 43 , 0       \'
Data 0 , 0 , 0 , 0 , 0 , 92 , 0 , 0 , 0 , 0 , 13 , 0 , 0 , 92 , 0 , 0       \'
Data 0 , 60 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0       \'
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0       \'

\'shifted keys UPPER case
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0       \'
Data 0 , 0 , 0 , 0 , 0 , 81 , 33 , 0 , 0 , 0 , 90 , 83 , 65 , 87 , 34 , 0       \'
Data 0 , 67 , 88 , 68 , 69 , 0 , 35 , 0 , 0 , 32 , 86 , 70 , 84 , 82 , 37 , 0       \'
Data 0 , 78 , 66 , 72 , 71 , 89 , 38 , 0 , 0 , 76 , 77 , 74 , 85 , 47 , 40 , 0       \'
Data 0 , 59 , 75 , 73 , 79 , 61 , 41 , 0 , 0 , 58 , 95 , 76 , 48 , 80 , 63 , 0       \'
Data 0 , 0 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 0 , 13 , 94 , 0 , 42 , 0 , 0       \'
Data 0 , 62 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 , 0       \'
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0       \'


Работает идеально – как бы я не тыкал по кнопкам в клаве – все отображается и выводится в ком порт без ошибок. Но когда этот код впихал в реальный проект – глюки пошли как и раньше, ну может чуть поменьше. Там ведь не просто надо вывести символ на экран и в порт, там жуткая обработка идет.  Отказался от команды Sound – сильно она долго работает, достаточно дернуть мембранкой пищалки в течении одной миллисекунды.
Цитировать
Код:

Kbdinput:
B = 0
Gifr = 64
Enable Int0
Do
Loop Until B <> 0
Disable Int0
Bsimvol = Chr(b)
Bznac = Val(bsimvol)
Printbin B
Speaker = 1
Waitms 1
Speaker = 0
Return


И все заработало вроде нормально. Дальнейшие испытания покажут, а мне интересно ваше мнение.


Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Байкер

  • Эксперт
  • *****
  • Сообщений: 575
  • Карма: 0
  • Пол: Мужской
  • Хуже нет, чем не знаешь, да ещё забудешь...
    • Просмотр профиля
Старик!
Ни фига я , честно, в этом не понимаю серьёзно  (специализация другая)....
Но за рвение и старание - снимаю шляпу (без задолижства и без прикрас).
Молодца!
Стать Учеником - просто поворот в Судьбе, быть Учителем - Дар и Проклятие Небес... Терпите  тупость Ученика...Ведь все мы чьи-то Ученики...  
       С уважением, Байкер!

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
Сорри за отсутствие, времени не было.

По теме.
Если делать по науке, надо организовать буфер клавиатуры, типа FIFO (first in – first out).
Обработчик прерывания добавляет в буфер очередную кнопку, если нет места в буфере – игнорирует нажатую кнопку.
Основной код в своем цикле извлекает из буфера очередной символ и обрабатывает его.
В простейшем случае буфер может иметь длину в один символ.

Например так:

Цитировать
\' B - это будет типа буфер
\' BCurr - текущий обрабатываемый символ, т.к. основной
\'         код не должен работать с буфером напрямую
\' Dummy - просто переменная

Dim B As Byte      
Dim BCurr As Byte
Dim Dummy As Byte    

\' Включаем прерывания и вешаем обработчик на клаву
\' Надеюсь правильно этот кусок написал ))

Enable Interrupts
On Int0 Kbd
Enable Int0

\'======= Как бы основной код =================
Do
If B <> 0 Then \' Если в буфере что-то есть,
BCurr = B      \'   то забираем символ в BCurr,
B = 0          \'   сбрасываем буфер
\' ..............................................................
\' .... Делаем обработку уже символа "BCurr", который не испортится, в "B" уже не лезем.
\' .... Рисуем на экране и т.д. Можно здесь пикнуть.
\' ..............................................................

End If
Loop
\' ============================================

\' Обработчик клавиатуры. Если буфер пуст (равен 0) загоняет в него нажатый символ,
\' иначе игнорирует нажатие

Kbd:
If B <> 0 Then \' буфер свободен
B = Getatkbd() \' загоняем в него символ
\' Здесь можно пикнуть
Else           \' буфер занят
Dummy = Getatkbd()  \' пропускаем нажатую кнопку
End If
Return
В результате чего, пока буфера не пустой, то новые нажатия будут игнорироваться. И обрабатываемый в текущий момент символ не будет неожиданно изменен на полпути, так как вся обработка идет над BCurr, который недоступен обработчику прерывания.

Но с другой стороны, если работет более простой код, то и усложнять не надо.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Интерестно, обязательно попробую, у меня была подобная мысьль об этом, но я ее почему-то забраковал и в код она так и не отлилась...
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Форум проекта "Минилаб-Мастер"


Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Попробовал твой пример, он немного не так работает как надо, видимо надо
Kbd:
If B <> 0 Then

исправить на

Kbd:
If B = 0 Then

Немного изменил идиологию алгоритма, игнорируем символы в прерывании, пока не обработаем переменную. Поменял местами переменную буфера и символа, так мне удобнее. Пока код не дает сбоев в учебном примере, буду эксперементировать.  Зацени:


Цитировать

Enable Interrupts

On Int0 Kbd                                                 \' обработчик прерывания

Cls

Bcurr = 0                                                   \'обнуляем переменные
B = 0


Enable Int0                                                 \'включаем прерывания

\'Главная программа
Do
Gosub Kbdinput                                              \'Уходим в подпрограмму приема символа
Cls
Locate 1 , 1                                                \'Типа печатаем символ
Lcd B


B = 0                                                       \'Разблокируем следующий цикл приема символа, пока не 0 прерывания работают вхолостую
Loop






\'Подпрограмма взятия символа из прерывания и предварительной обработки
Kbdinput:
Do
Loop Until Bcurr <> 0                                       \'ждем пока символ не упадет в буфер
B = Bcurr                                                   \'Буфер присваиваем универсальной переменной
Bcurr = 0                                                   \'Очищаем буфер
Bsimvol = Chr(b)                                            \'Всякая предворительная обработка символа
Bznac = Val(bsimvol)
Printbin B                                                  \'Контрольная печать в ком порт
Gosub Pik                                                   \'Пищим
Return

\'Обработчик прерывания
Kbd:
If B = 0 Then                                               \'Переменная пуста, можно заполнять буфер                                           \' буфер свободен
Bcurr = Getatkbd()                                          \' Что и делаем
Else                                                        \' Иначе
Dummy = Getatkbd()                                          \' Игнорируем все, пропуская символы
End If
Return


\'Пищалка
Pik:
Sound Speaker , 10 , 947
Return

Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Но код далеко не идеален, мне нужно свободно либо ожидать ввода символа, либо брать его из прерывания напрямую. Например тикает счетчик секунд и его надо прервать с помощью прерывания в любой момент.... Буду думать, наводка на буфер очень перспективна на мой взгляд.
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
Все правильно. Но ты изменил принцип организации ввода. Можно его назвать "real-time", что-ли, или "синхронным". В играх примерно так ввод устроен. Тебе, возможно, так и нужно. У тебя буфер перестал быть буфером. Обработчик прерывания ориентируется не на "свободность" буфера, а на состояние некоторого флажка, роль которого исполняет B, разрешая или блокируя ввод.

Таким образом очистка буфера (Bcurr = 0) теряет смысл, свободен он или нет нигде не проверяется. Более того, от Bcurr можно вообще избавиться. Так как обработчик заполняет "буфер" только при B = 0, то он может совать символ прямо в B, без промежуточного Bcurr.

Цитировать
Enable Interrupts

On Int0 Kbd                                                 \' обработчик прерывания

Cls

B = 0

Enable Int0                                                 \'включаем прерывания

\'Главная программа
Do
Gosub Kbdinput                                              \'Уходим в подпрограмму приема символа
Cls
Locate 1 , 1                                                \'Типа печатаем символ
Lcd B


B = 0                                                       \'Разблокируем следующий цикл приема символа, пока не 0 прерывания работают вхолостую
Loop

\'Подпрограмма взятия символа из прерывания и предварительной обработки
Kbdinput:
Do
Loop Until B <> 0                                           \'ждем пока символ не упадет в B
Bsimvol = Chr(b)                                            \'Всякая предворительная обработка символа
Bznac = Val(bsimvol)
Printbin B                                                  \'Контрольная печать в ком порт
Gosub Pik                                                   \'Пищим
Return

\'Обработчик прерывания
Kbd:
If B = 0 Then                                               \'Переменная пуста, можно заполнять B
B = Getatkbd()                                              \' Что и делаем
Else                                                        \' Иначе
Dummy = Getatkbd()                                          \' Игнорируем все, пропуская символы
End If
Return


\'Пищалка
Pik:
Sound Speaker , 10 , 947
Return
« Последнее редактирование: 28 Сентября 2010, 20:50:33 от pumpkin »

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
Цитировать
Например тикает счетчик секунд и его надо прервать с помощью прерывания в любой момент.... Буду думать, наводка на буфер очень перспективна на мой взгляд. 
Точнее назвать это флагом, я думаю, который устанавливается по прерыванию, а счетсик проверяет его состояние постоянно. А можно и прямо в обработчик прерывания воткнуть вызов тормоз счетчика. Вариантов как всегда уйма :)
« Последнее редактирование: 28 Сентября 2010, 18:44:17 от pumpkin »

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Cовершенно верно, флаг. Пока код отлично работает, даже в проекте. Единственно B = 0  впихал внутрь подпрограммы Kbdinput, для крастоты и автоматики. Все вроде пока красиво.

С буферами будет позже топик. Буфер ком порта и организация протокола, сейчас работаю над этим. А где буфер ком порта там и тайм-аут. А где тайм-аут, там и таймеры. Сейчас неплохо в них разобрался, классная вещь! Спасибо, pumpkin! Все круто!
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Форум проекта "Минилаб-Мастер"


Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Сегодня код прошол проверку в реальных боевых условиях, пока ошибок нет! Тихо радуюсь...

А пока филосовское отступление. Флаги - это сила! Они, плюс таймера и прерывания - основа операционных систем с вытясняющей многозадачностью и всем таким. Юзайте флаги - и будет вам Щасте!

У уважаемого DIHALT-а есть отличный набор статей на эту тему, с удовольствием сошлюсь:

http://easyelectronics.ru/avr-uchebnyj-kurs-arxitektura-programm.html#more-279

http://easyelectronics.ru/avr-uchebnyj-kurs-arxitektura-programm-chast-2.html#more-288

http://easyelectronics.ru/avr-uchebnyj-kurs-arxitektura-programm-chast-3.html#more-290

Я, как начинающий быдлокодер завис где-то между первым и вторым уровнем, но с интересом поглядываю на третий - флаговые автоматы. Но стараюсь писать свой код молульно, и нововведения встраиваются в код проекта легко, радуя внезапным уменьшением скомпиллированого кода и изчезновением глюков.

Терпеть не могу си, за его птичий синтаксис, бейсик это мое все, и что на нем можно делать красивый код уже доказано для меня. Например то же меню. Сравните сишное меню у того жеDIHALT-а

http://easyelectronics.ru/organizaciya-drevovidnogo-menyu.html#more-316

и баскомовское нано меню за авторством pumpkin-а и меня  :-[ (типа примазался)

http://minilabmaster.com/cgi-bin/yabb2/YaBB.pl?num=1246889930/0

  так же хочу выразить огромную благодарность pumpkin-у за профессионализм и поддержку.
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Предыдущие разборки с прерыванием и клавиатурой не прошли даром, все работает. Но иногда, когда дивайс держит паузу и считает секунды, заодно и опрашивая переменную b, где хранится принятый байт с клавы, дивайс зависает. Такое ощущение, что клава, от нечего делать дергает сигналом, дивайс уходит в прерывание, а там ничего больше нет. Глюк непостоянный и трудноотлавливаемый. Чортова функция Getatkbd() улетает в транс, таймаута у нее нет. В мануале написано, что вывести ее из транса можно установив Set ERR в прерывании, например, а у меня уже эта функция из прерывания вызывается. Посему такой вопрос - Как правильно организовать прерывание в прерывании? Слышал это возможно, но толком описания нет.

Хелп, плиз. Алгоритм должен выглядит примерно так - нажата кнопка, по int0 уходим на обработчик, в нем включаем снова прерывания, запускаем таймер 0 который при переполнении тупо включает Set ERR. Уходим в  Getatkbd().
« Последнее редактирование: 24 Мая 2012, 07:54:32 от admin »
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Кажися я сделал это! мне удалось скрестить ежа с ужом - сделать прерывание в прерывание - таймаут. Обернул Getatkbd()  в ассемблерный код, который позволяет делать это. Сейчас клавиатуру можно тыкать туда-сюда - и ничего не зависает, а раньше зависало! Я доволен как слон, если интересен код - выложу. Буду тестить в боевых условиях.
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

pumpkin

  • Модератор Раздела
  • Профи
  • *
  • Сообщений: 240
  • Карма: 2
  • Пол: Мужской
  • Это Я :-)
    • Просмотр профиля
Выкладывай. Интересно  :)

Andy

  • Администратор Форумa
  • Эксперт
  • *
  • Сообщений: 1803
  • Карма: 15
  • Пол: Мужской
  • Нельзя отремонтировать то, что не сломано...
    • minilabmaster
    • Просмотр профиля
    • Форум "Минилаб-Мастер"
Итак, надо не дать зависнуть функции Getatkbd(), разработчики пердусмотрели ее аварийное завершение при установки флага ERR в 1.

Конфигурим наш чип и прерывания, чип - Atmega128. Некоторые функции ассемблера заточены только под него, курите даташит на ваш чип, в комментах будет указано.
Цитировать
$crystal = 11059200                                         \'Кварц- 11,0592 МГц          .
$regfile = "m128def.dat"
$hwstack = 100                                              \' Размер аппаратного стека
$swstack = 50                                               \' Размер программного стека
$framesize = 50                                             \' Размер фрема

\'------Клавиатура Ps/2 -прерывание Int4 ------------------------------------
Config Keyboard = Pine.4 , Data = Pine.3 , Keydata = Keydata

\'------Кофигурим  таймер и время таймаута - 6 миллисикунд, программе обработки пофиг какой предделитьель здесь стоит, он задается стартом таймера на асме, смотрите ниже.  
Config Timer0 = Timer , Prescale = 256   \'Поэтому эта строка не обязательна, но после нее таймер сразу стартует!                   
On Timer0 Tout Nosave  \' В принципе можно отставить только эту строку
Stop Timer0  \'Останавливаем его
Timer0 = 0    \'Обнуляем
Disable Timer0  \' И отключаем нафиг.

\'------Конфигурим обработчик прерывания клавиатуры
On Int4 Isr4 Nosave
Disable Int4

\'-----Обработчик прерывания таймера----
Tout:
Set Err     \'Ставим ERR в 1
Return


Цитировать
 
\'Подпрограмма взятия символа из прерывания и предварительной обработки
Kbdinput:
\'Cursor On
B = 0
Enable Int4
Do
Loop Until B <> 0                                           \'ждем пока символ не упадет в B
Disable Int4
Bsimvol = Chr(b)                                            \'Превращаем принятый код в символ
Bznac = Val(bsimvol)                                        \'Превращаем принятый символ в число                                                           \'Контрольная печать в ком порт
Gosub Pik                                                   \'Пищим
Return

\'Обработчик прерывания INT4
Isr4:
$asm
 push r16           \' Сохраняем регистры
 push r25
 push r26
 push r27
 push r24
 in r24,sreg
 push r24
 in r24,EIMSK     \' И конфигуратор внешних прерываний, КУРИТЕ даташит на чип!
 push r24
 in r24,Eifr         \' И регистр статуса внешних прерываний, КУРИТЕ даташит на чип!
 push r24

 \'----Отключаем INT4!
  in  r25,EIMSK
  cbr  r25,16
  Out Eimsk , R25

 \'----Обнуляем Timer0
  ldi  r25,0
  Out Tcnt0 , R25


 SEI      \'Вот теперь можно снова включить прерывания!

 \'----Включаем  Timer0--
  in  r25,TIMSK
  sbr  r25,1
  Out Timsk , R25

 \'----Стартуем Timer0, сдесь можно изменить предделитель 6 - 256 4 - 64 2 - 8 КУРИТЕ даташит!
  in  r25,TCCR0
  sbr  r25,6
  Out Tccr0 , R25

 rCall Getsymbol        \' Вызываем Getsymbol, которая вызывает Getatkbd(), сразу отюда у меня вызвать не получилось, возможно получится у вас. Вызывать надо так - rCall _Getatkbd

 CLI             \'Отключаем прерывания




 \'----Останваливаем  Timer0--
  in  r25,TCCR0
  cbr  r25,7
  Out Tccr0 , R25

\'  ----Отключаем Timer0-
  in  R25,TIMSK
  cbr  R25,1
  Out Timsk , R25

   \'----Обнуляем Timer0
  ldi  R25,0
  Out Tcnt0 , R25

 pop r24
 !out Eifr,r24              \'Восстанавливаем регистры
 pop r24
 !out eIMSK,r24
 pop r24
 !out sreg,r24
 pop r24
 pop r27                                                   
 pop r26
 pop r25
 pop r16
 $end Asm
 Return


\' Воспомогательная функция, напрямую компилятор выдавал ошибку, хотя в помощи эта функция вызывалась напрямую, возможно проблема в конкретном коде.
Getsymbol:
B = Getatkbd()
Return



« Последнее редактирование: 27 Мая 2012, 08:01:45 от admin »
Заклинило деталь - надави на нее, если она сломалась - ничего, ее все равно надо было менять.

Форум проекта "Минилаб-Мастер"