С таким обработчиком клавиши нажимаются четко.
![](http://i077.radikal.ru/1301/44/52e4202f545e.jpg)
Код:
interrupt [EXT_INT0] void ext_int0() {
#asm
.EQU PIND=0x10
.EQU PINC=0x13
.EQU PINB=0x16
.EQU DDRC=0x14
.EQU DDRB=0x17
.EQU DDRD=0x11
.EQU PORTB=0x18
.EQU PORTC=0x15
.EQU PORTD=0x12
IN R28, SREG ; 1 1
PUSH R28 ; 2 3
; Переводим PORT в режим ввода
CLR R29 ; 1 4
OUT DDRC, R29 ; 1 5
SER R28 ; 1 6
OUT PORTC, R28 ; 1 7
; PORTB = c2b[PINC];
IN R28, PINC ; 1 8
ANDI R28, 0x3F ; 1 9 <- Может быть не нужно
CPI R28, 0x3F ; 1 10
BREQ _v12 ; 2 12
LDI R29, 2 ; 1 13 Адрес 0x200+R28
LD R29, Y ; 2 15
OUT PORTB, R29 ; 1 16
LDI R29, 2 ; 1 17
SUBI R28, -64 ; 1 18 Адрес 0x200+R28+64
LD R28, Y ; 2 19
IN R29, PORTD ; 1 20
ORI R29, 0x33 ; 1 21
AND R29, R28 ; 1 22
OUT PORTD, R29 ; 1 23
SER R28 ; 1 24
OUT DDRB, R28 ; 1 25
IN R28, DDRD ; 1 26
ORI R28, 0x33 ; 1 27
OUT DDRD, R28 ; 1 28
; Выход
POP R28 ; 2 30
OUT SREG, R28 ; 1 31
RETI
_v12: ; Переводим порты B,D в режим ввода. PORTС в режим вывода
OUT DDRB, R29 ; 1 13 R29=0
SER R28 ; 1 14
OUT DDRC, R28 ; 1 15
OUT PORTB, R28 ; 1 16
IN R28, DDRD ; 1 17
ANDI R28, ~0x33 ; 1 18
OUT DDRD, R28 ; 1 19
IN R28, PORTD ; 1 20
ORI R28, 0x33 ; 1 21
OUT PORTD, R28 ; 1 22
; PORTC = b2c[PINB] & d2c[PIND & 0x33];
IN R28, PINB ; 1 23
LDI R29, 1 ; 1 24 Адрес 0x100+R28
LD R28, Y ; 2 26
OUT PORTC, R28 ; 1 27 <- Если освободить регистр, то можно без этой команды
IN R28, PIND ; 1 28
ANDI R28, 0x33 ; 1 29 <- Можно заменить на одну ORI
SUBI R28, -128 ; 1 30 <- Можно заменить на одну ORI
LDI R29, 2 ; 1 31 Адрес 0x200+R28+128
LD R28, Y ; 2 33
IN R29, PORTC ; 1 34 <- Если освободить регистр, то можно без этой команды
AND R29, R28 ; 1 35
OUT PORTC, R29 ; 1 36
; Выход
POP R28 ; 2 38
OUT SREG, R28 ; 1 39 SREG
#endasm
}
---------- Post added at 15:48 ---------- Previous post was at 15:35 ----------
Наверное стоит добиться, что бы клавиатура работала даже на самых коротких командах типа
LXI H, 0FF00h
OUT 0FFh
MOV A, M
---------- Post added at 16:14 ---------- Previous post was at 15:48 ----------
Прерывание дает ответ за 40 тактов. (4 такта на вызов прерывания, и ответ на 28-ом или 36-ом такте.). При пересчете ATMega 8 Мгц на i8080 2 Мгц, получается 40/4 = 10 тактов.
MOV A, M выполняется за 7 тактов.
Код:
LXI D, 0FFFFh
LXI H, 0FFFDh
LDA режим
STAX D
MOV A, M
На таких коротких инструкциях работать не должно. (Надо проверить)
Если использовать ATMega16 с кварцем 16 Мгц (или более), то МК будет в любом случае успевать. Получается 5 тактов.
Но если используется программа типа:
Код:
STA 0FFFFh
LDA 0FFFDh (выполняется за 13 тактов)
То всё должно и так работать.