Programming AVR Microcontroller
►AVR Assembly Programming for 4x4 Keypad Matrix
►Programming AVR in C for 4x4 Keypad Matrix
Using these keypad routines is really simple.. here is a simple example that shows how to convert the key numbers to displayable ascii characters.
However the above function is just an example of how to use get_key function, you can define any translate function as per your requirement.
The next section of the tutorial will cover the programming of 8051. The usage example will apply to 8051 too.
►AVR Assembly Programming for 4x4 Keypad Matrix
CODE:
.include "8515def.inc"
.equ col1 = PINA0
.equ col2 = PINA1
.equ col3 = PINA2
.equ col4 = PINA3
.def keyval = r16
.def temp = r17
.def flags = r18
.equ keyport = PORTA
.equ pressed = 0
key_init:
ldi keyval,$F0 ;Make Cols as i/p
out DDRA, keyval ;and Rows as o/p
ldi keyval,$0F ;Enable pullups
out keyport, keyval ;on columns
ret
get_key:
ldi keyval,$0 ;Scanning Row1
ldi temp,$7F ;Make Row1 low
out keyport,temp ;Send to keyport
rcall read_col ;Read Columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit the routine
ldi keyval,$4 ;Scanning Row2
ldi temp,$BF ;Make Row2 Low
out keyport,temp ;Send to keyport
rcall read_col ;Read Columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit from routine
ldi keyval,$8 ;Scanning Row3
ldi temp,$DF ;Make Row3 Low
out keyport,temp ;Send to keyport
rcall read_col ;Read columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit the routine
ldi keyval,$C ;Scanning Row4
ldi temp,$EF ;Make Row4 Low
out keyport,temp ;send to keyport
rcall read_col ;Read columns
done:
ret
read_col:
cbr flags, (1<<pressed) ;Clear status flag
sbic PINA, col1 ;Check COL1
rjmp nextcol ;Go to COL2 if not low
hold:
sbis PINA, col1 ;Wait for key release
rjmp hold
sbr flags, (1<<pressed) ;Set status flag
ret ;key 1 pressed
nextcol:
sbic PINA,col2 ;Check COL2
rjmp nextcol1 ;Goto COL3 if not low
hold1:
sbis PINA, col2 ;Wait for key release
rjmp hold1
inc keyval ;Key 2 pressed
sbr flags,(1<<pressed) ;Set status flag
ret
nextcol1:
sbic PINA,col3 ;Check COL3
rjmp nextcol2 ;Goto COL4 if no pressed
hold2:
sbis PINA, col3 ;Wait for key release
rjmp hold2
inc keyval ;Key 3 pressed
inc keyval
sbr flags, (1<<pressed) ;Set status flag
ret
nextcol2:
sbic PINA,col4 ;Check COL4
rjmp exit ;Exit if not low
hold3:
sbis PINA, col4 ;Wait for key release
rjmp hold3
inc keyval ;Key 4 Pressed
inc keyval
inc keyval
sbr flags, (1<<pressed) ;Set status flag
ret
exit:
clr keyval ;reset keyval
cbr flags, (1<<pressed) ;No Key Pressed
ret
.equ col1 = PINA0
.equ col2 = PINA1
.equ col3 = PINA2
.equ col4 = PINA3
.def keyval = r16
.def temp = r17
.def flags = r18
.equ keyport = PORTA
.equ pressed = 0
key_init:
ldi keyval,$F0 ;Make Cols as i/p
out DDRA, keyval ;and Rows as o/p
ldi keyval,$0F ;Enable pullups
out keyport, keyval ;on columns
ret
get_key:
ldi keyval,$0 ;Scanning Row1
ldi temp,$7F ;Make Row1 low
out keyport,temp ;Send to keyport
rcall read_col ;Read Columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit the routine
ldi keyval,$4 ;Scanning Row2
ldi temp,$BF ;Make Row2 Low
out keyport,temp ;Send to keyport
rcall read_col ;Read Columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit from routine
ldi keyval,$8 ;Scanning Row3
ldi temp,$DF ;Make Row3 Low
out keyport,temp ;Send to keyport
rcall read_col ;Read columns
sbrc flags,pressed ;If key pressed
rjmp done ;Exit the routine
ldi keyval,$C ;Scanning Row4
ldi temp,$EF ;Make Row4 Low
out keyport,temp ;send to keyport
rcall read_col ;Read columns
done:
ret
read_col:
cbr flags, (1<<pressed) ;Clear status flag
sbic PINA, col1 ;Check COL1
rjmp nextcol ;Go to COL2 if not low
hold:
sbis PINA, col1 ;Wait for key release
rjmp hold
sbr flags, (1<<pressed) ;Set status flag
ret ;key 1 pressed
nextcol:
sbic PINA,col2 ;Check COL2
rjmp nextcol1 ;Goto COL3 if not low
hold1:
sbis PINA, col2 ;Wait for key release
rjmp hold1
inc keyval ;Key 2 pressed
sbr flags,(1<<pressed) ;Set status flag
ret
nextcol1:
sbic PINA,col3 ;Check COL3
rjmp nextcol2 ;Goto COL4 if no pressed
hold2:
sbis PINA, col3 ;Wait for key release
rjmp hold2
inc keyval ;Key 3 pressed
inc keyval
sbr flags, (1<<pressed) ;Set status flag
ret
nextcol2:
sbic PINA,col4 ;Check COL4
rjmp exit ;Exit if not low
hold3:
sbis PINA, col4 ;Wait for key release
rjmp hold3
inc keyval ;Key 4 Pressed
inc keyval
inc keyval
sbr flags, (1<<pressed) ;Set status flag
ret
exit:
clr keyval ;reset keyval
cbr flags, (1<<pressed) ;No Key Pressed
ret
►Programming AVR in C for 4x4 Keypad Matrix
CODE:
#include <avr/io.h> // Include file for AVR
#define keyport PORTA //Keypad Port
#define keyportddr DDRA //Data Direction Register
#define keyportpin PINA //Keypad Port Pins
#define col1 PA0 //Column1 PortA.0
#define col2 PA1 //Column2 PortA.1
#define col3 PA2 //Column3 PortA.2
#define col4 PA3 //Column4 PortA.3
#define TRUE 1
#define FALSE 0
unsigned char keyval; //A variable
/*
+---------------------------------------+
| Prototype: void key_init(void); |
| Return Type: void |
| Arguments: None |
| Description: Initialize ports and |
| Keypad. |
+---------------------------------------+
*/
void key_init(){
keyportddr = 0xF0;
keyport = 0x0F;
}
/*
+-----------------------------------------------+
| Prototype: unsigned char get_key(void); |
| Return Type: unsigned char |
| Arguments: None |
| Description: To read key from the keypad |
+-----------------------------------------------+
*/
unsigned char get_key(){
unsigned char i,key=1;
for(i=0;i<4;i++){ //Loop for 4 rows
keyport &=~(0x80>>i); //Make rows low one by one
if(!(keyportpin & (1<<col1))){
//check COL1
while(!(keyportpin & (1<<col1)));
//wait for release
return key;
//return pressed key value
}
if(!(keyportpin & (1<<col2))){
//Check COL2
key += 1;
//Second key pressed
while(!(keyportpin & (1<<col2)));
//wait for release
return key;
//return key value
}
if(!(keyportpin & (1<<col3))){
//Check COL3
key += 2;
//Third key pressed
while(!(keyportpin & (1<<col3)));
//Wait for release
return key;
//Return value
}
if(!(keyportpin & (1<<col4))){
//check COL4
key += 3;
//Fourth key pressed
while(!(keyportpin & (1<<col4)));
//Wait for release
return key;
//Return key value
}
key +=4; //Next row
keyport |= 0x80>>i;
//make read row high again
}
return FALSE; //return false if no key pressed
}
#define keyport PORTA //Keypad Port
#define keyportddr DDRA //Data Direction Register
#define keyportpin PINA //Keypad Port Pins
#define col1 PA0 //Column1 PortA.0
#define col2 PA1 //Column2 PortA.1
#define col3 PA2 //Column3 PortA.2
#define col4 PA3 //Column4 PortA.3
#define TRUE 1
#define FALSE 0
unsigned char keyval; //A variable
/*
+---------------------------------------+
| Prototype: void key_init(void); |
| Return Type: void |
| Arguments: None |
| Description: Initialize ports and |
| Keypad. |
+---------------------------------------+
*/
void key_init(){
keyportddr = 0xF0;
keyport = 0x0F;
}
/*
+-----------------------------------------------+
| Prototype: unsigned char get_key(void); |
| Return Type: unsigned char |
| Arguments: None |
| Description: To read key from the keypad |
+-----------------------------------------------+
*/
unsigned char get_key(){
unsigned char i,key=1;
for(i=0;i<4;i++){ //Loop for 4 rows
keyport &=~(0x80>>i); //Make rows low one by one
if(!(keyportpin & (1<<col1))){
//check COL1
while(!(keyportpin & (1<<col1)));
//wait for release
return key;
//return pressed key value
}
if(!(keyportpin & (1<<col2))){
//Check COL2
key += 1;
//Second key pressed
while(!(keyportpin & (1<<col2)));
//wait for release
return key;
//return key value
}
if(!(keyportpin & (1<<col3))){
//Check COL3
key += 2;
//Third key pressed
while(!(keyportpin & (1<<col3)));
//Wait for release
return key;
//Return value
}
if(!(keyportpin & (1<<col4))){
//check COL4
key += 3;
//Fourth key pressed
while(!(keyportpin & (1<<col4)));
//Wait for release
return key;
//Return key value
}
key +=4; //Next row
keyport |= 0x80>>i;
//make read row high again
}
return FALSE; //return false if no key pressed
}
Using these keypad routines is really simple.. here is a simple example that shows how to convert the key numbers to displayable ascii characters.
CODE:
unsigned char translate(unsigned char keyval)
{
if(keyval<10)
return keyval+'0';
else if(keyval>=10 && keyval < 16)
return keyval - 10 + 'A';
else
return '?';
}
/* usage */
ascii_key = translate(get_key());
/*
* ascii_key will have the ascii equivalent of key pressed on the keypad
* i.e. 0, 1, 2, 3, 4,...., A, B, C, D, E, F
*/
{
if(keyval<10)
return keyval+'0';
else if(keyval>=10 && keyval < 16)
return keyval - 10 + 'A';
else
return '?';
}
/* usage */
ascii_key = translate(get_key());
/*
* ascii_key will have the ascii equivalent of key pressed on the keypad
* i.e. 0, 1, 2, 3, 4,...., A, B, C, D, E, F
*/
However the above function is just an example of how to use get_key function, you can define any translate function as per your requirement.
The next section of the tutorial will cover the programming of 8051. The usage example will apply to 8051 too.
No comments:
Post a Comment