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
Hi John, I did not do an exhaustive
test of numbers > 4,289,999,999 but I did test a broad selection of random
numbers in that range. I reassembled the code for both *F87 and *F628 processors.
In both cases the MPLAB simulator showed correct operation.
Brian +
Comments:
file: /Techref/member/BB-LTL-/index.htm, 12KB, , updated: 2014/4/9 15:37, local time: 2024/11/22 19:16,
owner: BB-LTL-,
18.222.20.250:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://ecomorder.com/Techref/member/BB-LTL-/index.htm"> Member Homepage for BB-LTL-</A> |
Did you find what you needed? |