8051 LCD 'Hello World' - replacing DB with variable

只谈情不闲聊 提交于 2019-12-03 21:42:27

dptr contains the address of the text to display. So, if you replace #mesg1 with something like

mov dptr, #045h

you are outputting the (random) contents from memory at address 0x45, which explains the scrambled characters you see.

In order to output some decimal value, you need to convert it to an ascii string first, then you can use your existing wr_string routine to get it printed. See http://www.electro-tech-online.com/microcontrollers/14371-hex-decimal-then-ascii.html for a code sample (i,j,k contains the result string which you still need to zero-terminate for your wr_string routine).


The following code shows a similar routine. Note that wr_string needs to be modified to read the data from XDATA, not from code memory (movx a, @dptr instead of clr a / movc a, @a+dptr):

    ORG     08100h

hello:
    mov     r7, #42        ; value to convert
    mov     dptr, #buffer  ; destination buffer
    acall   str2ascii      ; convert value

    mov     P2, #(lcd_cmd SHR 8)   ; load P2 with high address
    mov     R0, #(lcd_cmd AND 255) ; load R0 with command reg addr
    mov     R7, #03h        ; set LCD position, line=1, char=3
    mov     dptr, #buffer   ; point to buffer
    acall   wr_string       ; write buffer to LCD

...

str2ascii:
; Converts a one byte decimal value into its ASCII string representation.
; Result is prepended with leading zeroes.
; 0   becomes "000"
; 42  becomes "042"
; 255 becomes "255"
;
; @param r7    Input value to convert (1 byte, 0 .. 255)
; @param dptr  Destination buffer, at 4 bytes (3 digits plus \0)
;
    mov     a, r7
    mov     b, #100
    div     ab        ; leftmost digit in a
    add     a,#30h    ; convert to ASCII
    movx    @dptr, a
    inc     dptr

    mov     a,b       ; get reminder
    mov     b,#10
    div     ab        ; middle digit in a, rightmost digit in b
    add     a,#30h    ; convert to ASCII
    movx    @dptr, a
    inc     dptr

    mov     a,b
    add     a,#30h    ; convert to ASCII
    movx    @dptr,a
    inc     dptr

    mov     a,#0
    movx    @dptr, a  ; terminate string
    ret

    xseg
buffer:     ds 17     ; one LCD line plus terminating \0

    end

On your code, dptr contains the address of your code memory which has the string you want to output. So, if you change #mesg1 to some hex value, like this:

mov dptr, #mesg1

LCD will try to write the ascii value which is on this hex address. And you don't know what it contains. In order to output variables on LCD (just like registers values), you should be attempted to:

1 - You can't store variable data on program memory with DB instruction. It doesn't work. You should write your variable value on internal or external data memory. For example, you can't do this:

   MOV dptr, #mesg1                    ;point to mesg1
   ACALL   wr_string                   ;write mesg1 to LCD

;LOTS OF INSTRUCTIONS...

mesg1:
   DB 'MY STRING'            
   DB R1                               ;In case that R1 is your variable          

In above example, LCD will only output MY STRING, independently the value of R1

2 - You need to convert the value of your variable (which will be on binary, decimal or hexadecimal) to ASCII. Just for 0 to 9, this is a very easy task. Just add to your variable the hexadecimal value 30H. So, for example:

    mov R1, #9H               ;in case that R1 is your variable with some number
    MOV A, R1
    ADD A, #30H
    MOV R1, A                 ;R1 will store #39H, which is the ascii value for number 9

Thus, an option is to split your variable into individual decimal numbers, and then convert to ascii every one. The code here do this, and stores each ascii value on variables i, j, k.

What I used to, is to use two functions: one for read strings from code memory, which was previously stored by DB instruction, and another to read variables values from internal memory:

    lcd_port EQU P1               ;The port that I send data to LCD
    data EQU #41H                 ;Some random register in internal data memory

    MOV DPTR, #my_string       
    ACALL lcd_string              ;This function will write on LCD some string

    MOV A, R1                     ;In case that R1 is my variable
    MOV data, A
    ACALL lcd_dta                 ;Writes R1 value on LCD

lcd_string:
    MOV A, #0x00
    MOVC A, @A+DPTR      
    JZ end_lcd_string    
    MOV DATA, A          
    CALL lcd_data        
    INC DPTR             
    JMP lcd_string       
end_lcd_string:        
    RET

lcd_data:
    CALL lcd_busy               ;verify if the LCD is busy, just like your function
    SETB LCD_RS                 ;Set bit on LCD RS pin
    SETB LCD_E                  ;Set bit on LCD Enable pin
    MOV lcd_port                ;Move your data to LCD
    CLR LCD_E                   ;Turn LCD Enable pin to 0
    RET

my_string:
    DB 'HELLO WORLD'

The above code should output on LCD the string HELLO WORLD, followed by R1 value.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!