Full Version : Vasilis 4x4 Keyboard and LCD Program (ASM)
avr >>LCD BASED PROJECTS >>Vasilis 4x4 Keyboard and LCD Program (ASM)


Admin3- 04-19-2006
LCD 2x16 characters & 4x4 keypad example



Connect AT90S2313 with LCD display 2x16 char and 4x4 keyboard (keypad). Its not any special code (short or fast code) but its very good for beginners



Designed by: Serasidis Vasilis

CODE

;
;* Description:  Test program with AT90S2313 AVR RISC Processor,
;*   LCD display using 4-wire interface and 4x4 keypad.
;*
;* Writed at:  27-05-2003
;* Target:  AT 90s2313
;* Author:  Serasidis Vasilis
;* Support E-mail: info@serasidis.gr
;* Home page:  http://www.serasidis.gr  
;*
;* LCD rs pin connected to PD6  
;* LCD r/w pin connected to PD5
;* LCD e pin connected to PD4  
;* D4-D7 FROM LCD IS CONNECTED TO PORTD PD0-PD3
;* The 4x4 keypad is conected to PortB pins (PB0-PB7)
;* PB0,PB1,PB2,PB3 inputs, PB4,PB5,PB6,PB7 outputs
;*
;*
;* This source its free, for all of you.
;*
;***************************************************************************

.include "2313def.inc" ;Define chip particulars


;***** Global register variables
.def wreg =R16 ;General use working register
.def timeout =R17 ;Timeout value passed to subroutine
.def lcdstat =R18 ;LCD busy/wait status
.def longtime=R19 ;Long timer for powerup
.def temp  =R20
.def test =R21 ;test register
.def monades =R22
.def dekades =R23

;***** Other equates
.equ lcdrs =PD6 ;LCD rs pin connected to PD6
.equ lcdrw =PD5 ;LCD r/w pin connected to PD5
.equ lcde =PD4 ;LCD e pin connected to PD4
.equ line1   =0x80 ;1η γραμμη του LCD
.equ line2   =0xC0 ;2η γραμμη του LCD
.equ col1 =0b11101111;ολόνα 1
.equ col2    =0b11011111;ολόνα 1
.equ col3    =0b10111111;ολόνα 1
.equ col4    =0b01111111;ολόνα 1



; Main program entry point on reset

reset:


 ldi temp,RAMEND
 out SPL,temp ;Init Stack Pointer


 rcall longdelay ;Delay some time
 ldi temp,0b11110000 ;PB0,1,2,3 inputs, PB4,5,6,7 outputs
 out DDRB,temp
 ldi temp,0b00001111 ;enable internal pull-ups on PB0-PB4
 out PORTB,temp

 rcall lcdinit  ;Initialize LCD module
again:  ldi monades,$30
 ldi dekades,$30
 rcall lcdclr  ;Clear the LCD
 ldi wreg,line1 ;Set address to line 1
 rcall lcdcmd
 ldi ZH,high(2*message1);Type the message1
 ldi ZL,low(2*message1);to the LCD
 rcall loadbyte

 ldi wreg,line2 ;Set address to line 2
 rcall lcdcmd
 ldi ZH,high(2*message2);Type the message2
 ldi ZL,low(2*message2);to the LCD
 rcall loadbyte

;=========================================================================
; Check all keys (1-16).
; The comments from the first 4 keys are the same with all other keys.
;=========================================================================
check_keys:
 ldi temp,col1  ;Enable column1
 out PORTB,temp  
 rcall delay  

 sbic  PINB,PB0 ; Pressed key No1 ?
 rjmp  key2  ; if Not, check next key
 ldi monades,$31 ; if yes...
 rjmp disp_no_of_key ; goto type it to LCD

key2:  sbic  PINB,PB1 ; Pressed key No2 ?
 rjmp  key3  ; if Not, check next key
 ldi monades,$32 ; if yes...
 rjmp disp_no_of_key ; goto type it to LCD

key3:  sbic  PINB,PB2 ; Pressed key No3 ?
 rjmp  key4  ; if Not, check next key
 ldi monades,$33 ; if yes...
 rjmp disp_no_of_key ; goto type it to LCD

key4:  sbic  PINB,PB3 ; Pressed key No4 ?
 rjmp  key5  ; if Not, check next key
 ldi monades,$34 ; if yes...
 rjmp disp_no_of_key ; goto type it to LCD

key5:  ldi temp,col2  ; Disable the first column...
 out PORTB,temp ; and enable the second
 rcall delay

 sbic  PINB,PB0 ; Pressed key No5 ?
 rjmp  key6  ; if Not...
 ldi monades,$35 ;
 rjmp disp_no_of_key

key6:  sbic  PINB,PB1 ; Pressed key No6 ?
 rjmp  key7  ; if Not...
 ldi monades,$36 ;
 rjmp disp_no_of_key

key7:  sbic  PINB,PB2 ; Pressed key No7 ?
 rjmp  key8  ; if Not...
 ldi monades,$37 ;
 rjmp disp_no_of_key

key8:  sbic  PINB,PB3 ; Pressed key No8 ?
 rjmp  key9  ; if Not...
 ldi monades,$38 ;
 rjmp disp_no_of_key

key9:  ldi temp,col3;
 out PORTB,temp
 rcall delay

 sbic  PINB,PB0 ; Pressed key No9 ?
 rjmp  key10  ; if Not...
 ldi monades,$39 ;
 rjmp disp_no_of_key

key10:  sbic  PINB,PB1 ; Pressed key No10 ?
 rjmp  key11  ; if Not...
 ldi monades,$30 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key11:  sbic  PINB,PB2 ; Pressed key No11 ?
 rjmp  key12  ; if Not...
 ldi monades,$31 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key12:  sbic  PINB,PB3 ; Pressed key No12 ?
 rjmp  key13  ; if Not...
 ldi monades,$32 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key13:  ldi temp,col4;
 out PORTB,temp
 rcall delay

 sbic  PINB,PB0 ; Pressed key No13 ?
 rjmp  key14  ; if Not...
 ldi monades,$33 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key14:  sbic  PINB,PB1 ; Pressed key No14 ?
 rjmp  key15  ; if Not...
 ldi monades,$34 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key15:  sbic  PINB,PB2 ; Pressed key No15 ?
 rjmp  key16  ; if Not...
 ldi monades,$35 ;
 ldi dekades,$31
 rjmp disp_no_of_key

key16:  sbic  PINB,PB3 ; Pressed key No16 ?
 rjmp  check_keys ; if Not...
 ldi monades,$36 ;
 ldi dekades,$31
 rjmp disp_no_of_key

;=========================================================================
; Here is typed the message3 ,message4, dekades and monades to LCD
;=========================================================================
disp_no_of_key:
 rcall lcdclr  ; Clear the LCD
 ldi wreg,line1 ; Set address to line 1
 rcall lcdcmd
 ldi ZH,high(2*message3); Load high part of byte address into ZH
 ldi ZL,low(2*message3); Load low part of byte address into ZL
 rcall loadbyte

 ldi wreg,line2 ; Set address to line 2
 rcall lcdcmd
 ldi ZH,high(2*message4); Load high part of byte address into ZH
 ldi ZL,low(2*message4); Load low part of byte address into ZL
 rcall loadbyte
 mov wreg,dekades
 rcall lcdput
 mov wreg,monades
 rcall lcdput
 rcall longdelay ;Wait some time
 rjmp again

;=========================================================================
;  Clear entire LCD and delay for a bit
;=========================================================================
lcdclr:
 ldi wreg,1 ;Clear LCD command
 rcall lcdcmd
 ldi timeout,256;Delay 15 mS for clear command
 rcall delay
 ret


;=========================================================================
;  Initialize LCD module
;=========================================================================

lcdinit:

 ldi wreg,0 ;Setup port pins
 out PORTD,wreg;Pull all pins low
 ldi wreg,0xff;All pins are outputs
 out DDRD,wreg
 ldi timeout,256;Wait at least 15 mS at power up
 rcall delay
 ldi wreg,3 ;Function set
 out PORTD,wreg
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi timeout,65;Wait at least 4.1 mS
 rcall delay
 ldi wreg,3 ;Function set
 out PORTD,wreg
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi timeout,2;Wait at least 100 uS
 rcall delay
 ldi wreg,3 ;Function set
 out PORTD,wreg
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi wreg,2 ;Function set, 4 line interface
 out PORTD,wreg
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi wreg,0b11110000;Make 4 data lines inputs
 out DDRD,wreg

;  At this point, the normal 4 wire command routine can be used

 ldi wreg,0b00100000;Function set, 4 wire, 2 line, 5x7 font
 rcall lcdcmd
 ldi wreg,0b00001100;Display on,  cursor off, blink off
 rcall lcdcmd
 ldi wreg,0b00000110;Address increment, no scrolling
 rcall lcdcmd

 ret

;  Wait for LCD to go unbusy
lcdwait:

 ldi wreg,0xF0;Make 4 data lines inputs
 out DDRD,wreg
 sbi PORTD,lcdrw;Set r/w pin to read
 cbi PORTD,lcdrs;Set register select to command
waitloop:

 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 in lcdstat,PIND;Read busy flag
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 sbrc lcdstat,3;Loop until done
 rjmp waitloop

 ret

;  Send command in wreg to LCD
lcdcmd:

 mov test,wreg
 rcall lcdwait
 ldi wreg,0xFF
 out  DDRD,wreg
 mov wreg,test
 mov test,wreg
 swap wreg
 andi wreg,0X0F
 out portD,wreg
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 mov wreg,test
 andi wreg,0x0F;Strip off upper bits
 out PORTD,wreg;Put on port
 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi wreg,0xF0;Make 4 data lines inputs
 out DDRD,wreg
 ret  

;  Send character data in wreg to LCD
lcdput:
 mov test,wreg;Save character
 rcall lcdwait ;Wait for LCD to be ready
 ldi wreg,0xFF;Make all port D pins outputs
 out DDRD,wreg
 mov wreg,test;Get character back
 mov test,wreg;Save another copy
 swap wreg ;Get upper nibble
 andi wreg,0x0F;Strip off upper bits
 out PORTD,wreg;Put on port
 sbi PORTD,lcdrs;Register select set for data

 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 mov wreg,test;Recall character
 andi wreg,0x0F;Strip off upper bits
 out PORTD,wreg;Put on port
 sbi PORTD,lcdrs;Register select set for data

 sbi PORTD,lcde;Toggle enable line
 cbi PORTD,lcde
 ldi wreg,0xF0;Make 4 data lines inputs
 out DDRD,wreg
 ret

longdelay:
 ldi longtime,180;
 ldi timeout,256;
puwait:
 rcall delay
 dec longtime
 brne puwait
 ret

;***** Delay n*64 microseconds using timer 0, delay time passed in timeout
delay:
 
 ldi  test,64
cagain:  dec test
 brne  cagain
 dec  timeout
 brne  delay
 ret

;=========================================================================
loadbyte:
;=========================================================================
 lpm  ; Load byte from program memory into r0

 tst r0 ; Check if we've reached the end of the message
 breq return ; If so, quit

 mov wreg,r0
 rcall lcdput ; Echo received char

 adiw ZL,1 ; Increase Z registers
 rjmp loadbyte

return:  ret  ;return
;=========================================================================


message1:
.db "Press any key",0
message2:
.db "please (1-16)",0
message3:
.db "You pressed",0
message4:
.db "key:",0



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