Firstly, I am extremely sorry if I donot know how to pose a question correctly. It's my first time using this forum for guidance! I have to convert a 4x4 keypad matrix AVR assembly code into 4x3 and this has to be done via interrupts. So far, this is what i have done:
.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', '='
I get my initialized output on the LCD in my proteus simulation, but whenever I press anything on the keypad it doesn't register on the LCD. I can see from my simulation that my columns from pins p4-p6 are set which im not sure should be the case: My proteus simulation:
I adjusted the code provided in my manual, but as I am learning I'm not sure at all where I went wrong. Also, i remember that interrupt service routines require a vector table (IVT) and you call them from their designated memory locations in the IVT. In the code I was provided, there was an ISR for the keypad button pressing but no IVT set. Could that be the problem?
Your code does not contain any ISR function. The ISR function is activated by an interrupt. You don't have any interrupt enabled and you don't have a jump set to the relevant ISR function.
KPD_ISR
is not an ISR, and is not a function. The function is called by theCALL
instruction and must end with the RET instruction. The ISR function is called by an interrupt and must end with anRETI
instruction. In order for the activated interrupt to call the ISR function, there must be a jump to the ISR at the appropriate place in the IVT.And one more important thing. The ISR must not cause any change to the state of the processor after completion. So it has to take care of saving and restoring all used registers including SREG.
For the next ISR, it should be as short as possible. In no case should it contain a long-lasting code, writing on the display in your code.
Please read some tutorial, for example here