; Control 2-line LCD with AT90S2313 AVR RISC Processor ; Using 4-wire interface ; ; Charles R. Ott ; May 22, 1998 .nolist ;Suppress listing of include file .include "2313def.inc" ;Define chip particulars .list ;***** 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 ;***** 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 ; Timer/Counter prescaler values .equ TSTOP =0 ;Stop Timer/Counter .equ TCK1 =1 ;Timer/Counter runs from CK .equ TCK8 =2 ;Timer/Counter runs from CK / 8 .equ TCK64 =3 ;Timer/Counter runs from CK / 64 .equ TCK256 =4 ;Timer/Counter runs from CK / 256 .equ TCK1024 =5 ;Timer/Counter runs from CK / 1024 .equ TEXF =6 ;Timer/Counter runs from external falling edge .equ TEXR =7 ;Timer/Counter runs from external rising edge .cseg ; Interrupt vectors .org 0 rjmp reset ;Reset Vector .org INT0addr ;External Interrupt0 Vector reti .org INT1addr ;External Interrupt1 Vector reti .org ICP1addr ;Input Capture1 Interrupt Vector reti .org OC1addr ;Output Compare1 Interrupt Vector reti .org OVF1addr ;Overflow1 Interrupt Vector reti .org OVF0addr ;Overflow0 Interrupt Vector rjmp t0int .org URXCaddr ;UART Receive Complete Interrupt Vector reti .org UDREaddr ;UART Data Register Empty Interrupt Vector reti .org UTXCaddr ;UART Transmit Complete Interrupt Vector reti .org ACIaddr ;Analog Comparator Interrupt Vector reti ; Main program entry point on reset reset: ldi wreg,RAMEND ;Init Stack Pointer out SPL,wreg ldi wreg,TSTOP ;Timer 0 off (just in case) out TCCR0,wreg ;Stop timer ldi wreg,0b00000010 ;Enable Timer 0 interrupt out TIMSK,wreg sei ;Enable interrupts ldi wreg,0xFF ;Turn off all LEDs out PORTB,wreg ldi wreg,0xFF ;Make port B pin all outputs out DDRB,wreg ldi longtime,100 ;Wait 1.5 second for LCD power up ldi timeout,256 ;Delay 15 mS puwait: rcall delay dec longtime brne puwait main: rcall lcdinit ;Initialize LCD module rcall lcdclr ;Clear LCD screen ldi wreg,0x80 ;Set address to line 1 rcall lcdcmd ldi ZH,high(message*2) ldi ZL,low(message*2);Init Z-pointer nextc: lpm ;Get next character from ROM tst R0 ;See if at end of message breq line2 ;If so, do next message mov wreg,R0 ;Send it rcall lcdput adiw ZL,1 ;Increment Z-pointer rjmp nextc ;Loop for more line2: ldi wreg,0xC0 ;Set address to line 2 rcall lcdcmd ldi ZH,high(message2*2) ldi ZL,low(message2*2);Init Z-pointer nextc2: lpm ;Get next character from ROM tst R0 ;See if at end of message breq halt ;If so, quit mov wreg,R0 ;Send it rcall lcdput adiw ZL,1 ;Increment Z-pointer rjmp nextc2 ;Loop for more halt: rjmp halt ;Sit here forever..... ; 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: cbi PORTB,0 ;Turn on LED 0 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 ; rcall strobe ;Toggle enable line 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 ; rcall strobe ;Toggle enable line 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 ; rcall strobe ;Toggle enable line sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde ldi wreg,2 ;Function set, 4 line interface out PORTD,wreg ; rcall strobe ;Toggle enable line 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,0b00101000 ;Function set, 4 wire, 2 line, 5x7 font rcall lcdcmd ldi wreg,0b00001100 ;Display on, no cursor, no blink rcall lcdcmd ldi wreg,0b00000110 ;Address increment, no scrolling rcall lcdcmd sbi PORTB,0 ;Turn off LED 0 ret ; Wait for LCD to go unbusy lcdwait: cbi PORTB,1 ;Turn on LED 1 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: ; rcall strobe sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde in lcdstat,PIND ;Read busy flag ; rcall strobe ;Read, and ignore lower nibble sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde sbrc lcdstat,3 ;Loop until done rjmp waitloop sbi PORTB,1 ;Turn off LED 1 ret ; Send command in wreg to LCD lcdcmd: push wreg ;Save character rcall lcdwait ;Wait for LCD to be ready ldi wreg,0xFF ;Make all port D pins outputs out DDRD,wreg pop wreg ;Get character back push wreg ;Save another copy swap wreg ;Get upper nibble andi wreg,0x0F ;Strip off upper bits out PORTD,wreg ;Put on port ; rcall strobe sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTD,wreg ;Put on port ; rcall strobe 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: push wreg ;Save character rcall lcdwait ;Wait for LCD to be ready ldi wreg,0xFF ;Make all port D pins outputs out DDRD,wreg pop wreg ;Get character back push 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 ; rcall strobe sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTD,wreg ;Put on port sbi PORTD,lcdrs ;Register select set for data ; rcall strobe sbi PORTD,lcde ;Toggle enable line cbi PORTD,lcde ldi wreg,0xF0 ;Make 4 data lines inputs out DDRD,wreg ret ;***** Timer 0 overflow interrupt handler t0int: set ;Set T flag ldi wreg,TSTOP ;Timer 0 off out TCCR0,wreg ;Stop timer reti ;Done, return ;***** Delay n*64 microseconds using timer 0, delay time passed in timeout delay: in wreg,SREG ;Save status register push wreg out TCNT0,timeout clt ;Clear T ldi wreg,TCK256 ;Timer 0 prescaler, CK / 256 out TCCR0,wreg ;Run timer dwait: brtc dwait ;Wait for timer 0 interrupt to set T pop wreg ;Restore status register out SREG,wreg ret message: .db "Time 09:45:33 PM",0 message2: .db "Temp 75.6",0xDF," F",0