Code:
;PIC Microcontoller Basic Math Method ;****************************************************************************** ; ; Filename: QUAD_MATH_TESTS.ASM ; Function: Math routines using PIC16F87 ; Created: 29-Jul-2009 ; Author: Brian Beard ; Company: Lucid Technologies ; ;****************************************************************************** ; list p=16F87 ;list directive to define processor #include <p16F87.inc> ;processor specific variable definitions errorlevel -302 ;suppress message 302 from list file ; ;Program Configuration Register 1 __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_CLKOUT ; ;Program Configuration Register 2 __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF ; ;****************************************************************************** ;VARIABLE DEFINITIONS ORG 0x020 ; Bank 0 = 000:07F ACa3 RES 1 ; 32-bit Accumulator a, lsb+3, ms-byte ACa2 RES 1 ; 32-bit Accumulator a, lsb+2 ACa1 RES 1 ; 32-bit Accumulator a, lsb+1 ACa0 RES 1 ; 32-bit Accumulator a, ls-byte ; ACb3 RES 1 ; 32-bit Accumulator b, lsb+3, ms-byte ACb2 RES 1 ; 32-bit Accumulator b, lsb+2 ACb1 RES 1 ; 32-bit Accumulator b, lsb+1 ACb0 RES 1 ; 32-bit Accumulator b, ls-byte ; BCD9 RES 1 ; 10^9, billions BCD8 RES 1 ; 10^8 BCD7 RES 1 ; 10^7 BCD6 RES 1 ; 10^6, millions BCD5 RES 1 ; 10^5 BCD4 RES 1 ; 10^4 BCD3 RES 1 ; 10^3, thousands BCD2 RES 1 ; 10^2 BCD1 RES 1 ; 10^1 BCD0 RES 1 ; 10^0 ; bitcnt RES 1 ; bit count digcnt RES 1 ; digit count c_hold RES 1 ; Carry bit hold ; ORG 0x070 ; 0x70h to 0x7Fh is available in all banks w_temp res 1 ; variable used for context saving status_temp res 1 ; variable used for context saving pclath_temp res 1 ; variable used for context saving ; ;****************************************************************************** ;***** Start of program memory, RESET and INTerrupt vectors. ;****************************************************************************** ; ORG 0x000 ; processor reset vector nop ; required for ICD clrf PCLATH ; ensure page bits are cleared goto MAIN ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf PCLATH,W ; move pclath register into W register movwf pclath_temp ; save off contents of PCLATH register ; ; isr code can go here or be located as a call subroutine elsewhere ; movf pclath_temp,W ; retrieve copy of PCLATH register movwf PCLATH ; restore pre-isr PCLATH register contents movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f ; swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt ; ;****************************************************************************** ;***** Subroutines. ;****************************************************************************** ; ; Quadruple Precision (32-bit) Addition & Subtraction, adapted from AN526. ; ACa? and ACb? are each four-byte (32-bit) binary accumulators. ; ACa3 and ACb3 are the MS-Bytes, ACa0 and ACb0 are the LS-Bytes. ; Addition (Q_add): (ACb)+(ACa) --> (ACb), (ACa) is unchanged ; Subtraction (Q_sub): (ACb)-(ACa) --> (ACb), (ACa) is negated ; Q_sub call neg_ACa ;First negate ACa, then add Q_add movf ACa0,w addwf ACb0,f ;Add lsb btfss STATUS,C ;Test for carry goto q_2 ; go if no carry incf ACb1,f ;Add carry to lsb+1 btfss STATUS,Z ;Test for carry ripple (FF --> 00) goto q_2 ; and go if no carry incf ACb2,f ;Add carry to lsb+2 btfsc STATUS,Z ;Test for carry ripple incf ACb3,f ; add carry to lsb+3, msb q_2 movf ACa1,w addwf ACb1,f ;Add lsb+1 btfss STATUS,C ;Test for carry goto q_4 ; go if no carry incf ACb2,f ;Add carry to lsb+2 btfsc STATUS,Z ;Test for carry ripple incf ACb3,f ; add carry to lsb+3, msb q_4 movf ACa2,w addwf ACb2,f ;Add lsb+2 btfsc STATUS,C ;Test for carry incf ACb3,f ; add carry to lsb+3, msb movf ACa3,w addwf ACb3,f ;Add msb retlw 0 ; neg_ACa comf ACa0,f ; complement (ACa) comf ACa1,f comf ACa2,f comf ACa3,f incf ACa0,f ; add one btfss STATUS,Z retlw 0 incf ACa1,f btfss STATUS,Z retlw 0 incf ACa2,f btfss STATUS,Z retlw 0 incf ACa3,f retlw 0 ; ;============================================================================ ; Quadruple Precision (32-bit) unsigned Binary to BCD conversion ; BCD9 to BCD0 comprise one ten digit unpacked Binary-Coded-Decimal number. ; The upper nibble of each digit is zero (00008421). BCD9 is the MS-Digit. ; ACb3 to ACb0 comprise a four-byte (32-bit) binary accumulator. ; ACb3 is the MS-Byte. ; The 32-bit binary number in ACb in converted to a ten digit BCD number. ; Q_b2bcd clrf BCD9 ;Clear all bcd digits clrf BCD8 clrf BCD7 clrf BCD6 clrf BCD5 clrf BCD4 clrf BCD3 clrf BCD2 clrf BCD1 clrf BCD0 movlw D'32' ;Outer loop movwf bitcnt ; bit counter b2bcd1 rlf ACb0,f ;Shift 32-bit accumulator rlf ACb1,f ; left to rlf ACb2,f ; put ms-bit rlf ACb3,f ; into Carry movlw BCD0 ;Point to address of least movwf FSR ; significant bcd digit movlw D'10' ;Inner loop movwf digcnt ; digit counter b2bcd2 rlf INDF,f ;Shift Carry into bcd digit movlw D'10' ;Subtract ten from digit then subwf INDF,w ; check and adjust for decimal overflow btfsc STATUS,C ;If Carry = 1 (result >= 0) movwf INDF ; adjust for decimal overflow decf FSR,f ;Point to next bcd digit decfsz digcnt,f ;Decrement digit counter goto b2bcd2 ; - go if digcnt > 0 decfsz bitcnt,f ;Decrement bit counter goto b2bcd1 ; - go if bitcnt > 0 retlw 0 ; ;============================================================================ ; Quadruple Precision (32-bit) unsigned BCD to Binary conversion. ; BCD9 to BCD0 comprise one ten digit unpacked Binary-Coded-Decimal number. ; The upper nibble of each digit is zero (00008421). BCD9 is the MS-Digit. ; ACb3 to ACb0 comprise a four-byte (32-bit) binary accumulator. ; ACb3 is the MS-Byte. ; The 10-digit BCD number is converted to a 32-bit binary number in ACb. ; Q_bcd2b movlw D'32' ;Outer loop movwf bitcnt ; bit counter bcd2b1 movlw BCD9 ;Set pointer for movwf FSR ; most significant digit movlw D'10' ;Inner loop movwf digcnt ; digit counter movlw 0x05 ;Weight of next MS-Digit's carry bit clrf c_hold ;0 --> carry_hold bcd2b2 bcf STATUS,0 ;Clear Carry bit rrf INDF,f ;Right shift 0 into bcd digit rlf c_hold,f ;Carry --> c_hold,0 btfsc c_hold,1 ;Add five if carry from previous rotate is addwf INDF,f ; set, else no change incf FSR,f ;Advance digit pointer decfsz digcnt,f ;Decrement digit counter, goto bcd2b2 ; repeat if > 0 rrf c_hold,f ;Last carry from digit rotate --> C rrf ACb3,f ;Ripple Carry bits rrf ACb2,f ; from MSB to rrf ACb1,f ; LSB of rrf ACb0,f ; 32-bit binary accumulator decfsz bitcnt,f ;Decrement bit counter, goto bcd2b1 ; repeat if > 0 retlw 0 ; ;******************************************************************* ; Test Program ;******************************************************************* ; Load constant values for testing ; load1 movlw 0x10 movwf ACa3 movlw 0x00 ; loads ACa = 10 00 00 00 movwf ACa2 movlw 0x00 movwf ACa1 movlw 0x00 movwf ACa0 movlw 0x32 movwf ACb3 movlw 0xFF ; loads ACb = 32 FF 7F DE movwf ACb2 movlw 0x7F movwf ACb1 movlw 0xDE movwf ACb0 retlw 0 load2 movlw 0x00 movwf ACa3 movlw 0x01 ; loads ACa = 00 01 FF AF movwf ACa2 movlw 0xFF movwf ACa1 movlw 0xAF movwf ACa0 movlw 0x00 movwf ACb3 movlw 0x00 ; loads ACb = 00 00 CF E7 movwf ACb2 movlw 0xCF movwf ACb1 movlw 0xE7 movwf ACb0 retlw 0 load3 movlw 0x00 movwf ACa3 movlw 0x00 ; loads ACa = 00 00 00 01 movwf ACa2 movlw 0x00 movwf ACa1 movlw 0x01 movwf ACa0 movlw 0x0F movwf ACb3 movlw 0xFF ; loads ACb = 0F FF FF FF movwf ACb2 movlw 0xFF movwf ACb1 movlw 0xFF movwf ACb0 retlw 0 ; MAIN nop clrf STATUS ; Do initialization, select bank 0 registers page0 ; select program memory page 0 ; call load1 ; a=10 00 00 00, b=32 FF 7F DE call Q_add ; Answer = 42 FF 7F DE call Q_b2bcd ; Answer = 1,124,040,670 call Q_bcd2b ; Answer = 42 FF 7F DE ; self1 call load1 ; a=10 00 00 00, b=32 FF 7F DE call Q_sub ; Neg = F0 00 00 00, Answer = 22 FF 7F DE call Q_b2bcd ; Answer = 0,587,169,758 call Q_bcd2b ; Answer = 22 FF 7F DE ; self2 call load2 ; a=00 01 FF AF, b=00 00 CF E7 call Q_add ; Answer = 00 02 CF 96 call Q_b2bcd ; Answer = 0,000,184,214 call Q_bcd2b ; Answer = 00 02 CF 96 ; self3 call load2 ; a=00 01 FF AF, b=00 00 CF E7 call Q_sub ; Neg = FF FE 00 51, Answer = FF FE D0 38 call Q_b2bcd ; Answer = 4,294,889,528 call Q_bcd2b ; Answer = FF FE D0 38 ; self4 call load3 ;a=00 00 00 01, b=0F FF FF FF call Q_add ; Answer = 10 00 00 00 call Q_b2bcd ; Answer = 0,268,435,456 call Q_bcd2b ; Answer = 10 00 00 00 ; self5 call load3 ;a=00 00 00 01, b=0F FF FF FF call Q_sub ; Neg = FF FF FF FF, Answer = 0F FF FF FE call Q_b2bcd ; Answer = 0,268,435,454 call Q_bcd2b ; Answer = 0F FF FF FE ; self99 NOP ;============================================================================ end
Questions:
Hi,
I have tested the routine BCD to 32 Bits binary.
The software work well and the result binary good untill
4289999999 after this the result is bad.
Could you confirm ? PIC16F628 using
John
Comments: