我使用的是专有的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用十六进制值(ASCII让事情变得简单),只需调出屏幕上的乱码。 所以确实调用子程序这只是增加每次的值,所以我不能确定时,它的移动到DPTR应该是什么格式的数据。
任何愚蠢的事我已经错过了?
谢谢!
dptr
包含address
显示文本的。 所以,如果你更换#mesg1
喜欢的东西
mov dptr, #045h
你在地址0×45,这说明你看到乱码输出从存储器(随机)内容。
为了输出一些十进制值,则需要先将其转换为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
在你的代码,DPTR包含有要输出的字符串代码存储器的地址。 所以,如果你改变#mesg1一些十六进制值,如下所示:
mov dptr, #mesg1
LCD会尝试写的ASCII值是这个十六进制地址。 而你不知道它包含什么。 为了LCD(就像寄存器中的值)的输出变量,你应该尝试:
1 - 你不能存储与DB指令程序内存变量数据。 它不工作。 你应该写内部或外部数据存储器的变量值。 例如,你可以这样做:
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
在上面的例子中,液晶将只输出MY STRING,独立于R1的值
2 - 您需要将变量值(这将是二进制,十进制或十六进制),以ASCII转换。 只是0到9,这是一个很容易的事。 只需添加到您的变量的十六进制值30H。 因此,举例来说:
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
因此,选择是你的变量分成独立的十进制数,然后转换为ASCII每一个人。 在这里代码做到这一点,并存储在变量I,J,K每个ASCII值。
什么我所用,是使用两个功能:一个是从代码存储器读取串,这是以前由DB指令存储,另一个读从内部内存变量值:
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'
上面的代码应在LCD上输出的串HELLO WORLD,随后R1值。