• На практике подобные подпрограммы часто возвращают всякую ерунду из-за дребезга контактов, а также различных наводок в проводах, соединяющих клавиатуру и электронные узлы. Один из возможных вариантов решения этой проблемы приведен в Программе 11.3. В этой программе для опроса клавиатуры используется подпрограмма SCAN_IT, код которой был приведен в Программе 11.2. Сохраняя в памяти значение, полученное при предыдущем опросе, можно отслеживать любые изменения состояния клавиатуры. Подпрограмма GET_IT возвращает код кнопки только в том случае, если состояние клавиатуры не менялось на протяжении 256 последовательных опросов. В зависимости от качества клавиатуры, уровня помех и частоты процессора надежность считывания можно увеличить (при этом возрастет время отклика), добавив в тело цикла короткую задержку или увеличив размер счетчика до двух байтов.
; ************************************
; * ФУНКЦИЯ: Сканирует клавиатуру 4 х 3 и возвращает номер клавиши *
; * ФУНКЦИЯ: (имеется защита от дребезга) *
; * ВХОД: Нет *
; * ВЫХОД: Номер клавиши в W ([МЕМ]=10, [0]=11, [SET]=12) *
; * ВЫХОД: Возвращает -1 (h’FF’), если не нажато ни одной клавиши *
; * ОКРУЖЕНИЕ: Переменные COUNT, NEW_KEY, OLD_KEY *
; * ОКРУЖЕНИЕ: Подпрограмма SCAN_IT *
; *************************************
cblock ; Три глобальные переменные
COUNT 1, NEW_KEY:1, OLD_KEY:1
endc
GET_IT clrf COUNT; Обнуляем счетчик
GLOOP call SCAN_IT; «Сырое» значение находится в W
movwf NEW_KEY; Сохраняем новое значение
subwf OLD_KEY,w; Отличается от предыдущего?
btf sc STATUS,Z
goto EQUAL; ЕСЛИ одинаковы, ТО переходим к EQUAL
;Результат отличается от предыдущего, поэтому:
movf NEW_KEY,w; Переписываем предыдущее значение новым
movwf OLD KEY
goto GET_IT; и начинаем цикл опроса сначала
; ЕСЛИ значения одинаковы, ТО —
EQUAL incfsz COUNT,f; Инкрементируем счетчик. ЕСЛИ нет
goto GLOOP; переполнения, считываем новое значение
movf OLD_KEY,w; ИНАЧЕ возвращаем требуемое значение!
return
unsigned int scan_it(void)
{
unsigned int key, pattern;
key=1; pattern = 0xFE; /* Начальное значение маски b’11111110’ */
while(key<13) /* У нас 12 клавиш */
{
PORT_B = pattern; /* Выбираем строку */
if(!COL1) {break;} /* Считываем состояние каждого столбца, */
key++; /* выходя из цикла при нулевом значении */
if(!COL2) {break;} /* ИНАЧЕ инкрементируем счетчик цикла */
kеу++;
if(!COL3) {break;}
kеу++;
pattern = pattern << 1; /* Сдвигаем маску на один бит влево */
}
if(key==13) {key = 0xFF;} /* Если в счетчике число 13, нажатые клавиши */
return key; /* отсутствуют */
}
В Программе 11.4 приведен текст Си-программы для компилятора CCS, которая выполняет те же действия, что и код в Программе 11.2. При этом предполагается, что порт В уже сконфигурирован следующим образом: