Номер на ЖК-дисплей в сборе в PIC16Fxx - PullRequest
0 голосов
/ 08 октября 2018

Я использую PIC16.

Я застрял на том, как преобразовать число (двоичное / шестнадцатеричное / десятичное) в сборке в ASCII для отображения на ЖК-дисплее, например:

У меня есть номер, который хранится здесь в регистре

число = 0x04d2 (1234 в десятичном виде)

 0x30 = 0x04
 0x31 = 0xd2 

Как мне преобразовать его в ASCII, чтобы на ЖК-дисплее отображалось 1234на дисплее?

без использования деления.

Ответы [ 5 ]

0 голосов
/ 11 октября 2018

Как мне преобразовать его в ASCII, чтобы на ЖК-дисплее отображалось 1234?

без использования деления.

"без"Использование деления "является сложной частью.Первым шагом является преобразование 16-разрядного двоичного числа в представление BCD.Наилучший доступный метод известен под несколькими именами, наиболее распространенным является алгоритм «двойного пикирования».Это пример для 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 в 4-битные символы ASCII.

Я оставлю эту работу оригиналуПлакат.Удачи.

0 голосов
/ 10 октября 2018

Вот как я это сделал.

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    
0 голосов
/ 09 октября 2018

Чтобы преобразовать число в ASCII, вам просто нужно было добавить 0x30.

0 десятичный 0x30 ASCII
1 десятичный 0x30 ASCII
2 десятичный 0x32 ASCII
...

Но, конечно, вам пришлось разделить свой номер на однозначные цифры.

0 голосов
/ 09 октября 2018

В 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 ...

0 голосов
/ 08 октября 2018

Вот пример на 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++);
    }
}
...