首先,我非常抱歉,如果我不知道如何正确提出一个问题。这是我第一次使用这个论坛的指导!我必须转换一个4x 4键盘矩阵AVR汇编代码到4x 3,这必须通过中断来完成。到目前为止,这是我所做的:
.INCLUDE "M32DEF.INC"
.org 0x00
jmp main
.org 0x50
main:
.EQU KEY_PORT = PORTC
.EQU KEY_PIN = PINC
.EQU KEY_DDR = DDRC
.EQU LCD_DPRT = PORTA
.EQU LCD_DDDR = DDRA
.EQU LCD_DPIN = PINA
.EQU LCD_CPRT = PORTB
.EQU LCD_CDDR = DDRB
.EQU LCD_CPIN = PINB
.EQU LCD_RS = 0
.EQU LCD_RW = 1
.EQU LCD_EN = 2
LDI R20, HIGH (RAMEND)
OUT SPH,R20
LDI R20, LOW (RAMEND)
OUT SPL,R20
; ascii code for keypressed displayed on PORTD
LDI R21, 0xFF
OUT DDRA,R21 ; port a output to lcd
; PC0 – PC3 rows
; PC4 – PC6 columns
LDI R20, 0xF0 //portc 0-3 input pins
OUT KEY_DDR, R20
GroundAllColumns:
LDI R20, 0b00001110 // portc 0-3 display 111
OUT KEY_PORT, R20
LDI R21,0xFF;
OUT LCD_DDDR, R21 ;LCD data port is output
OUT LCD_CDDR, R21 ; A,B PORT AS OUTPUT
CBI LCD_CPRT,LCD_EN
CALL DELAY_2ms ;wait for power on
LDI R16,0x38 ; FOR 7X5 DISPLAY
CALL CMNDWRT ;call command function
CALL DELAY_2ms ;wait 2 ms
LDI R16,0x0E ;display on, cursor on
CALL CMNDWRT ;call command function
LDI R16,0x01 ;clear LCD
CALL CMNDWRT
CALL DELAY_2ms
LDI R16,0x06 ; INCREMENT CURSOR
CALL CMNDWRT
LDI R16,0x84 ; INCREMENT CURSOR IST LINE 4TH COLUMN
CALL CMNDWRT
LDI R16, 'F'
CALL DATAWRT
LDI R16, 'A'
CALL DATAWRT
LDI R16, 'S'
CALL DATAWRT
LDI R16, 'T'
CALL DATAWRT
LDI R16,0xC3 ; INCREMENT CURSOR 2ND LINE 3RD COLUMN
CALL CMNDWRT
LDI R16, '0'
CALL DATAWRT
here: rjmp here
KPD_ISR:
LDI R21, 0b01111111
OUT KEY_PORT,R21
NOP
IN R21,KEY_PIN
ANDI R21,0x0F
CPI R21,0x0F
BRNE COL1
LDI R21, 0b10111111
OUT KEY_PORT, R21
NOP
IN R21, KEY_PIN
ANDI R21,0x0F
CPI R21,0x0F
BRNE COL2
LDI R21, 0b11011111
OUT KEY_PORT, R21
NOP
IN R21, KEY_PIN
ANDI R21,0x0F
CPI R21,0x0F
BRNE COL3
COL1:
LDI R30, LOW(KCODE0<<1)
LDI R31, HIGH(KCODE0<<1)
RJMP Find
COL2:
LDI R30, LOW(KCODE1<<1)
LDI R31, HIGH(KCODE1<<1)
RJMP Find
COL3:
LDI R30, LOW(KCODE2<<1)
LDI R31, HIGH(KCODE2<<1)
RJMP Find
Find:
LSR R21
BRCC Match
LPM R20, Z+
RJMP Find MATCH:
LPM R20, Z
ldi r17,0x0f
in r16,pinc
andi r16,0x0f
cp r16,r17
breq kpd_isr
OUT PORTA, R20
mov r16,r20
call datawrt ; here call BDELAY
rjmp KPD_ISR
.ORG 0x300
KCODE0: .DB '7', '8', '9' ;col1
KCODE1: .DB '4', '5', '6'
KCODE2: .DB '1', '2', '3'
KCODE3: .DB 'c', '0', '='
字符串
在Proteus模拟中,我在LCD上得到了初始化的输出,但是每当我按下键盘上的任何东西时,它都不会在LCD上注册。我可以从我的模拟中看到,引脚p4-p6的列被设置,我不确定应该是这样:My proteus simulation:
我调整了手册中提供的代码,但随着我的学习,我完全不确定我错在哪里。此外,我记得中断服务例程需要一个向量表(IVT),你可以从IVT中指定的内存位置调用它们。在我提供的代码中,有一个ISR用于按下键盘按钮,但没有设置IVT。这可能是问题所在吗?
1条答案
按热度按时间q9yhzks01#
您的代码不包含任何ISR函数。ISR函数由中断激活。您没有启用任何中断,也没有设置到相关ISR函数的跳转。
KPD_ISR
不是ISR,也不是函数。该函数由CALL
指令调用,必须以RET指令结束。ISR函数由中断调用,必须以RETI
指令结束。为了使激活的中断调用ISR函数,必须在IVT中的适当位置跳转到ISR。还有一件更重要的事情,ISR在完成后不能对处理器的状态造成任何改变,所以它必须负责保存和恢复所有使用过的寄存器,包括SREG。
对于下一个ISR,它应该尽可能短。在任何情况下,它都不应该包含一个持久的代码,在你的代码中显示。
请阅读一些教程,例如here