|
|
  |
16тикнопочная клавиатура и 80C552, Помогите студенту |
|
|
|
Jun 19 2008, 10:01
|
Группа: Новичок
Сообщений: 3
Регистрация: 6-06-07
Пользователь №: 28 238

|
Имеется клавиатура с цифрами 0-F, подключенная к порту P1 контроллера. Изначально P1 = 11111111b. Каждая клавиша кодируется двумя битами в P1 - один как бы обозначает ряд, другой - столбец. При нажатии кнопки соответствующие 2 бита сбрасываются в 0. В этом случае определение нажатой кнопки - циклический перебор состояний P1. Но появляются какие-то проблемы. Стоит задача: при нажатии клавиши вывести сначала знак "*", потом - знак "#" каждую секунду, пока нажата клавиша, затем, когда клавиша отпущена - цифру, соответствующую клавише. Реализовать это надо с использованием прерываний. Вот исходник: Код ORG 8000H LJMP MAIN
ORG 8033H LJMP P1HANDLE
ORG 803BH LJMP P1HANDLE
ORG 8043H LJMP P1HANDLE
ORG 804BH LJMP P1HANDLE
MAIN: TM2IR EQU 0C8h CTCON EQU 0EBh S0BUF EQU 099h IEN1 EQU 0E8h IEN0 EQU 0A8h IP1 EQU 0F8h TM2CON EQU 0EAh
MOV A, #00000000B MOV R1, #11111111B MOV R2, #11111111B MOV R3, #00000000B MOV P1, #00001111B MOV TM2IR, #00000000B MOV TM2CON, #00000011B MOV CTCON, #10101010B MOV IP1, #00000000B MOV IEN1, #00001111B MOV IEN0, #10000000B SETB IE.7
LOOP: NOP JMP LOOP
P1HANDLE: MOV R4, P1 MOV TM2IR, #00000000B CLR TI MOV S0BUF, #00101010B JNB TI, $ CLR TI CLR TI MOV S0BUF, R4 JNB TI, $ CLR TI CALL WAIT CALL WAIT
PRINT23H: CLR TI MOV S0BUF, #00100011B JNB TI, $ CLR TI CALL WAIT MOV A, P1 CJNE A, #00001111B, PRINT23H <Определение нажатой клавиши и вывод соответствующего символа>
RETURN: MOV A, #00000000B MOV R1, #11111111B MOV R2, #11111111B MOV R3, #00000000B MOV P1, #00001111B MOV TM2IR, #00000000B MOV TM2CON, #00000011B MOV CTCON, #10101010B MOV IP1, #00000000B MOV IEN1, #00001111B MOV IEN0, #10000000B SETB IE.7 A1: RETI
WAIT: OUTER_CYCLE: INNER_CYCLE: NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP DJNZ R2, INNER_CYCLE DJNZ R1, OUTER_CYCLE RET
DELAY: JNB TI, WAIT RET
END Это - гарантированно рабочий код, возможно не оптимальный. Определение клавиши сделано так, но это не работает: Код GET_NUMBER: MOV P1, #11011111B MOV A, P1 CJNE A, #11011111B, RECOGN0
MOV P1, #11101111B MOV A, P1 CJNE A, #11101111B, RECOGN0
MOV P1, #01111111B MOV A, P1 CJNE A, #01111111B, RECOGN0
MOV P1, #10111111B MOV A, P1 CJNE A, #10111111B, RECOGN0 JMP GET_NUMBER
RECOGN0: MOV A, #11010000B ORL A, R4 CJNE A, #11011101B, RECOGN1 MOV R3, #00110001B LJMP OUTPUT
RECOGN1: CJNE A, #11011110B, RECOGN2 MOV R3, #00110010B LJMP OUTPUT
RECOGN2: CJNE A, #11010111B, RECOGN3 MOV R3, #00110011B LJMP OUTPUT
RECOGN3: CJNE A, #11011011B, RECOGN4 MOV R3, #00110100B LJMP OUTPUT
RECOGN4: MOV A, #11100000B ORL A, R4 CJNE A, #11101101B, RECOGN5 MOV R3, #00110101B LJMP OUTPUT
RECOGN5: CJNE A, #11101110B, RECOGN6 MOV R3, #00110110B LJMP OUTPUT
RECOGN6: CJNE A, #11100111B, RECOGN7 MOV R3, #00110111B LJMP OUTPUT
RECOGN7: CJNE A, #11101011B, RECOGN8 MOV R3, #00111000B LJMP OUTPUT
RECOGN8: MOV A, #01110000B ORL A, R4 CJNE A, #01111101B, RECOGN9 MOV R3, #00111001B LJMP OUTPUT
RECOGN9: CJNE A, #01111110B, RECOGN10 MOV R3, #00110000B LJMP OUTPUT
RECOGN10: CJNE A, #01110111B, RECOGN11 MOV R3, #01000001B LJMP OUTPUT
RECOGN11: CJNE A, #01111011B, RECOGN12 MOV R3, #01000010B LJMP OUTPUT
RECOGN12: MOV A, #10110000B ORL A, R4 CJNE A, #10111101B, RECOGN13 MOV R3, #01000011B LJMP OUTPUT
RECOGN13: CJNE A, #10111110B, RECOGN14 MOV R3, #01000100B LJMP OUTPUT
RECOGN14: CJNE A, #10110111B, RECOGN15 MOV R3, #01000101B LJMP OUTPUT
RECOGN15: CJNE A, #10111011B, NOT_RECOGN MOV R3, #01000110B LJMP OUTPUT
NOT_RECOGN: CJNE A, #10111011B, RETURN
OUTPUT: CLR TI MOV S0BUF, R3 JNB TI, $ CLR TI Этот код почему-то определяет только верхние 4 кнопки, выводя цифры 1-4, если нажимать остальные - то выводит тоже 1-4.
|
|
|
|
|
Jun 19 2008, 10:47
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Как всё запущено... Ну, если "в лоб", то что-то такое: Код GET_NUMBER: MOV P1, #11011111B MOV A, P1 CJNE A, #11011111B, L1 MOV P1, #11101111B MOV A, P1 CJNE A, #11101111B, L2 MOV P1, #01111111B MOV A, P1 CJNE A, #01111111B, L3 MOV P1, #10111111B MOV A, P1 CJNE A, #10111111B, L4 JMP GET_NUMBER
L1: ; наверное у Вас это считается первой строкой? или третьей? CJNE A, #11011101B, L1C2; константа = что выдали в порт, но с одним нулём в одной колонке MOV R3, #00110001B; наверное - это код строки/столбца? LJMP OUTPUT L1C21: CJNE A, #11011110B, L1C3 MOV R3, #00110010B LJMP OUTPUT L1C32: CJNE A, #11010111B, L1C4 MOV R3, #00110011B LJMP OUTPUT L1C4: CJNE A, #11011011B, LXX; Переходим на LXX если нажали две или больше клавиш MOV R3, #00110100B LJMP OUTPUT
L2: аналогично, но меняются константы L3: и здесь - аналогично, но др. константы L4: и здесь...
|
|
|
|
|
Jun 19 2008, 11:56
|
Группа: Новичок
Сообщений: 3
Регистрация: 6-06-07
Пользователь №: 28 238

|
Цитата(Палыч @ Jun 19 2008, 14:47)  Как всё запущено... Ну, если "в лоб", то что-то такое: Код ... В R3 я кладу ASCII код символа, который будет выведен. Физически на клавиатуре L1 - первая. По распайке - не знаю. Вопрос такой: перед тем, как определять клавишу - нужно выключать прерывания? Проверил на эмуляторе, вроде работает, только с косяком. Попробую разобраться сам.
|
|
|
|
|
Jun 19 2008, 12:46
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Чтобы ответить на Ваши вопросы, нужно разбираться в том, что Ваша программа и в каком месте делает. Ваш стиль написания программ - как бы это по-мягче сказать ? - не информативен... И коментарии отсутствуют. Вряд ли кто-то что-то разберёт... Если Вы текст своей программы не поправите, получить советы вряд ли сможите. Например Цитата(lytdybr @ Jun 19 2008, 14:56)  В R3 я кладу ASCII код символа, который будет выведен. Более понятно, это записывается так (в R3 положить код символа 1) mov R3, #'1' Цитата(lytdybr @ Jun 19 2008, 14:56)  Вопрос такой: перед тем, как определять клавишу - нужно выключать прерывания? Речь идёт о той части программы, которая начинается с метки get_number? Если, да, то не вижу смысла это делать...
|
|
|
|
|
Jun 19 2008, 13:16
|
Группа: Новичок
Сообщений: 3
Регистрация: 6-06-07
Пользователь №: 28 238

|
Код
ORG 8000H LJMP MAIN
ORG 8033H LJMP P1HANDLE
ORG 803BH LJMP P1HANDLE
ORG 8043H LJMP P1HANDLE
ORG 804BH LJMP P1HANDLE
MAIN: TM2IR EQU 0C8h CTCON EQU 0EBh S0BUF EQU 099h IEN1 EQU 0E8h IEN0 EQU 0A8h IP1 EQU 0F8h TM2CON EQU 0EAh
MOV A, #00000000B MOV R1, #11111111B MOV R2, #11111111B MOV R3, #00000000B MOV P1, #11111111B ; Сбрасываем флаги прерываний T2 MOV TM2IR, #00000000B : Включаем таймер MOV TM2CON, #00000011B ; Реагируем на перепад 1->0 на p1.0 - p1.3 MOV CTCON, #10101010B MOV IP1, #00000000B ; Включаем прерывания от регистров захвата (capture register) MOV IEN1, #00001111B ; Включаем прерывания вообще MOV IEN0, #10000000B
LOOP: ; Ожидание прерываний NOP JMP LOOP
; Обработка прерываний от регистров захвата 0-3 P1HANDLE: ;сохраняем P1 MOV R4, P1 ;Сброс флагов прерыаний MOV TM2IR, #00000000B
; выводим "*" CLR TI MOV S0BUF, #00101010B JNB TI, $ CLR TI
; Пока клавиша не отпущена - выводим "#" PRINT23H: CLR TI MOV S0BUF, #00100011B JNB TI, $ CLR TI CALL WAIT
MOV A, P1 CJNE A, #11111111B, PRINT23H
; Выводим на экран символ соответствующий нажатой клавише GET_NUMBER: ; Линия 1 MOV P1, #11011111B MOV A, P1 CJNE A, #11011111B, RECOGN0 ; Линия 2 MOV P1, #11101111B MOV A, P1 CJNE A, #11101111B, RECOGN4 ; Линия 3 MOV P1, #01111111B MOV A, P1 CJNE A, #01111111B, RECOGN8 ; Линия 4 MOV P1, #10111111B MOV A, P1 CJNE A, #10111111B, RECOGN12 JMP GET_NUMBER
RECOGN0: CJNE A, #11011101B, RECOGN1 MOV R3, #'1' LJMP OUTPUT
RECOGN1: CJNE A, #11011110B, RECOGN2 MOV R3, #'2' LJMP OUTPUT
RECOGN2: CJNE A, #11010111B, RECOGN3 MOV R3, #'3' LJMP OUTPUT
RECOGN3: CJNE A, #11011011B, RECOGN4 MOV R3, #'4' LJMP OUTPUT
RECOGN4: CJNE A, #11101101B, RECOGN5 MOV R3, #'5' LJMP OUTPUT
RECOGN5: CJNE A, #11101110B, RECOGN6 MOV R3, #'6' LJMP OUTPUT
RECOGN6: CJNE A, #11100111B, RECOGN7 MOV R3, #'7' LJMP OUTPUT
RECOGN7: CJNE A, #11101011B, RECOGN8 MOV R3, #'8' LJMP OUTPUT
RECOGN8: CJNE A, #01111101B, RECOGN9 MOV R3, #'9' LJMP OUTPUT
RECOGN9: CJNE A, #01111110B, RECOGN10 MOV R3, #'0' LJMP OUTPUT
RECOGN10: CJNE A, #01110111B, RECOGN11 MOV R3, #'A' LJMP OUTPUT
RECOGN11: CJNE A, #01111011B, RECOGN12 MOV R3, #'B' LJMP OUTPUT
RECOGN12: CJNE A, #10111101B, RECOGN13 MOV R3, #'C' LJMP OUTPUT
RECOGN13: CJNE A, #10111110B, RECOGN14 MOV R3, #'D' LJMP OUTPUT
RECOGN14: CJNE A, #10110111B, RECOGN15 MOV R3, #'E' LJMP OUTPUT
RECOGN15: CJNE A, #10111011B, NOT_RECOGN MOV R3, #'F' LJMP OUTPUT
; Клавиша не распознана NOT_RECOGN: CJNE A, #10111011B, RETURN ; выводим символ OUTPUT: CLR TI MOV S0BUF, R3 JNB TI, $ CLR TI ; Восстанавливаем состояние регистров перед возвратом из прерывания RETURN: MOV A, #00000000B MOV R1, #11111111B MOV R2, #11111111B MOV R3, #00000000B MOV P1, #00001111B MOV TM2IR, #00000000B MOV TM2CON, #00000011B MOV CTCON, #10101010B MOV IP1, #00000000B MOV IEN1, #00001111B MOV IEN0, #10000000B
; Возврат из прерывания A1: RETI
; Пауза примерно 1 сек. WAIT: OUTER_CYCLE: INNER_CYCLE: NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP DJNZ R2, INNER_CYCLE DJNZ R1, OUTER_CYCLE RET
END Исправил, добавил комменты.
|
|
|
|
|
Jun 19 2008, 13:42
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(lytdybr @ Jun 19 2008, 16:16)  Код ; Восстанавливаем состояние регистров перед возвратом из прерывания RETURN: MOV A, #00000000B MOV R1, #11111111B MOV R2, #11111111B MOV R3, #00000000B MOV P1, #00001111B MOV TM2IR, #00000000B MOV TM2CON, #00000011B MOV CTCON, #10101010B MOV IP1, #00000000B MOV IEN1, #00001111B MOV IEN0, #10000000B ; Возврат из прерывания A1: RETI Вот этот кусок кода У Вас зачем нужен? R1 и R2 в этом прерывании не используются... Да и регистры устройств разве портятся? А если желаете сохранять значения аккумулятора и регистров, то, обычно, используют команды POP/PUSH: в начале прерывания сохраняемые регистры заталкивают в стек, перед выходом из прерывания - извлекают. В микроконтроллерах МК51 для этой же цели есть специальная фишка - банки регистров (их аж 4), которые можно переключать (это удобно, если в прерывании используется много регистров R0-R7), при этом в основной программе используют банк 0, в одном прерывании - банк 1, в другом прерывании - банк 2, и т.д.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|