PIC16Fxx 中 LCD 显示的数字

A number to LCD display in assembly in PIC16Fxx

我用的是PIC16

我对如何将汇编中的数字 (binary/hex/decimal) 转换为 ASCII 以显示在 LCD 显示器上感到困惑,例如:

我在寄存器中存储了一个号码

数字 = 0x04d2(十进制为 1234)

 0x30 = 0x04
 0x31 = 0xd2 

我如何将它转换为 ASCII,以便 LCD 在显示屏上显示 1234?

不使用除法。

这是一个用 C 语言编写的示例,但只需稍加改动就可以在汇编中完成同样的操作。

static void Console_printNum(
    uint32_t num,
    uint8_t base,
    uint8_t point)
{
    #define CHAR_BUFSIZE 33
    const char* const numchars[] = {"0","1","2","3","4","5","6","7","8","9",
        "A","B","C","D","E","F"};
    const char* buf[CHAR_BUFSIZE];
    const char** pStr = &(buf[CHAR_BUFSIZE-1]);

    do {
        *(--pStr) = numchars[num % base];
        num /= base;
        } while( num != 0 );

    while( pStr < &buf[CHAR_BUFSIZE-1] ) {    //copy the buffer into the queue
        if((&buf[CHAR_BUFSIZE-1] - pStr) == point) {
            Console_printStr(".");                       //print decimal point
        }
        Console_printStr(*pStr++);
    }
}

要将数字转换为 ASCII,您只需添加 0x30

0 十进制 0x30 ASCII
1 个十进制 0x30 ASCII
2 十进制 0x32 ASCII
...

但是当然你必须将你的号码分成一位数。

在 PIC16 汇编程序中,16 位除以 10 就像...

;Input RegA2 as low byte RegA1 as High byte
;Result of division by 10 is stored back to RegA2 and RegA1
;Remainder of division is stored in RegA0
;RegAE is temporary storage
        clrf    RegA0       
        movlw   16
        movwf   RegAE
        lslf    RegA2, f
divI16by_c10_        
        rlf     RegA1, f
        rlf     RegA0, f       
        movlw   10
        subwf   RegA0, f
        btfsc   Carry
        bra     divI16by_c10_OK
        addwfc  RegA0, f
        bcf     Carry
divI16by_c10_OK        
        rlf     RegA2, f
        decfsz  RegAE, f
        bra     divI16by_c10_
        return 

直接复制到C语言...

我就是这样做的。

B_HIGH_BYTE 和 B_LOW_BYTE 是你要转换成 ASCII 的数字,这里的其他一切只是一个临时变量

我手动将数字除以 d'10000'、d'1000'、d'100'、d'10',剩下的就是最后一个 :)

可能不是购买满足我需求的最快方式。谢谢大家的建议。

;====================================SPECIAL DIVISION========================   
SPECIAL_DIVISION
    
    clrf SPECIAL_DIV_COUNTER 
    clrf SPECIAL_DIV_HIGH_BYTE 
    clrf SPECIAL_DIV_LOW_BYTE 

    clrf SPECIAL_DIV_PREV_ANS_HIGH_BYTE 
    clrf SPECIAL_DIV_PREV_ANS_LOW_BYTE 
    
    movf B_HIGH_BYTE, 0
    movwf SPECIAL_DIV_HIGH_BYTE
    
    movf B_LOW_BYTE, 0
    movwf SPECIAL_DIV_LOW_BYTE
    
    
    loop_SD         ;getting 5th digit
 movf SPECIAL_DIV_HIGH_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_HIGH_BYTE 
 
 movf SPECIAL_DIV_LOW_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_LOW_BYTE 
    
 movlw 0x10
 subwf SPECIAL_DIV_LOW_BYTE,1
 btfss STATUS,0
 goto $+2
 goto $+3
 movlw 0x01
 subwf SPECIAL_DIV_HIGH_BYTE,1
 btfss STATUS,0
 goto $+7
 
 movlw 0x27
 subwf SPECIAL_DIV_HIGH_BYTE,1
 btfss STATUS,0
 goto $+3
 incf SPECIAL_DIV_COUNTER
    goto loop_SD
    
    movf SPECIAL_DIV_COUNTER,0
    addlw 0x30
    call display_digit

    clrf SPECIAL_DIV_COUNTER

    movf SPECIAL_DIV_PREV_ANS_HIGH_BYTE,0
    movwf SPECIAL_DIV_HIGH_BYTE

    movf SPECIAL_DIV_PREV_ANS_LOW_BYTE,0
    movwf SPECIAL_DIV_LOW_BYTE

    loop_SD2      ;getting 4th digit
 movf SPECIAL_DIV_HIGH_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_HIGH_BYTE 
 
 movf SPECIAL_DIV_LOW_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_LOW_BYTE 
    
 movlw 0xe8
 subwf SPECIAL_DIV_LOW_BYTE,1
 btfss STATUS,0
 goto $+2
 goto $+3
 movlw 0x01
 subwf SPECIAL_DIV_HIGH_BYTE,1
 btfss STATUS,0
 goto $+7
 
 movlw 0x03
 subwf SPECIAL_DIV_HIGH_BYTE,1
 btfss STATUS,0
 goto $+3
 incf SPECIAL_DIV_COUNTER
    goto loop_SD2
    
    movf SPECIAL_DIV_COUNTER,0
    addlw 0x30
    call display_digit

    clrf SPECIAL_DIV_COUNTER

    movf SPECIAL_DIV_PREV_ANS_HIGH_BYTE,0
    movwf SPECIAL_DIV_HIGH_BYTE

    movf SPECIAL_DIV_PREV_ANS_LOW_BYTE,0
    movwf SPECIAL_DIV_LOW_BYTE
    
    loop_SD3      ;getting 3rd digit
 movf SPECIAL_DIV_HIGH_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_HIGH_BYTE 
 
 movf SPECIAL_DIV_LOW_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_LOW_BYTE 
    
 movlw 0x64
 subwf SPECIAL_DIV_LOW_BYTE,1
 btfss STATUS,0
 goto $+2
 goto $+3
 movlw 0x01
 subwf SPECIAL_DIV_HIGH_BYTE,1
 
 btfss STATUS,0
 goto $+3
 incf SPECIAL_DIV_COUNTER
    goto loop_SD3
    
    movf SPECIAL_DIV_COUNTER,0
    addlw 0x30
    call display_digit

    clrf SPECIAL_DIV_COUNTER

    movf SPECIAL_DIV_PREV_ANS_HIGH_BYTE,0
    movwf SPECIAL_DIV_HIGH_BYTE

    movf SPECIAL_DIV_PREV_ANS_LOW_BYTE,0
    movwf SPECIAL_DIV_LOW_BYTE
    
    loop_SD4      ;getting 2nd digit
 movf SPECIAL_DIV_HIGH_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_HIGH_BYTE 
 
 movf SPECIAL_DIV_LOW_BYTE,0
 movwf SPECIAL_DIV_PREV_ANS_LOW_BYTE 
    
 movlw 0x0a
 subwf SPECIAL_DIV_LOW_BYTE,1
 btfss STATUS,0
 goto $+2
 goto $+3
 movlw 0x01
 subwf SPECIAL_DIV_HIGH_BYTE,1
 
 btfss STATUS,0
 goto $+3
 
 incf SPECIAL_DIV_COUNTER
    goto loop_SD4
    
    movf SPECIAL_DIV_COUNTER,0
    addlw 0x30
    call display_digit

    clrf SPECIAL_DIV_COUNTER

    movf SPECIAL_DIV_PREV_ANS_HIGH_BYTE,0
    movwf SPECIAL_DIV_HIGH_BYTE

    movf SPECIAL_DIV_PREV_ANS_LOW_BYTE,0
    movwf SPECIAL_DIV_LOW_BYTE
    
    
    movf SPECIAL_DIV_LOW_BYTE,0     ;getting 1st digit
    addlw 0x30
    call display_digit
    
  
    
    
    
    
return    

How would i go about to convert it to ASCII so that the LCD would display the 1234 in the display?

without using division.

"without using division" 是棘手的部分。第一步是将 16 位二进制数转换为 BCD 表示法。最好的可用方法有多个名称,最常见的是 "double dabble" 算法。这是 PIC16F 的示例:

;
; See:
;   https://en.wikipedia.org/wiki/Double_dabble
;
BIN2BCD_VAR     UDATA
A_reg:      res     2
D_reg:      res     3
mBits:      res     1

BIN2BCD_CODE    CODE
;
; Function: Bin2BCD
; Input:    A_reg, 16-bit binary
;
; Output:   D_reg, 3 bytes of packed BCD digits
;
Bin2BCD:
    banksel D_reg
    clrf    D_reg+0         ; Clear result
    clrf    D_reg+1
    clrf    D_reg+2
    movlw   D'16'           ; Set bit counter
    movwf   mBits

ConvertBit:
    movlw   H'33'           ; Correct BCD value so that
    addwf   D_reg+0,F       ; subsequent shift yields
    btfsc   D_reg+0,.3      ; correct value.
    andlw   H'F0'
    btfsc   D_reg+0,.7
    andlw   H'0F'
    subwf   D_reg+0,F

    movlw   H'33'
    addwf   D_reg+1,F
    btfsc   D_reg+1,.3
    andlw   H'F0'
    btfsc   D_reg+1,.7
    andlw   H'0F'
    subwf   D_reg+1,F

    rlf     A_reg+0,F       ; Shift out a binary bit ...
    rlf     A_reg+1,F

    rlf     D_reg+0,F       ; ... and into BCD value.
    rlf     D_reg+1,F
    rlf     D_reg+2,F

    decfsz  mBits,F         ; Repeat for all bits
    goto    ConvertBit
    return

下一部分是一次将 BCD 表示转换为 ASCII 字符 4 位。

我将把这个工作留给原发帖者。祝你好运。