??? 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 |
Topic | Author | Date |
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 |