我必须使用组件在8051上创建一个数字电压表。我有一个在LCD上以十六进制输出但我无法以十进制输出。
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
LEDs equ p1 ;LEDs on port 1
DAC equ 0600h ;DAC mapped at address 0600h
ORG 08100h
DVM: 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,#00h
mov dptr, #mesg3
acall wr_string
mov R7,#40h
mov dptr, #mesg3
acall wr_string
mov R7, #01h ;set LCD position, line=1, char=1
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
acall start ;repeat
acall print_hex3
sjmp DVM
Start:
mov dptr,#DAC ;load dptr address of DAC
mov R7,#10000000b ;initialise Event
mov a,#0 ;initialise DAC value
nxtbit: xrl a,r7 ;Ex-OR DAC value with Event
movx @dptr,A ;Output DAC value
acall delay
jb P3.5,keep ;if comparator +ve keep set bit
xrl a,R7 ;else reset bit
keep: xch a,R7 ;R7?A (move R7 to A so we can rotate it)
clr c ;make sure we put zero in MSB
rrc a ;Rotate R7 right through carry
xch a,R7 ;R7?A (mov A back to R7 & restore A)
jnc nxtbit ; repeat nxtbit until all bit done
cpl a ;invert Dac Value
mov LEDs,a ;write Dac Value to LEDs
ret
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
print_hex3:
PUSH ACC
SWAP A
ANL A,#0FH
ADD A,#HEXstring3-mvcoff3a
MOVC A,@A+PC
mvcoff3a:
ACALL char_from_Acc
POP ACC
ANL A,#0FH
ADD A,#HEXstring3-mvcoff3b
MOVC A,@A+PC
mvcoff3b:
AJMP char_from_Acc
HEXstring3:
DB '0123456789ABCDEF' ;'standard' hex string
Char_from_ACC: push acc
acall lcd_busy
pop acc ;routine to output result to LCD
mov R1, #(lcd_wr AND 255) ;Load R1 with wr_data address
movx @R1, a
ret
mesg1: db "DVM Prog ",0
mesg2: db "Voltage = ",0
mesg3: db " ",0
Delay: MOV R0, #05h ;Load R0, R1 with huge number
loop1: MOV R1, #08h ;
loop2:
DJNZ R1, loop2 ;Decrement R1 and jump if not zero to loop2
DJNZ R0, loop1 ;Decrement R0 and jump if not zero to loop1
ret ;return to main prog
div16_16:
CLR C ;Clear carry initially
MOV R4,#00h ;Clear R4 working variable initially
MOV R5,#00h ;CLear R5 working variable initially
MOV B,#00h ;Clear B since B will count the number of left-shifted bits
div1:
INC B ;Increment counter for each left shift
MOV A,R2 ;Move the current divisor low byte into the accumulator
RLC A ;Shift low-byte left, rotate through carry to apply highest bit to high-byte
MOV R2,A ;Save the updated divisor low-byte
MOV A,R3 ;Move the current divisor high byte into the accumulator
RLC A ;Shift high-byte left high, rotating in carry from low-byte
MOV R3,A ;Save the updated divisor high-byte
JNC div1 ;Repeat until carry flag is set from high-byte
div2: ;Shift right the divisor
MOV A,R3 ;Move high-byte of divisor into accumulator
RRC A ;Rotate high-byte of divisor right and into carry
MOV R3,A ;Save updated value of high-byte of divisor
MOV A,R2 ;Move low-byte of divisor into accumulator
RRC A ;Rotate low-byte of divisor right, with carry from high-byte
MOV R2,A ;Save updated value of low-byte of divisor
CLR C ;Clear carry, we don't need it anymore
MOV 07h,R1 ;Make a safe copy of the dividend high-byte
MOV 06h,R0 ;Make a safe copy of the dividend low-byte
MOV A,R0 ;Move low-byte of dividend into accumulator
SUBB A,R2 ;Dividend - shifted divisor = result bit (no factor, only 0 or 1)
MOV R0,A ;Save updated dividend
MOV A,R1 ;Move high-byte of dividend into accumulator
SUBB A,R3 ;Subtract high-byte of divisor (all together 16-bit substraction)
MOV R1,A ;Save updated high-byte back in high-byte of divisor
JNC div3 ;If carry flag is NOT set, result is 1
MOV R1,07h ;Otherwise result is 0, save copy of divisor to undo subtraction
MOV R0,06h
div3:
CPL C ;Invert carry, so it can be directly copied into result
MOV A,R4
RLC A ;Shift carry flag into temporary result
MOV R4,A
MOV A,R5
RLC A
MOV R5,A
DJNZ B,div2 ;Now count backwards and repeat until "B" is zero
MOV R3,05h ;Move result to R3/R2
MOV R2,04h ;Move result to R3/R2
RET
end
底部的大部分是用于执行16位分割的代码,但我无法将其链接到十六进制。我也有问题解决代码的确切工作方式。任何帮助将不胜感激。
答案 0 :(得分:0)
你的价值似乎只有8位还是我错过了什么?我没有看到用于打印所述值的16位除法有多大用处。我会将十个幂存储在一个表中并使用减法,类似于C代码:
void print(unsigned char x)
{
const unsigned char powers[] = { 100, 10, 1 };
int i;
int lz = 1;
for(i = 0; i < 3; i += 1)
{
int digit = 0;
while(x >= powers[i])
{
x -= powers[i];
digit += 1;
}
if (i == 2 || digit != 0 || !lz)
{
putchar('0' + digit);
lz = 0;
}
}
putchar('\n');
}
当然,如果你需要按某个范围进行缩放,你需要进行划分,但到目前为止这个问题只提到了印刷。