;----------------------------------------------------------------------------- ; Copyright (C) 2012 .... ; ; Programmer : Larry Aamodt ; ; File name : lcd_routines.asm ; Language : ARM assembly ; Assembler ; Keil ; Target MCU : NXP LPC2148 on Embedded Artists education board ; Date : 12/05/12 LDA lcd_routines.asm. debugged ; ; Description : LCD display routines ; Copy this code to your own program ; ; Procedures you can call are: ; lcdReset must be called first. no parameters. ; lcdClear use to clear the display & home the cursor ; no parameters are required. ; lcdWRdata use to write one character on the display ; place an ASCII char in r0 before calling. ; The cursor will advance. ; lcdCursorAt use to move the cursor. Two parameters ; r0 = row (1 or 2) ; r1 = column to move cursor to (0-15) ; ; Example use of the LCD routines: ; bl lcdReset ; do this once at the top of your program ; ; mov r0,#31h ; place the ascii code for number one in r0 ; bl lcdWRdata ; display the character '1' on LCD display ; ; bl lcdClear ; clear the display ; ; mov r0,#1 ; select LCD row 1 ; mov r1,#4 ; select LCD column 4 ; bl lcdCursorAt ; move the cursor ; ; ; NOTE: All registers are saved by these routines, i.e. upon return ; from the subroutine all registers, except flags, have the ; same value in them as before the subroutine was called (this ; breaks with the ARM convention for subroutines but is done ; to make it easier for you). ; ;----------------------------------------------------------------------------- AREA lcdroutines,CODE,READONLY EXPORT lcdReset EXPORT lcdClear EXPORT lcdWRdata EXPORT lcdCursorAt EXPORT delay ; ----------------------------------------------------------------------------- ; LCD Procedures follow. ;------------------------------------------------------------------------------ ; ***** LCD equates ****** IO0PIN EQU 0xE0028000 IO0SET EQU 0xE0028004 IO0DIR EQU 0xE0028008 IO0CLR EQU 0xE002800C IO1PIN EQU 0xE0028010 IO1SET EQU 0xE0028014 IO1DIR EQU 0xE0028018 IO1CLR EQU 0xE002801C T0_TCR_ADDR EQU 0xE0004004 T0_PR_ADDR EQU 0xE000400C T0_MCR_ADDR EQU 0xE0004014 T0_MR0_ADDR EQU 0xE0004018 ; ----------------------------------------------------------------------------- ; Procedure lcdReset Must be called before writing to the LCD ; No parameters required ; ----------------------------------------------------------------------------- lcdReset STMFD SP!,{LR,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9} LDR r1,=T0_PR_ADDR ; Prescale register MOV r2,#2 ; prescale count value STR r2,[r1] ; Prescaler will divide by 3 LDR r1,=T0_MCR_ADDR ; Match control register MOV r2,#0x6 ; bit 2 = one STR r2,[r1] ; stop counter when match reached LDR r5,=IO0CLR LDR r6,=IO0SET LDR r7,=IO1CLR LDR r8,=IO1SET LDR r0,=35000 BL delay ; delay 35ms LDR r0,=IO0DIR LDR r4,[r0] ; read current Port 0 direction bits LDR r3,=0x40408000 ; one's for pins to be set for output ORR r4,r4,r3 ; bits 22 & 30 to be outputs STR r4,[r0] ; set lcd port bits to output LDR r3,=0x00400000 ; STR r3,[r5] ; write 0 to LCD R/W signal LDR r3,=0x40008000 STR r3,[r6] ; turn on backlight - write 1 to P0.30 LDR r0,=IO1DIR LDR r4,[r0] ; read current Port 1 direction bits LDR r3,=0x03FF0000 ; one's for lcd pins - set for output ORR r4,r4,r3 ; bits 16 to 25 to be outputs STR r4,[r0] ; set lcd port direction bits to output STR r3,[r7] ; clear the LCD data & control bits LDR r9,=0x02000000 ; bit pattern to turn on/off E LDR r2,=0x00380000 ; function: 2 lines, 5x7 dots STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits MOV r0,#40 BL delay ; wait 40 microseconds LDR r2,=0x000E0000 ; function: display on, cursor on STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits MOV r0,#40 BL delay ; wait 40 microseconds LDR r2,=0x00010000 ; lcd function: clear display STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits MOV r0,#1600 BL delay ; delay for 1600 microseconds LDR r2,=0x00030000 ; lcd function: set entry mode STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits end_lcdReset LDMFD SP!,{PC,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9} ;------------------------------------------------------------------------------ ; Procedure pulse_e uses r0. Not interuptable (r14 not saved) ; assumes r9 has 0x02000000 in it ; assumes r7 has IO1CLR address in it ; assumes r8 has IO1SET address in it ;------------------------------------------------------------------------------ pulse_e MOV r0,#4 STR r9,[r8] ; assert E ploop1 SUBS r0,r0,#1 ; delay 600ns or so BNE ploop1 STR r9,[r7] ; de-assert E MOV r0,#8 ploop2 SUBS r0,r0,#1 ; delay 1100ns or so BNE ploop2 end_pulse_e BX LR ; ----------------------------------------------------------------------------- ; Procedure lcdClear Clears the LCD and positions cursor to line1, left col ; no parameters required ; ----------------------------------------------------------------------------- lcdClear STMFD SP!,{LR,r0,r1,r2,r3,r7,r8,r9} LDR r9,=0x02000000 ; bit pattern to turn on/off E LDR r3,=0x03FF0000 ; one's for pins used for lcd LDR r7,=IO1CLR LDR r8,=IO1SET LDR r2,=0x00010000 ; lcd function: clear display STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits MOV r0,#1600 BL delay end_lcdClear LDMFD SP!,{PC,r0,r1,r2,r3,r7,r8,r9} ; ----------------------------------------------------------------------------- ; Procedure lcdCursorAt ; r0 assumed to contain the row# (1 or 2) ; r1 assumed to contain col#(0-15) ; No cursor movement if invalid row or col # is found ; ----------------------------------------------------------------------------- lcdCursorAt STMFD SP!,{LR,r0,r1,r2,r3,r7,r8,r9} CMP r1,#15 ; check column & row range BHI end_lcdCursorAt CMP r0,#0 BEQ end_lcdCursorAt CMP r0,#2 BHI end_lcdCursorAt ADDEQ r1,r1,#0x40 ; build the cursor address LDR r0,=0x00800000 ORR r2,r0,r1,LSL #16 ; r2 now has the address LDR r3,=0x03FF0000 ; one's for pins used for lcd LDR r7,=IO1CLR LDR r8,=IO1SET LDR r9,=0x02000000 ; bit pattern to turn on/off E STR r2,[r8] ; set lcd function bits BL pulse_e STR r3,[r7] ; clear lcd bits MOV r0,#40 BL delay end_lcdCursorAt LDMFD SP!,{PC,r0,r1,r2,r3,r7,r8,r9} ; ----------------------------------------------------------------------------- ; Procedure lcdWRdata Writes data (an ASCII character) to the ; current cursor position on the LCD ; r0 is assumed to contain the character to send ; ----------------------------------------------------------------------------- lcdWRdata STMFD SP!,{LR,r0,r1,r2,r3,r7,r8,r9} LDR r9,=0x02000000 ; bit pattern to turn on/off E LDR r3,=0x03FF0000 ; one's for pins used for lcd LDR r7,=IO1CLR LDR r8,=IO1SET AND r0,r0,#0xFF ; make sure only 8 bits are non-zero ORR r0,r0,#0x100 ; set bit that indicates writing LSL r0,r0,#16 STR r0,[r8] ; write data BL pulse_e STR r3,[r7] ; clear lcd bits end_lcdWRData LDMFD SP!,{PC,r0,r1,r2,r3,r7,r8,r9} ; ----------------------------------------------------------------------------- ; Procedure delay microsecond delay using timer 0 ; (12Mhz clock & VPB divide by 4 assumed) ; reg R0 must contain a delay value in uS ; Not interruptable (r14 not saved) ; assumes lcdReset has been called prior to delay ; r0, r1 not preserved ; ----------------------------------------------------------------------------- delay LDR r1,=T0_MR0_ADDR ; Match register zero STR r0,[r1] ; load match count per R0 ; ldr r0,=0x8000 ; str r0,[r5] ; turn on p0.15 led LDR r1,=T0_TCR_ADDR ; Timer 0 Control Register MOV r0,#2 ; bit 1 = one STR r0,[r1] ; Clear counter & prescaler MOV r0,#0 STR r0,[r1] MOV r0,#1 ; bit 0 = one STR r0,[r1] ; Turn on counter dloop LDR r0,[r1] ; Read TCR register ANDS r0,r0,#1 BNE dloop ; ldr r0,=0x8000 ; str r0,[r6] ; turn off p0.15 led end_delay BX LR ; Return END