Свежие обсуждения
Микроконтроллеры

Ликбез по программированию PIC , vol. # 2

1 6 17

DWD: Радио №8, 2000г., стр.30
Спасибо, вечером посмотрю!

 

to Левон:
диодов в схеме picmaniac 3, на трех выходах, для защиты от выжигания выводов порта при двух нажатых кнопках, когда образуется КЗ между выводами с нулем и единицей.
еще там 4 резистора на входах, на мой взгляд лишних - защищать входы не от чего, а 220 ом по сравнению с 50 ком на внутренних подтягивающих ничего и не дадут.
так что три выхода и четыре входа с тремя диодами и 12 кнопок.
В результате контроллер сможет однозначно определить ситуации:
- ничего не нажато
- нажата одна и какая
- нажато две и какие
- нажато больше двух, но уже не известно каких
Программно два последних варианта можно и не обрабатывать (считать в этих случаях, что нажато 0 ), а кнопки на клавиатуре нажимать одним пальцем

 

ну вот, первая программа для PIC готова оцените
в программе реализовал:
- считывание кода с клавиатуры 4 строки 3 столбца и вывод его на семисегментный индикатор с общим анодом (не уверен в правильности названия - вроде анод это "минус", а здесь общий "плюс") (клавиатуру подключил к PORTB, индикатор к PORTA)
- сделал модель для протеуса (даже три, с разным количеством диодов) - работает
(глюки в моделях без и с 4-я диодами при нажатии трех и более клавиш объясняются фантомами - программную защиту делать не стал, наоборот, хотел, чтобы принимались символы каждой нажатой клавиши (это давняя мечта - так надоела блокировка компьютерной клавиатуры в играх ))
- при чтении клавиатуры:
-- учтен дребезг контактов
-- "*" - обнуляет уже введенный код
-- "#" - завершает ввод кода без набора установленного в программе количества символов
-- цифровые кнопки - ввод символа
- вроде неплохое описание всех ассемблерных инструкций (на описание потратил столько-же, сколько и на программу )
Программа работает по алгоритму:
- опрос клавиатуры и заполнение 8 разрядных буферов для каждой клавиши
- если в буфере появилось B'11111111' - значит восемь циклов назад была нажата клавиша - записываем или обрабатываем символ
- если B'00000000' - клавиша была отпущена
В 194 строке устанавливается количество вводимых символов = от 1 до 16 (сейчас 6). Если нужно больше 16, надо добавить регистров ОЗУ для их хранения.
В 226 строке стоит задержка между выбором считываемой строки. При текущей задержке время выполнения основного цикла примерно 1 секунда. В результате можно поэкспериментировать с дребезгом контактов. Для нормальной работы эту задержку нужно убрать.

42357.rar

 

Солидно. Достаточно сложно. Хорошие комментарии.

Я тут немного поразмыслил над техзаданием. Если делать по предложенной мною
http://www.pic16.nm.ru/likbez2/ButtonMatrix5.gif
схеме с тремя диодами, то идея возникла такая - зарезервировать в ОЗУ контроллера 3 регистра (к примеру, С1, С2, С3 их назвать). Затем настроить RB4-RB7 на вход, RB1-RB3 на выход. Выставлять поочередно лог.0 на выходах RB1, RB2, RB3 и считывать состояние входов PORTB. Сохранять состояние входов в регистрах С1, С2, С3 для первого, второго и третьего столбца соответственно. При этом лог.1 в старших полубайтах будут соответствовать отпущенным кнопкам, лог.0 - нажатым. Затем можем проинвертировать эти регистры и "забить нулями" их младшие полубайты при помощи лог.И (andlw или andwf).
Получим такую картину - три регистра, старшие полубайты которых содержат информацию о нажатых кнопках, а младшие полубайты нули. Причем после инверсии отпущенной кнопке будет соответствовать лог.0 в бите регистра, а нажатой - лог.1.

С1 = |_*_|_7_|_4_|_1_|0|0|0|0|
С2 = |_0_|_8_|_5_|_2_|0|0|0|0|
С3 = |_#_|_9_|_6_|_3_|0|0|0|0|

_1_ - так я обозначил соответствие битов кнопкам.
Далее потребуется обработать эти данные и выдать результат в одном байте.
Для подсчета количества нажатых кнопок можем использовать еще один зарезервированный заранее регистр (к примеру, назовем его KEYCOUNTER). А результат будем помещать, к примеру, в регистр с названием KEYRESULT. Обнуляем эти регистры заранее.
Проверяем поочередно каждый из 12 бит в старших полубайтах регистров С1, С2, С3. Если бит=0, то ничего не делаем, переходим к следующему биту.
А если бит=1, то инкрементируем KEYCOUNTER. Если этот равный единице бит соответствует одной из цифровых кнопок 0-9, то записываем в регистр KEYRESULT соответствующее число (для кн."1" - единицу, для "9" - девятку, для "0" можем либо 0, либо 10 записывать). Если же нажата кн. "*", то устанавливаем в 1 бит KEYRESULT,4. А если нажата "#" - то устанавливаем в 1 бит KEYRESULT,5. Таким образом появляется возможность устанавливать любой приоритет при нажатии нескольких цифровых кнопок (вдруг потребуется).
После проверки всех 12 бит смотрим - какое число в регистре KEYCOUNTER (сколько кнопок было одновременно нажато). Если число больше 3, то записываем туда 3. И переносим это число в два старших бита регистра KEYRESULT.
В итоге получаем в регистре KEYRESULT результат опроса клавиатуры. В младшем полубайте содержится число, соответствующее старшей (условно старшей - мы сами её выбираем) из нажатых цифровых кнопок. Биты 4 и 5 содержат информацию о состоянии кнопок * и # соответственно. Биты 6 и 7 содержат число одновременно нажатых кнопок (от 0 до 3, а случай больше 3 нам неинтересен). Представленный в таком виде результат удобен для последующего анализа, в том числе и для вывода на индикатор.

Всё вышеописанное - лишь моё ИМХО и предложение.

 

можно и так, т. е. 3 выхода (RB1, RB2, RB3) с диодами – столбцы и 4 входа (RB4, RB5, RB6, RB7) с резисторами – строки
но я бы все таки предложил сделать 4 выхода на RB0, RB1, RB2 и RB3 с диодами и 3 входа на RB4, RB5 и RB6
вот почему:
- входы RB4 - RB7 можно использовать для прерываний от внешних устройств, а RB0 - RB3 нет
(в результате – применительно к варианту "кодовый замок" – на свободный RB7 в будущем например можно поставить геркон входных дверей, по которому начнется отсчет времени, отведенного на ввод кода)
- к выходам RB можно без проблем подключить кроме клавиатуры любые другие устройства, ко входам – не все
(например, если это будет семисегментный индикатор, то нажатия кнопок всего лишь исказят отображаемый код – зажгут лишние сегменты. Если это будет цифровое устройство – результат может быть неожиданным )
В результате на клавиатуру мы фактически теряем всего три линии вместо четырех и освобождаем одну, по которой возможно прерывание.
Затем, с получением кода клавиши в одном регистре согласен, но есть предложение по модификации способа его получения:
- 3 и более одновременно нажатых клавиш не обрабатывать – ждать пока лишние будут отпущены. К примеру если будут нажаты “*” + “#” + “7” какую из четырех (“*”, “#”, “7” или “9”) считать фантомом?
- 2 обрабатывать только если это “*” + “цифра” или “#” + “цифра”
- 1 обрабатывать
После все цифровые клавиши запоминать в массиве. Можно ограничиться 8 регистрами ОЗУ, по одному символу в регистре (первые 4 бита – цифра плюс 4-ый и 5-ый – клавиши “*” и “#”)
Затем нужен сам алгоритм работы клавиатуры, я предлагаю:
- цифра – запись символа в массив
- “*” – очистка массива
- “#” – конец ввода и действия с введенным кодом (проверка или что-то еще)
- достижение предустановленного количества знаков в коде – то-же, что и “#”
Вывод кода на индикатор предлагаю делать сразу. В качестве индикатора можно использовать два 4-ех значных семисегментных (итого 8 знаков), и фактически постоянно выводить туда массив символов (можно организовать по прерыванию от таймера). Используя дешифратор и регистр или счетчик (правда две лишние микросхемы, ну и с дешифраторами пока не работал, лишь догадываюсь об их существовании) можно ограничиться 6 выводами МК – 4 RB0-RB3 на дешифратор и два от RA на регистр

 

к выходам RB можно подключить кроме клавиатуры любые другие устройства, ко входам – не все
picmaniac, приношу извинения - смысл резисторов наконец-то дошел
действительно, можно подключить и цифровые устройства, единственно, чтобы они не срабатывали без участия МК от нажатия клавиш, пока RB4-RB7 настроены как входы
поэтому, можно принять ваше ТЗ

 

Alex73, да какие извинения, о чём речь!
Приятно иметь дело с единомышленником!

Жаль, у меня сейчас времени нет на контроллеры. Вчера часик всего лишь покумекал. А для внешних прерываний специальный вход есть - RB0/INT, я его в схеме клавиатуры не задействовал. Нам бы для начала совместно написать и отладить фрагмент кода для опроса клавиатуры и помещения результата в один байт. Желательно с составлением графа и алгоритма - для лучшего понимания, это всё же ликбез. Такое моё предложение.
А потом уже будем решать - как результат дальше обрабатывать и на что выводить.

 

составил алгоритм
почти по ТЗ:
- по трем и более клавишам зацикливание на начало, т. е. пока не отпустят лишние
- две проходят, только если это "*"&"цифра" или "#"&"цифра", иначе зацикливание на начало
- ноль - зацикливание на начало
- есть защита от дребезга - задержка 10 ms и повторное считывание
- цифры имеют код от 0 для нуля до 9 для девяти
- "*", если нажата одна, имеет код 10
- "#", если нажата одна, имеет код 11
- перед завершением стоит проверка "изменилось ли состояние клавиатуры", и если нет - зацикливание на начало
т. е. на выходе в KeyResult имеем всегда новое состояние клавиатуры:
6 и 7 биты - количество нажатых клавиш = 1 или 2
5 бит - если установлен, нажата "#"
4 бит - если установлен, нажата "*"
0 - 3 биты - код цифры, или если цифра не нажата, решетки (11) или звездочки (10)
ну как?

 

вот сам файл с алгоритмом

 

извиняюсь, сразу после отправки заметил ошибку в рисунке, и так два раза
вот алгоритм; вроде на этот раз рабочий