0

我必须使用组件在 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 位划分的代码,但我无法将其链接到十六进制。我也有问题弄清楚代码是如何工作的。任何帮助将不胜感激。

4

1 回答 1

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');
}

当然,如果你需要按一定范围进行缩放,你将需要除法,但到目前为止的问题只提到了打印。

于 2012-12-11T16:43:34.960 回答