Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
05/28/07 18:23
Read: times


 
#139934 - LCD asm printf function
Responding to: ???'s previous message
Hi, I think this could be useful for some one. Here is an asm function similar to C's printf, to use with a LCD in 4 bit mode:

Functions this way: you push in to the stack the numbers you want to display, then you call the LcdPrintf function with DPTR pointing to the string you want to display. When the function finds a 0xD0 in the middle of the string it will be replaced by the next value poped from the stack. It also interprets number above 0x80 as "positioning commands": 0x80 puts the cursor on the 1st lin 1st col, 0xC0 = 2nd line 1st col, 0xC1 = 2nd line 2nd cols, and so on. 0xF0 tells that is the end of the string.


Code and example (I'll put it in the code library):
Themost usefull part for you might be the "DispNum" function

PS.: LcdStats should be declared on the IRAM, it holds the status of the RS line and the Back light (pin 7)

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

; LCD Routines:

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

;********************************************************************

; Sends Commands or Chars on ACC to the LCD nibble per nibble

; To send char do an AND on LcdStat with LCD_RS

; Destroys: r6 & r7

;********************************************************************

LcdWrite:

mov r6, #2 ; Sending 2 nibbles

mov r7, a ; backup a

swap a ; high nibble first

_LcdWLoop:

anl a, #0x0F ; discard high nibble

orl a, LcdStat ; get the RW, RS & BL status

mov LCD, a

setb LCD_PEN ; Clock the Enable pin

clr LCD_PEN ; /

acall LcdBusy ; wait the busy bit to clear

mov a, r7 ; restore to send low nibble

djnz r6, _LcdWLoop

ret



;********************************************************************

; LcdRead: Reads a byte from LCD in the Acc

;********************************************************************

LcdRead:

mov LCD, #0x2F ; Pull high the data pins

_LcdB: ; & RW pin (RS & EN low)

setb LCD_PEN ; Reads the first 4 bits

mov a, LCD

clr LCD_PEN

anl a, #0x0F ; Use just low nibble

swap a ; first is the high nibble

push acc

setb LCD_PEN ; Reads the last 4 bits

mov a, LCD

clr LCD_PEN

anl a, #0x0F ; Use just low nibble

mov r5, a

pop acc

orl a, r5 ; combine whole byte

ret



;********************************************************************

; LcdBusy: Wait until busy is clear

;********************************************************************

LcdBusy:

acall LcdRead

jb acc.7, LcdBusy

ret



;********************************************************************

; Initializes the LCD in 4 bit mode, 2 lines x 16 cols

;********************************************************************

_LcdISeq: .db 0x33, 0x32, 0x28, 0x06, 0x01, 0x0F, 0x0C

LcdInit:

mov r0, #7 ; send 7 bytes

mov dptr, #_LcdISeq

_LcdILoop:

clr a

movc a, @a+dptr ; get the init seq bytes

inc dptr



mov r4, #2 ; sending 2 nibbles

mov r5, a ; backup byte on r5

swap a ; get first nibble

_LcdLoop2:

anl a, #0x0F

mov LCD, a

setb LCD_PEN

clr LCD_PEN



mov r7, #10 ; Do some delay because the

_LcdILoop3: ; busy bit cant be read yet

djnz r6, _LcdILoop3

djnz r7, _LcdILoop3



mov a, r5 ; get the original byte

djnz r4, _LcdLoop2 ; send second nibble



djnz r0, _LcdILoop ; Loop for 7 bytes

ret



;********************************************************************

; Prints a formated string ended by #0xF0 on the LCD

; Format: if encounter one of thiz do that:

; 0x80 to 0xCF -> position cursor

; 0xD0 -> same as printf %d (prints 1 byte on the stack

; as decimal a number.)

; 0xE0 -> Clear LCD

; 0xF0 -> End of String

;********************************************************************

LcdPrintf:

pop 0x01 ; get the dptr pushed by acall on r1 & r2

pop 0x02 ; to get the right params for printf

__LcdPrintf:

clr a

movc a, @a+dptr ; get next byte

inc dptr ; point to next byte

cjne a, #0xF0, _KeepPrint ; check for end

push 0x02 ; restore the dptr ptr

push 0x01

ret

_KeepPrint:

mov r0, a ; backup

subb a, #0x80 ; check if ch is less

jc _NormalChars ; then 0x80 (normal ch)

mov a, r0

subb a, #0xD0 ; check if ch is > 0x80 & < 0xCF

jnc _NoPos

mov a, r0

acall LcdWrite ; (positioning)

sjmp __LcdPrintf

_NoPos:

cjne r0, #0xD0, _NoDecimal ; check for a = 0xD0 (above subb)

orl LcdStat, #LCD_RS ; this will send chars

pop acc ; get the ch to print as decimal

acall DispNum ; from the stcak

xrl LcdStat, #LCD_RS ; back to commands

sjmp __LcdPrintf

_NoDecimal:

cjne r0, #0xE0, __LcdPrintf ; check for a = 0xE0

mov a, #0x01 ; clear command

acall LcdWrite

sjmp __LcdPrintf

_NormalChars:

orl LcdStat, #LCD_RS ; this will send chars

mov a, r0 ; get the ch to print

acall LcdWrite ; send the char

xrl LcdStat, #LCD_RS ; back to commands

sjmp __LcdPrintf



;********************************************************************************************

; DispNum: Show the acc on the LCD as a decimal number

; LcdStat must be already orld with LCD_RS

;********************************************************************************************

DispNum:

mov b, #100

div ab

jz DispNoCent

add a, #48 ; to ASCII

acall LcdWrite

DispNoCent:

mov a, b

mov b, #10

div ab

add a, #48 ; to ASCII

acall LcdWrite

mov a, b

add a, #48 ; to ASCII

acall LcdWrite

ret




Example:

TESTSTR: .db 0xE0, "LcdStat: ", 0xD0, 0xF0
mov dptr, #TESTSTR
push LcdStat

acall LcdPrintf



List of 12 messages in thread
TopicAuthorDate
Display number on LCD 2x16            01/01/70 00:00      
   How far have you got?            01/01/70 00:00      
   perhaps reading the datasheet would help            01/01/70 00:00      
      Andy & Richard            01/01/70 00:00      
         Sorry!            01/01/70 00:00      
         Apologies where due, I guess I missed that.            01/01/70 00:00      
   A bit of help            01/01/70 00:00      
      See Code Library            01/01/70 00:00      
   convert to ASCII            01/01/70 00:00      
      Not BCD            01/01/70 00:00      
   Thanks            01/01/70 00:00      
      LCD asm printf function            01/01/70 00:00      

Back to Subject List