|
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, 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
|
|
|