1

独自の 8051 ボードを使用して、アセンブリ プログラミングを学習しています。私は現在、LCD 'Hello World' プログラムに取り組んでいます。これがコードです。

lcd_cmd equ 0800h           ;Write COMMAND reg address 0800h
lcd_st  equ 0801h           ;Read STATUS reg address 0801h
lcd_wr  equ 0802h           ;Write DATA reg address 0802h
lcd_rd  equ 0803h           ;Read DATA reg address 0803h

ORG 08100h

hello:  
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, #mesg1                    ;point to mesg1
acall   wr_string                   ;write mesg1 to LCD

mov R7, #41h                        ;set LCD position, line= 2, char=1
mov dptr, #mesg2                    ;point to mesg2
acall   wr_string                   ;write mesg2 to LCD

stop:   ajmp    stop                ;soft halt  

wr_string:
acall   lcd_busy        ;wait until LCD not busy
mov a, R7                           ;get LCD position
orl a, #080h                        ;msb set for LCD RAM address
movx    @R0, a                      ;write lcd_cmd to set line & char
nxt_char:
acall   lcd_busy                    ;wait until LCD not busy
clr a
movc    a, @a+dptr          
inc dptr                            ;point to next byte in string
jz  str_end                         ;if 0 then end of string

mov R1, #(lcd_wr AND 255)           ;Load R1 with wr_data address
movx    @R1, a                      ;Write char to LCD
sjmp    nxt_char                    ;get next char in string
str_end:    ret

lcd_busy:
mov R1, #(lcd_st AND 255)       ;Load R1 with status address
movx    a, @R1                          ;read LCD status
jb  acc.7, lcd_busy         ;keep checking until busy bit clear
ret

mesg1:  db  "Hello   ",0
mesg2:  db  "World ",0
END

すべて正常に動作します。ただし、変数をLCDに出力するのに問題があります。#mesg1 を 16 進値 (簡単にするために ascii) に置き換えると、単純にスクランブルされた文字が画面に表示されます。毎回値を単純にインクリメントするサブルーチンを呼び出す場合も同様です。そのため、データが dptr に移動されたときにデータがどのような形式になるべきかわかりません。

私が見逃した愚かなことはありますか?

ありがとう!

4

2 に答える 2

1

dptraddress表示するテキストの が含まれます。したがって、#mesg1次のようなものに置き換えると

mov dptr, #045h

アドレス 0x45 のメモリから (ランダムな) コンテンツを出力しています。これは、表示されるスクランブルされた文字を説明しています。

10 進数値を出力するには、最初にそれを ASCII 文字列に変換する必要があります。その後、既存のwr_stringルーチンを使用して出力することができます。コード サンプルについては、 http://www.electro-tech-online.com/microcontrollers/14371-hex-decimal-then-ascii.htmlを参照してください(i、j、k には、まだゼロで終了する必要がある結果の文字列が含まれています) wr_string ルーチン用)。


次のコードは、同様のルーチンを示しています。wr_stringコードメモリからではなくXDATAからデータを読み取るように変更する必要があることに注意してください(movx a, @dptr代わりに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
于 2013-01-10T16:10:18.440 に答える