EE3376 Programs EE3376 Home

STRING2LCD Program

Build this using Code Warrior and the ee3376 Stationery .


;****************************************************************
;*
;* UTEP EE3376
;* string2lcd_hcs12.asm 
;* Dragon12/HCS12 board, Code Warrior v3
;* 4 Dec 03
;*
;* This lab demonstrates the basic initialization and use
;* of a Hantronix LCD (Model HDM16216L-5) on the Dragon12 HCS12 board. 
;* This is a 16 char x 2 line LCD with a 5x7 dots character format. 
;* Uses a HD44780 based controller. The Dragon12 LCD is hardwired to use
;* a 4-bit interface to Port K with pins set up as follows:
;*
;* RS = PK0 (Port K bit 0 to RS Register Selector)
;*   -> RS = 0 selects Instruction Register, RS=1 selects Data Register
;* EN = PK1 (Enable; pulse enable to latch data-write into LCD)
;* R/W = connected to ground (W = 0 since we only write)
;* DB4 = PK2; DB5 = PK3; DB6 = PK4; DB7 = PK5
;* PK6 and PK7 are unused
;*
;* The program is based on using strings to write to each line of the LCD. 
;* The final display will show string1 'Code Warrior' on line 1
;* and string2 'Dragon12' on line 2. You can modify the strings manually
;* in the program itself or in DBug12 using the 'mm' command.
;*
;****************************************************************

; export symbols
            XDEF Entry		; export 'Entry' symbol
            ABSENTRY Entry    	; for absolute assembly: mark this as application entry point


PSEUDO_ROM	EQU		$1000	; absolute address to place code/constant data
RAM		    	EQU		$1400	; absolute address to place variables
STACK			EQU		$3C00	; top of stack


; registers
portk 			EQU		$32		; 
portk_ddr		EQU		$33		; data direction register for Port K

; masks
enable			EQU		%00000010	; enable bit for enable on/off pulses
output			EQU		%11111111	; make a port an output

; constants
msec			EQU		$1770	; 6000 (=$1770) loops = 1 msec in startx loop

; LCD initialization strings; msb = most significant bits, lsb = least sig. bits
init_lcd1		EQU		$0C		; first init string we write (3 times) to LCD  on startup
init_lcd2		EQU		$08		; set to 4 bit transfer (repeat twice)
init_lcd3		EQU		$08		; set to 2 lines, 5x7 dots, 4 msb of 8 bits
init_lcd4		EQU		$20		; set to 2 lines, 5x7 dots, 4 lsb of 8 bits		
init_lcd5		EQU		$00		; display off, 4 msb
init_lcd6		EQU		$20		; display off, 4 lsb
init_lcd7		EQU		$00		; display clear, 4 msb
init_lcd8		EQU		$04		; display clear, 4 lsb
init_lcd9		EQU		$00		; entry mode 4 msb
init_lcd10		EQU		$18		; entry mode, 4 lsb (increment DDRAM, cursor moves)
init_lcd11		EQU		$00		; display on, 4 msb
init_lcd12		EQU		$3C		; display on, 4 lsb (display on, cursor on, blink on)
init_lcd13		EQU		$30		; display on, 4 lsb (display on, cursor/blink off)
		
;-----------------------------------------------------
; variable/data section
            ORG RAM

string1:			dc.b	"Code Warrior"
string2:			dc.b	"Dragon12"
length1:		dc.b	12 				; the length of string1
length2:		dc.b	8				; the length of string2
count:			ds.b	1				; buffer to hold length of string
portk_img		ds.b	1				; buffer to hold portk data

;------------------------------------------------------
; code section
	ORG	PSEUDO_ROM	;set PC to $1000

Entry:
			; do some initialization
			lds	#STACK			; initialize stack pointer
			movb	#output, portk_ddr		; make Port K an Output
			jsr	LCD_INIT 		; initialize the LCD
				
				
			; write string1 to the LCD line 1
			ldx	#string1		; pointer to string passed via reg X
			movb	length1, count		; load count buffer with length of string
			jsr	WRITE_STRING
				
			; set LCD to line 2 at DDRAM address $40, RS=0
			movb	#$30, portk_img		; RS=0, %1100 to DB7-DB4
			jsr	ENABLE_PULSE
			movb	#$00, portk_img		; RS=0, %0000 to DB3-DB0
			jsr	ENABLE_PULSE
				
			; write string2 to the LCD line 2
			ldx	#string2		; pointer to string passed via reg X
			movb	length2, count		; load count buffer with length of string
			jsr	WRITE_STRING
				
			; display on, cursor off, blink off; 2 4-bit writes needed
			movb	#init_lcd11, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd13, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
				
			swi		; end the program
							
;------------------------------------------------------
; Subroutine LCD_INIT to initialize the LCD
; sets LCD to line 1

LCD_INIT:		ldd	#$14		; wait 20 msec after power on  (need delay > 15 msec)
			jsr	DELAY
				
			; write first init string three times with various delays
			movb	#init_lcd1, portk_img
				
			; write 1/delay 1
			jsr	ENABLE_PULSE	; pulse data in portk to write it
			ldd	#$05				; wait 5 msec (need delay > 4.1 msec)
			jsr	DELAY
				
			; write 2/delay 2
			jsr	ENABLE_PULSE	; pulse data in portk to write it
			ldd	#$01				; wait 1 msec (need delay > 100 usec)
			jsr	DELAY
				
			; write 3, no delay needed
			jsr	ENABLE_PULSE	; no delay needed here
				
			; final initialization writes
			; wait > 1 msec between each write ( > 40 usec delay needed)
				
			; set to 4 bit transfers; only one 4-bit write needed
			movb	#init_lcd2, portk_img
			jsr	ENABLE_PULSE	
			ldd	#$01
			jsr		DELAY
				
			; set to 2 lines, 5x7 dot character display;  two 4-bit writes needed
			movb	#init_lcd3, portk_img
			jsr	ENABLE_PULSE	
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd4, portk_img
			jsr	ENABLE_PULSE	
			ldd	#$01
			jsr	DELAY
				
			; display off; two 4-bit writes needed
			movb	#init_lcd5, portk_img
			jsr	ENABLE_PULSE	
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd6, portk_img
			jsr	ENABLE_PULSE	
			ldd	#$01
			jsr	DELAY
				
			; display clear; two 4-bit writes needed
			movb	#init_lcd7, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd8, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
				
			; entry mode = increment, cursor move; two 4-bit writes needed
			movb	#init_lcd9, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd10, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
				
			; display on, cursor on, blink on; two 4-bit writes needed
			movb	#init_lcd11, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
			movb	#init_lcd12, portk_img
			jsr	ENABLE_PULSE
			ldd	#$01
			jsr	DELAY
				
			rts

;------------------------------------------------------
; Subroutine WRITE_STRING will write string to current line of LCD
; pass string pointer via reg X

WRITE_STRING:

begin:			ldaa	0,x	; 4 msb nibble
			ldab	0,x	; 4 lsb nibble
			lsra		; center msb nibble
			lsra
			lslb		; center lsb nibble
			lslb
			staa	portk_img		; write msb nibble
			bset	portk_img, $01		; set RS=1
			bclr	portk_img, $C2		; clear upper 2 bits and enable bit
			jsr	ENABLE_PULSE
			stab	portk_img		; write lsb nibble
			bset	portk_img, $01		; set RS=1
			bclr	portk_img, $C2		; clear upper 2 bits and enable bit
			jsr	ENABLE_PULSE
			inx
				
			dec	count		; continue for count =  length of the string
			bne	begin
						 			
			rts
				
;------------------------------------------------------
; Subroutine ENABLE_PULSE
; Used each time a write occurs; portk holds write data
; portk gets write data from buffer portk_img
; Need enable high to latch the write data, then low to clear way for next write
; Need to wait at least 40 usec after enable for function to complete - we
; build this delay into this subroutine

ENABLE_PULSE:

			; save A and B on stack since we need them
			psha
			pshb
				
			movb	portk_img, portk
				
			bset	portk,enable	; set portk  enable bit high
				
			; hold enable high for  > 230 ns
			; blcr takes 4 cycles before enable bit goes low
			; so add a couple NOPs to give 6 cycles total = 240 ns
			nop
			nop
				
			bclr	portk, enable
				
			; functions take at least 40 usec to complete
			; so add 1 msec delay before we do next function
			ldd #$01
			jsr DELAY
				
			; restore A and B
			pulb
			pula
				
			rts				
							
;------------------------------------------------------
; Subroutine DELAY - Register D contains number of Delay loops
; 1 msec delay per Delay loop	

DELAY:		
			pshx
			
			tfr	d,y
starty:			ldx	#msec
startx:			dex
			bne	startx
			dey		
			bne	starty		
			
			pulx 
			
			rts
				
;****************************************************************


EE3376 Programs EE3376 Home