Full Version : Ott-Land 16x1 Char 4-Wire LCD Routines (ASM)
avr >>LCD BASED PROJECTS >>Ott-Land 16x1 Char 4-Wire LCD Routines (ASM)


Admin5- 04-19-2006
Bruce Land's version of Charles Ott's LCD Routine lcd2.asm

Control a 16 char x 1-line LCD using 4-wire bus interface (plus 3 control lines) AT90S4414

by Charles R. Ott Modified by Bruce Land for EE476 at Cornell

Port D controls the LCD
Port A, pin 7, supplies power to the LCD
Port B is used for diagnostic LED displays


CODE

;   Control a 16 char x 1-line LCD with AT90S4414 AVR Processor
;   Using 4-wire bus interface (plus 3 control lines)
;
;   Charles R. Ott
;   May 22, 1998

;-----------------------------------

;   Modified by Bruce Land for EE476 at Cornell

;   Jan 1999

;

;   Port D controls the LCD

;   Port A, pin 7,  supplies power to the LCD

;   Port B is used for diagnostic LED displays

;

;   The program sets up the display, displays an EE 476 message.

;   then endlessly loops, writing out characters.

;   The LCD is sensitive to power up.

;-----------------------------------

.nolist            ;Suppress listing of include file
.include "4414def.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

.def    charcnt =r20      ;Char position on the display

.def    chr =r21      ;a variable character to print

;***** 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 enable 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 $0000

   rjmp    RESET  ;reset entry vector

   reti        

   reti

   reti

   reti

   reti

   reti

   rjmp    t0int

   reti

   reti        

   reti

   reti    

   reti

;   Main program entry point on reset

reset:  ldi wreg, LOW(RAMEND);setup stack pointer

   out     SPL, wreg

   ldi wreg, HIGH(RAMEND)

   out SPH, 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,0x0F  ;Turn on four LEDs
 ;out    PORTB,wreg
   ldi wreg,0xFF  ;Make port B pin all outputs
   out DDRB,wreg



 ;power down the LCD

   ldi wreg, 0xff;LCD power connection

   out DDRA, wreg;power it down after reset

   ldi wreg, 0x00

   out PORTA,wreg

   ldi longtime,100  ; then Wait 1.5 second with LCD power off
   ldi timeout,0  ;Delay 15 mS

offwait:rcall   delay
   dec longtime
   brne    offwait



 ;now power up LCD

   ldi wreg, 0xff

   out PORTA, wreg
   ldi longtime,100  ;Wait 1.5 second for LCD power up
   ldi timeout,0  ;Delay 15 mS  
puwait: rcall   delay
   dec longtime
   brne    puwait

   ldi wreg,0xFF  ;Turn off all LEDs
   out PORTB,wreg



 ;hopefully by now the LCD has rebooted
main:   rcall   lcdinit    ;Initialize LCD module
   rcall   lcdclr    ;Clear LCD screen

   clr charcnt    ;zero the character count

   ldi chr, 0x20  ;load var char with first printable

   ldi ZH,high(message*2);first message addr to Z-ptr
   ldi ZL,low(message*2);Init Z-pointer
nextc:  lpm        ;Get next character from ROM
   tst R0    ;See if at end of message
   breq    end1      ;If so, next message

   cpi charcnt,8  ;addressing changes at char #8!

   brne    wrtit      ;at char 8, fix it

   ldi wreg,0xC0  ;Set address to last 8 chars

   rcall   lcdcmd  
wrtit:  mov wreg,R0    ;Send it to the LCD
   rcall   lcdput
   adiw    ZL,1      ;Increment Z-pointer

   inc charcnt    ;keep track of chars on display
   rjmp    nextc      ;Loop for more



end1:   ldi longtime,100  ;Wait 1.5 second for human to read it
   ldi timeout,0  ;Delay 15 ms    
wait1   :rcall  delay
   dec longtime
   brne    wait1



;now the second message

mloop:  rcall   lcdclr    ;Clear LCD screen

   clr charcnt    ;zero the character count

   ldi ZH,high(mess2*2);get the second message
   ldi ZL,low(mess2*2);Init Z-pointer
nextc2: lpm        ;Get next character from ROM
   tst R0    ;See if at end of message
   breq    end2      ;If so, next message

   cpi charcnt,8  ;addressing changes at char #8

   brne    wrtit2    ;fix it

   ldi wreg,0xC0  ;Set address to last 8 chars

   rcall   lcdcmd  
wrtit2: mov wreg,R0    ;Send it
   rcall   lcdput
   adiw    ZL,1      ;Increment Z-pointer

   inc charcnt    ;keep track of chars
   rjmp    nextc2    ;Loop for more



end2:   mov wreg, chr  ;print one more char

   rcall   lcdput

   inc chr    ;the next printable char

   ldi longtime,15;Wait .3 second  
   ldi timeout,0  ;Delay 15 mS

wait3:  rcall   delay
   dec longtime
   brne    wait3


   rjmp    mloop      ;print 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



;   LCD specs call for 3 repetitions as follows
   ldi wreg,3    ;Function set
   out PORTD,wreg;to 8-bit mode

   nop        ;nop is data setup time
   sbi PORTD,lcde;Toggle enable line
   cbi PORTD,lcde


   ldi timeout,256;Wait at least 15 mS
   rcall   delay


   ldi wreg,3    ;Function set
   out PORTD,wreg

   nop
   sbi PORTD,lcde;Toggle enable line
   cbi PORTD,lcde


   ldi timeout,256;Wait at least 15 ms
   rcall   delay


   ldi wreg,3    ;Function set
   out PORTD,wreg

   nop
   sbi PORTD,lcde;Toggle enable line
   cbi PORTD,lcde



   ldi timeout,256;Wait at least 15 ms
   rcall   delay


   ldi wreg,2    ;Function set, 4 line interface
   out PORTD,wreg

   nop
;   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
   

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


   ldi wreg,0b00100000;Function set, 4 wire, 1 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:
   sbi PORTD,lcde;Toggle enable line
   cbi PORTD,lcde
   in  lcdstat,PIND  ;Read busy flag
 ;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

   nop        ;wait for data setup time
   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

   nop
   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

   nop
   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

   nop
   sbi PORTD,lcde;Toggle enable line
   cbi PORTD,lcde

 ;cbi    PORTD,lcdrs;--


   ldi wreg,0xF0  ;Make 4 data lines inputs
   out DDRD,wreg
   ret


=============================================
;***** Timer 0 overflow interrupt handler
t0int:
   set        ;Set T flag

   ldi wreg,0xFF  ;Turn off all LEDs
   out PORTB,wreg
   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

; weird construction, interrupt is called like a subroutine


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


=============================================

; text data
message:
   .db "Testing EE476", 0x00

mess2:

   .db "Printable chrs=", 0x00





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