Full Version : How to Connect 4x4 Keyboard (AVR ASM)
avr >>BEGINNER UTILITIES >>How to Connect 4x4 Keyboard (AVR ASM)


AVR_Admin- 05-17-2006
How to Connect 4x4 Keyboard (AVR ASM)

CODE

;**** A P P L I C A T I O N   N O T E   A V R 2 4 0 ************************
;*
;* Title:  4x4 keypad, wake-up on keypress
;* Version:  1.2
;* Last Updated: 2004.11.11
;* Target:  All AVR Devices
;*
;* Support E-mail: avr@atmel.com
;*
;* DESCRIPTION
;* This Application note scans a 4 x 4 keypad and uses sleep mode
;* causing the AVR to wake up on keypress.  The design uses a minimum of
;* external components. Included is a test program that wakes up the AVR
;* and performs a scan when a key is pressed and flashes one of two LEDs
;* the number of the key pressed.  The external interrupt line is used for
;* wake-up.  The example runs on the AT90S1200 but can be any AVR with suitable
;* changes in vectors, EEPROM and stack pointer. The timing assumes a 4 MHz clock.
;* A look up table is used in EEPROM to enable the same structure to be used
;* with more advanced programs e.g ASCII output to displays.
;***************************************************************************

;***** Register used by all programs
;******Global variable used by all routines

.def temp =r16;general scratch space

;Port B pins

.equ ROW1 =3;keypad input rows
.equ ROW2 =2
.equ ROW3 =1
.equ ROW4 =0
.equ COL1 =7;keypad output columns
.equ COL2 =6
.equ COL3 =5
.equ COL4 =4

;Port D pins

.equ GREEN =0;green LED
.equ RED =1;red LED
.equ INTR =2;interrupt input

.include "1200def.inc"

;***** Registers used by interrupt service routine


.def key =r17;key pointer for EEPROM
.def status =r21;preserve sreg here

;***** Registers used by delay subroutine
;***** as local variables

.def fine =r18;loop delay counters
.def medium =r19
.def  coarse =r20

;*****Look up table for key conversion******************************
.eseg    ;EEPROM segment
.org 0

.db 1,2,3,15,4,5,6,14,7,8,9,13,10,0,11,12
;****Source code***************************************************
.cseg    ;CODE segment
.org 0
 rjmp reset ;Reset handler
 rjmp scan ;interrupt service routine
 reti  ;unused timer interrupt
 reti  ;unused analogue interrupt

;*** Reset handler **************************************************
reset:  
 
 ldi temp,0xFB ;initialise port D as O/I
 out DDRD,temp ;all OUT except PD2 ext.int.
 ldi temp,0x30 ;turn on sleep mode and power
 out MCUCR,temp ;down plus interrupt on low level.
 ldi temp,0x40 ;enable external interrupts
 out GIMSK,temp
 sbi ACSR,ACD ;shut down comparator to save power
main:  cli  ;disable global interrupts
 ldi temp,0xF0 ;initialise port B as I/O
 out DDRB,temp ; 4 OUT  4 IN
 ldi temp,0x0F ;key columns all low and
 out PORTB,temp ;active pull ups on rows enabled
 ldi temp,0x07 ;enable pull up on PD2 and
 out PORTD,temp ;turn off LEDs
 sei  ;enable global interrupts ready
 sleep  ;fall asleep
 rcall flash ;flash LEDs for example usage
 ldi temp,0x40
 out GIMSK,temp ;enable external interrupt
 rjmp main ;go back to sleep after keyscan

;****Interrupt service routine***************************************
scan:  
 in status,SREG ;preserve status register
 sbis PINB,ROW1 ;find row of keypress
 ldi key,0 ;and set ROW pointer
 sbis PINB,ROW2
 ldi key,4
 sbis PINB,ROW3
 ldi key,8
 sbis PINB,ROW4
 ldi key,12
 ldi temp,0x0F ;change port B I/O to
 out DDRB,temp ;find column press
 ldi temp,0xF0 ;enable pull ups and
 out PORTB,temp ;write 0s to rows
 rcall settle ;allow time for port to settle
 sbis PINB,COL1 ;find column of keypress
 ldi temp,0 ;and set COL pointer
 sbis PINB,COL2
 ldi temp,1
 sbis PINB,COL3
 ldi temp,2
 sbis PINB,COL4
 ldi temp,3
 add key,temp ;merge ROW and COL for pointer
 ldi temp,0xF0 ;reinitialise port B as I/O
 out DDRB,temp ; 4 OUT  4 IN
 ldi temp,0x0F ;key columns all low and
 out PORTB,temp ;active pull ups on rows enabled
 out SREG,status ;restore status register

 ldi temp,0x00
 out GIMSK,temp  ;disable external interrupt
   ;have to do this, because we're
   ;using a level-triggered interrupt

 reti  ;go back to main for example program

;***Example test program to flash LEDs using key press data************

flash:  out EEAR,key ;address EEPROM
 sbi EECR,EERE ;strobe EEPROM
 in temp,EEDR ;set number of flashes
 tst temp ;is it zero?
 breq zero ;do RED LED
green_flash:
  cbi PORTD,GREEN;flash green LED 'temp' times
  rcall delay
  sbi PORTD,GREEN
  rcall delay
  dec temp
  brne green_flash
exit:  ret
zero:  ldi temp,10
flash_again:  cbi PORTD,RED;flash red LED ten times
  rcall delay
  sbi PORTD,RED
  rcall delay
  dec temp
  brne flash_again
 rjmp exit

 
;****Time Delay Subroutine for LED flash*********************************
delay:
ldi coarse,8  ;triple nested FOR loop
cagain:  ldi medium,255 ;giving about 1/2 second
magain:   ldi fine,255;delay on 4 MHz clock
fagain:   dec fine
  brne fagain
 dec medium
 brne magain
dec coarse
brne cagain
ret

;***Settling time delay for port to stabilise******************************
settle:
ldi temp,255
tagain:  dec temp
 brne tagain
ret




Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.