2012-12-11 55 views
0

我必須使用組件在8051上創建一個數字電壓表。我有一個在LCD上以十六進制輸出,但我不能得到它以十進制輸出。數字電壓表爲8051

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  'ABCDEF'  ;'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

你的價值似乎只有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'); 
} 

當然,如果你需要將規模擴大一些範圍,您將需要劃分,但問題至今只提到了印刷。