Muy buenas family. Por favor no quiero que lo lean todo, solo un paseo por encima.
1- Yo programo en CC5, nunca he hecho nada en asm para pics, por lo que no tengo ni la menor idea de como compilar este codigo, o sea, con que programa.
2- El otro lio, y el mas grave, es que este codigo esta escrito para un PIC16F628, y necesito imperiosamente modificarlo para un PIC16F877, debe poderse hacer porque el 16f628 no tiene nada que no tenga el 16f877.
Yo tengo el .hex del codigo que pondre a continuacion, cuando lo puse en proteus con el PIC16F628 como es logico funciona, pero cuando lo pongo con el PIC16F877, da errores de acceso a memoria que no existe, se pude modificar?, es solo cambiar las referencias distintas a los pines, ayuda por favor. Gracias
1- Yo programo en CC5, nunca he hecho nada en asm para pics, por lo que no tengo ni la menor idea de como compilar este codigo, o sea, con que programa.
2- El otro lio, y el mas grave, es que este codigo esta escrito para un PIC16F628, y necesito imperiosamente modificarlo para un PIC16F877, debe poderse hacer porque el 16f628 no tiene nada que no tenga el 16f877.
Yo tengo el .hex del codigo que pondre a continuacion, cuando lo puse en proteus con el PIC16F628 como es logico funciona, pero cuando lo pongo con el PIC16F877, da errores de acceso a memoria que no existe, se pude modificar?, es solo cambiar las referencias distintas a los pines, ayuda por favor. Gracias
Código:
---------------------------------------------------------------------------------------------------------------
;CAPMET737.ASM 21AUG03 - COPYRIGHT JOHN BECKER - EPE IND/CAP/FREQ METER
;PIC16F628, 3.2768MHz, WDT OFF, POR ON, XTAL XS
;Config register bits
; CP1 CP0 CP1 CP0 NIL CPD LVP BOR MCL OS2 POR WDT OS1 OS0
; 1 1 1 1 1 1 0 0 1 0 0 0 0 1
;N.B. Logic 1/0 do NOT necessarily mean that the function is On/Off
;respectively - refer to PIC '627/8 data sheet
#DEFINE BANK0 BCF $03,5
#DEFINE BANK1 BSF $03,5
List P = PIC16F628, R=DEC;
__CONFIG h'3F21'
include P16F628.inc
CBLOCK
REGA0 ;lsb
REGA1
REGA2
REGA3 ;msb
REGB0 ;lsb
REGB1
REGB2
REGB3 ;msb
REGC0 ;lsb
REGC1
REGC2
REGC3 ;msb
DSIGN ;Digit Sign. 0=positive,FF(or non zero)=negative
DIGIT1 ;MSD
DIGIT2
DIGIT3
DIGIT4
DIGIT5 ;Decimal digits
DIGIT6
DIGIT7
DIGIT8
DIGIT9
DIGIT10 ;LSD
MTEMP
MCOUNT
DCOUNT
LOOP
LOOPA
RSLINE
STORE
SLOWIT
POINT
TIMEMSB
OVERFLOW
STORE2
LARGE
NANO
CAPREF3
CAPREF2
CAPREF1
CAPREF0
INDREF3
INDREF2
INDREF1
INDREF0
TIMEOUT
SWITCH
ZERO
INDCORRECT
CAPCORRECT
CORRECTLOC
ENDC
PROMVAL EQU $70 ; accessed via both BANKS
; locations up to $7F are available
; **************
.ORG 0
goto GIEOFF
.ORG 4 ; Interrupt vector address
goto GIEOFF
.ORG 5 ; Start of program memory
GIEOFF: BCF INTCON,GIE ; turn off global interrupts
BTFSC INTCON,GIE
goto GIEOFF
goto START
TABLCD: addwf PCL,F ;LCD initialisation table
retlw %00110011 ;initialise lcd - first byte
retlw %00110011 ;2nd byte (repeat of first)
retlw %00110010 ;set for 4-bit operation
retlw %00101100 ;set for 2 lines
retlw %00000110 ;set entry mode to increment each address
retlw %00001100 ;set display on, cursor off, blink off
retlw %00000001 ;clear display
retlw %00000010 ;return home, cursor & RAM to zero
;end inititalisation table
TITLE: addwf PCL,F
retlw ' '
retlw 'E'
retlw 'P'
retlw 'E'
retlw ' '
retlw 'L'
retlw 'C'
retlw 'F'
retlw ' '
retlw 'M'
retlw 'E'
retlw 'T'
retlw 'E'
retlw 'R'
retlw ' '
retlw ' '
retlw ' '
TITLEB: addwf PCL,F
retlw ' '
retlw 'W'
retlw 'A'
retlw 'I'
retlw 'T'
retlw 'I'
retlw 'N'
retlw 'G'
retlw ' '
retlw 'T'
retlw 'I'
retlw 'M'
retlw 'I'
retlw 'N'
retlw 'G'
retlw ' '
OVERFLOWED: addwf PCL,F
retlw 'O'
retlw 'V'
retlw 'E'
retlw 'R'
retlw 'F'
retlw 'L'
retlw 'O'
retlw 'W'
CALIB: addwf PCL,F
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw 'N'
retlw 'U'
retlw 'L'
retlw 'L'
retlw 'E'
retlw 'D'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
TIMEDOUT: addwf PCL,F
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw 'T'
retlw 'I'
retlw 'M'
retlw 'E'
retlw ' '
retlw 'O'
retlw 'U'
retlw 'T'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
CAPTIME: addwf PCL,F
retlw ' '
retlw ' '
retlw ' '
retlw 'C'
retlw 'A'
retlw 'P'
retlw 'A'
retlw 'C'
retlw 'I'
retlw 'T'
retlw 'O'
retlw 'R'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
INDTIME: addwf PCL,F
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw 'I'
retlw 'N'
retlw 'D'
retlw 'U'
retlw 'C'
retlw 'T'
retlw 'O'
retlw 'R'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
CORRECTMSG: addwf PCL,F
retlw ' '
retlw 'C'
retlw 'O'
retlw 'R'
retlw 'R'
retlw 'E'
retlw 'C'
retlw 'T'
retlw 'I'
retlw 'O'
retlw 'N'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
;*******************
START: clrf PORTA
clrf PORTB
movlw $07
movwf CMCON
BANK1
movlw %11000000
movwf TRISB
movlw %00011100 ; RA0,RA1 as output
movwf TRISA
movlw %10000110 ; timer 1:128, pull-ups off
movwf OPTION_REG
BANK0
clrf INTCON
call PAUSIT
call LCDSET
call PAUSIT
movlw %00000000 ; T1 ext osc disable (bit3=0), T1 stopped (bit0=0), internal clock (bit1=0), bit2 dont care
movwf T1CON
btfsc PORTA,2 ; is S3 (RA2) pressed?
goto CORRECTIT
call LCD1
bsf RSLINE,4
clrf LOOP
TITLE2: movf LOOP,W
call TITLE
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TITLE2
clrf INTCON
clrf POINT
clrf CAPREF3
clrf CAPREF2
clrf CAPREF1
clrf CAPREF0
clrf INDREF3
clrf INDREF2
clrf INDREF1
clrf INDREF0
movlw 0
call PRMGET
movwf INDCORRECT
movlw 1
call PRMGET
movwf CAPCORRECT
call PAUSIT ; delay
call PAUSIT ; delay
clrf INTCON
movlw 255
movwf SWITCH
;****************** START OF MAIN
MAIN: clrf TIMEOUT
movf PORTA,W
andlw %00010000
xorwf SWITCH,W
btfsc STATUS,Z
goto MAIN2
movf PORTA,W
andlw %00010000
movwf SWITCH
call LCD21
bsf RSLINE,4
clrf LOOP
TITLE3: movf LOOP,W
call TITLEB
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TITLE3
call LCD1
bsf RSLINE,4
clrf LOOP
btfsc PORTA,4
goto TIMOUT4
MAIN3: movf LOOP,W
call CAPTIME
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto MAIN3
goto MAIN2
MAIN4: movf LOOP,W
call INDTIME
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TIMOUT4
goto MAIN4
MAIN2: btfsc SWITCH,4
goto INDUCT
goto CAPACITOR
; *****************
; QBASIC ROUTINE ILLUSTRATING INDUCTANCE FORMULA
;CLS
;DEFDBL A-Z
;PRINT "Formula: L = ((1000000000 / (2 * PI * F) ^ 2)) / C"
;PRINT
;PI = 22 / 7
;F = 389305: PRINT "Frequency = "; F
;C = 200: C = (C * C) / (C + C): PRINT "Capacitance = "; C
;Process:
;L = F * 44: PRINT L
;L = INT(L / 7): PRINT L
;L = INT(1000000000 / L): PRINT L
;L = L * L: PRINT L
;L = INT(L / 10):
;L = L / 1000
;PRINT "Inductance = "; L; "uH"
; **************
INDUCT: movlw %00000001 ; set for correct osc
movwf PORTA
call INDTIMER ; get osc frequency
call COPY_TIME_REGA
clrf POINT
clrf LARGE
movf TMR1H,W
andlw %11000000
iorwf TIMEMSB,W ; is timing value less than 16384?
btfsc STATUS,Z
call LARGEVALUE ; yes
btfsc TIMEOUT,0
goto TIMEEND
call LCD1 ; set address
bsf RSLINE,4 ; set RS for data send
call BIN2DEC
call SHOWITALL
movlw 'H'
call LCDOUT
movlw 'z'
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
call COPY_TIME_REGA
movlw 44 ; multiply freq x 44 (22 x 2) (2 x PI = 44/7)
call MULTIPLYSMALL ; REGA * 44 -> REGA
movlw 7 ; divide by 7
call DIVIDESMALL ; REGA / 7 -> REGA
call COPY_REGA_REGB ; copy answer into REGB
call DIVIDEBILLION ; 1,000,000,000 / REGB -> REGA
call COPY_REGA_REGB ; copy answer into REGB
call MULTIPLY ; REGA * REGB -> REGA (squaring REGA)
movf STATUS,W
andlw 1
movwf OVERFLOW
movlw '2'
movf OVERFLOW,F
btfss STATUS,Z
goto SHOWOVERFLOW
movlw 10 ; divide by 10
call DIVIDESMALL ; REGA / 100 -> REGA
movf STATUS,W
andlw 1
movwf OVERFLOW
movlw 'C'
movf OVERFLOW,F
btfss STATUS,Z
goto SHOWOVERFLOW
movf INDCORRECT,W ; multiply by correction factor
call MULTIPLYSMALL ; REGA * REGB -> REGA
movf STATUS,W
andlw 1
movwf OVERFLOW
movlw 'A'
movf OVERFLOW,F
btfss STATUS,Z
goto SHOWOVERFLOW
movlw 100 ; divide by 100
call DIVIDESMALL ; REGA / 100 -> REGA
movf STATUS,W
andlw 1
movwf OVERFLOW
movlw 'B'
movf OVERFLOW,F
btfss STATUS,Z
goto SHOWOVERFLOW
btfsc PORTA,2 ; is S3 (RA2) pressed?
call CALIBIND
movf LARGE,F
btfsc STATUS,Z
call SUBTRACTINDREF
movlw 4
movwf POINT
call LCD21 ; set address
bsf RSLINE,4 ; set RS for data send
call BIN2DEC ; converts binary in REGA to decimal in DIGIT
movf LARGE,F
btfsc STATUS,Z
call CHECKMILLI
call SHOWITALL
movf LARGE,F
btfss STATUS,Z
goto IND2
movlw 'u'
movf NANO,F
btfss STATUS,Z
movlw 'm'
call LCDOUT
IND2: movlw 'H'
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
goto MAIN
; ***************
CAPACITOR: movlw %00000010 ; set for correct osc
movwf PORTA
clrf TIMEMSB
call INDTIMER
call COPY_TIME_REGA
clrf POINT
clrf LARGE
movf TMR1H,W
andlw %11111110
iorwf TIMEMSB,W ; is timing value less than 512?
btfsc STATUS,Z
call LARGEVALUE ; yes
btfsc ZERO,0
goto TIMEEND
call LCD1 ; set address
bsf RSLINE,4 ; set RS for data send
call BIN2DEC
call SHOWITALL
movlw 'H'
call LCDOUT
movlw 'z'
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
call COPY_TIME_REGA
movlw 22 ; multiply freq x PI (R = 1k) (ignoring 3 zeros)
call MULTIPLYSMALL
movlw 7
call DIVIDESMALL
call COPY_REGA_REGB ; copy answer into REGB
call DIVIDEBILLION ; REGA / REGB -> REGA
movf CAPCORRECT,W ; multiply by correction factor
call MULTIPLYSMALL ; REGA / REGB -> REGA
movlw 100 ; divide by 100
call DIVIDESMALL ; REGA / 100 -> REGA
btfsc PORTA,2 ; is S3 (RA2) pressed?
call CALIBCAP
movf LARGE,F
btfsc STATUS,Z
call SUBTRACTCAPREF
call LCD21 ; set address
bsf RSLINE,4 ; set RS for data send
call BIN2DEC
call CHECKNANO
call SHOWITALL
movlw 'u'
movf LARGE,F
btfss STATUS,Z
goto CAP2
movlw 'n'
movf NANO,F
btfsc STATUS,Z
movlw 'p'
CAP2: call LCDOUT
movlw 'F'
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
call LCDOUT
movlw ' '
goto MAIN
; **************
LARGEVALUE:
clrf TIMEOUT
incf LARGE,F
movlw %00000000 ; stop timer 1
movwf T1CON
clrf TMR1L ; reset timer 1
clrf TMR1H
bcf PIR1,0 ; clear timer rollover flag
movf PORTB,W ; get current status of RB6
andlw %01000000
movwf STORE ; store it
clrf SLOWIT
bsf T1CON,0 ; start timer 1
WAITB1:
movf PORTA,W
andlw %00010000
xorwf SWITCH,W
btfss STATUS,Z
return
WAITB2: movf PORTB,W ; get current status of RB6
andlw %01000000
movwf STORE2 ; temp store it
xorwf STORE,W ; compare with prev val of RB6
btfsc STATUS,Z ; is it equal?
goto WAITB1 ; yes
movf STORE2,W ; no, different, so store val
movwf STORE
call OSCILLATE ; get timing between two changes of RB6 (1 full cycle)
btfsc TIMEOUT,0
return
call COPY_TIME_REGA
movlw 122
call MULTIPLYSMALL ; REGA * 122 -> REGA multiply freq x 122 to get time re 3.2768MHz xtal (1000000/819200 =1.22)
movlw 100 ; divide by 100
call DIVIDESMALL ; REGA / 100 -> REGA
call COPY_REGA_REGB ; copy answer into REGB
call DIVIDEBILLION ; 1,000,000,000 / REGB -> REGA
movf REGA0,W ; copy answer back into TIMER
movwf TMR1L
movf REGA1,W
movwf TMR1H
movf REGA2,W
movwf TIMEMSB
movlw 4
movwf POINT
return
; ***********
CHECKNANO: clrf NANO
movf DIGIT1,W
iorwf DIGIT2,W
iorwf DIGIT3,W
iorwf DIGIT4,W
iorwf DIGIT5,W
iorwf DIGIT6,W
andlw %00001111
btfsc STATUS,Z
return
bsf NANO,0
movlw 4
movwf POINT
return
; ***********
CHECKMILLI: clrf NANO
movf DIGIT1,W
iorwf DIGIT2,W
iorwf DIGIT3,W
iorwf DIGIT4,W
iorwf DIGIT5,W
andlw %00001111
btfsc STATUS,Z
return
bsf NANO,0
movlw 7
movwf POINT
return
; *************
CALIBCAP: movf REGA0,W
movwf CAPREF0
movf REGA1,W
movwf CAPREF1
movf REGA2,W
movwf CAPREF2
movf REGA3,W
movwf CAPREF3
call SHOWCALIB
return
CALIBIND: movf REGA0,W
movwf INDREF0
movf REGA1,W
movwf INDREF1
movf REGA2,W
movwf INDREF2
movf REGA3,W
movwf INDREF3
call SHOWCALIB
return
; **************
SHOWCALIB: call LCD1
bsf RSLINE,4
clrf LOOP
CALIB2: movf LOOP,W
call CALIB
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto CALIB2
call PAUSIT
return
; **************
SUBTRACTCAPREF: ; subtract ref from current val
; REGA - REGB -> REGA ;Return carry set if overflow
movf CAPREF3,W
movwf REGB3
movf CAPREF2,W
movwf REGB2
movf CAPREF1,W
movwf REGB1
movf CAPREF0,W
movwf REGB0
call SUBTRACT
movf STATUS,W
andlw 1
movwf OVERFLOW
return
SUBTRACTINDREF: ; subtract ref from current val
; REGA - REGB -> REGA ;Return carry set if overflow
movf INDREF3,W
movwf REGB3
movf INDREF2,W
movwf REGB2
movf INDREF1,W
movwf REGB1
movf INDREF0,W
movwf REGB0
call SUBTRACT
movf STATUS,W
andlw 1
movwf OVERFLOW
return
; **************
INDTIMER: movlw %00000110 ; T1 ext osc sync off (bit 2) timer1 off
movwf T1CON ; uses T1 ext clock input via RB6 and measures
; number of clock pulses during 25 cycles of TMR0
BANK1
movlw %10000110 ; timer 1:128, pullups off
movwf OPTION_REG
BANK0
clrf TMR1L ; reset timer 1
clrf TMR1H
clrf TIMEMSB
bcf PIR1,0 ; clr timer rollover flag
movlw %00000111 ; T1 ext osc sync off (bit 2) timer1 on
movwf T1CON
movlw 25
movwf SLOWIT
clrf TMR0
bcf INTCON,2
TIMEIT: btfss PIR1,0 ; has timer 1 overflowed?
goto TIMIT2
bcf PIR1,0
incf TIMEMSB,F
TIMIT2: btfss INTCON,2 ; has timer 0 overflowed?
goto TIMEIT
bcf INTCON,2
decfsz SLOWIT,F
goto TIMEIT
movlw %00000000
movwf T1CON
return
; ****************
OSCILLATE: clrf ZERO
clrf T1CON
clrf TMR1H
clrf TMR1L
bcf PIR1,0
bsf T1CON,0 ; start timer 1
clrf TIMEMSB
bsf T1CON,0 ; start timer 1
OSCA1:
movf PORTA,W
andlw %00010000
xorwf SWITCH,W
btfss STATUS,Z
return
btfsc PIR1,0 ; has timer 1 overflowed?
call INCMSB ; yes
OSCA1A: movf PORTB,W ; is RB6 same as before?
andlw %01000000
movwf STORE2
xorwf STORE,W
btfsc STATUS,Z
goto OSCA1 ; yes
movf STORE2,W ; no, so continue for next cycle
movwf STORE
OSCA2:
movf PORTA,W
andlw %00010000
xorwf SWITCH,W
btfss STATUS,Z
return
btfsc PIR1,0 ; has timer 1 overflowed?
call INCMSB ; yes
OSCA2A: movf PORTB,W ; is RB6 same as before?
andlw %01000000
movwf STORE2
xorwf STORE,W
btfsc STATUS,Z
goto OSCA2 ; yes
movlw %00000000 ; no, stop timer 1
movwf T1CON
return
INCMSB: incf TIMEMSB,F
decf SLOWIT,F
bcf PIR1,0
clrf TMR1H
clrf TMR1L
movf SLOWIT,F
btfsc STATUS,Z
bsf ZERO,0
return
;******** LCD ROUTINES **********
LCD1: movlw %10000000
goto LCDLIN
LCD5: movlw %10000101
goto LCDLIN
LCD6: movlw %10000110
goto LCDLIN
LCD8: movlw %10001000
goto LCDLIN
LCD9: movlw %10001001
goto LCDLIN
LCD13: movlw %10001101
goto LCDLIN
LCD15: movlw %10001111
goto LCDLIN
LCD21: movlw %11000000
goto LCDLIN
LCD25: movlw %11000101
goto LCDLIN
LCD26: movlw %11000110
goto LCDLIN
LCD28: movlw %11001000
LCDLIN: BCF RSLINE,4
LCDOUT: movwf STORE
movlw 50
movwf LOOPA
DELAYIT: decfsz LOOPA,F
goto DELAYIT
call SENDIT
SENDIT: swapf STORE,F
movf STORE,W
andlw 15
iorwf RSLINE,W
movwf PORTB
BSF PORTB,5
nop
nop
BCF PORTB,5
RETURN
; *************
PAUSIT: movlw 25
movwf SLOWIT
bcf INTCON,2
PAUSE: btfss INTCON,2
goto PAUSE
bcf INTCON,2
decfsz SLOWIT,F
goto PAUSE
return
PAUSIT2: clrf TMR0
movlw 10
movwf SLOWIT
bcf INTCON,2
PAUSE2: btfss INTCON,2
goto PAUSE2
bcf INTCON,2
decfsz SLOWIT,F
goto PAUSE2
return
;..............
LCDSET: clrf LOOP ;clr LCD set-up loop
clrf RSLINE ;clear RS line for instruction send
LCDST2: movf LOOP,W ;get table address
call TABLCD ;get set-up instruction
call LCDOUT ;perform it
incf LOOP,F ;inc loop
btfss LOOP,3 ;has last LCD set-up instruction now been done?
goto LCDST2 ;no
return
CLRLINE1: call LCD1 ;set address for line 1 cell 1
bsf RSLINE,4 ;set RS for data send
clrf LOOP ;
CLRL1: movlw ' ' ;clear cell
call LCDOUT ;
incf LOOP,F ;inc loop
btfss LOOP,4 ;has last LCD letter been sent?
goto CLRL1 ;no
return
CLRLINE2: call LCD21
bsf RSLINE,4
movlw 16
movwf LOOP
CL2: movlw ' '
call LCDOUT
decfsz LOOP,F
goto CL2
return
; ***********
SHOWITALL: movlw DIGIT1
movwf FSR
movlw 10
movwf LOOP
SHOW2: movf INDF,W
call LCDOUT
movf LOOP,W
xorwf POINT,W
btfss STATUS,Z
goto SHOW3
movlw '.'
call LCDOUT
SHOW3: incf FSR,F
decfsz LOOP,F
goto SHOW2
return
; ***********
COPY_TIME_REGA:
movf TIMEMSB,W
movwf REGA2
movf TMR1H,W
movwf REGA1
movf TMR1L,W
movwf REGA0
clrf REGA3
return
; *********
MULTIPLYSMALL:
movwf REGB0
clrf REGB1
clrf REGB2
clrf REGB3
call MULTIPLY
movf STATUS,W
andlw 1
movwf OVERFLOW
return
; *************
DIVIDESMALL:
movwf REGB0
clrf REGB1
clrf REGB2
clrf REGB3
call DIVIDE
movf STATUS,W
andlw 1
movwf OVERFLOW
return
; ***********
DIVIDEBILLION:
movlw $3B ; divide 1,000,000,000 ($3B9ACA00) by the answer
movwf REGA3
movlw $9A
movwf REGA2
movlw $CA
movwf REGA1
movlw $00
movwf REGA0
call DIVIDE
movf STATUS,W
andlw 1
movwf OVERFLOW
return
; ***********
COPY_REGA_REGB:
movf REGA0,W
movwf REGB0
movf REGA1,W
movwf REGB1
movf REGA2,W
movwf REGB2
movf REGA3,W
movwf REGB3
return
; *********** PETER HEMSLEY'S 32-BIT MATHS ROUTINES *******
;*** SIGNED MULTIPLY ***
;REGA * REGB -> REGA
;Return carry set if overflow
multiply
clrf MTEMP ;Reset sign flag
call chksgna ;Make REGA positive
skpc
call chksgnb ;Make REGB positive
skpnc
return ;Overflow
call movac ;Move REGA to REGC
call clra ;Clear product
movlw D'31' ;Loop counter
movwf MCOUNT
muloop call slac ;Shift left product and multiplicand
rlf REGC3,w ;Test MSB of multiplicand
skpnc ;If multiplicand bit is a 1 then
call addba ;add multiplier to product
skpc ;Check for overflow
rlf REGA3,w
skpnc
return
decfsz MCOUNT,f ;Next
goto muloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
; *************
;*** SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero
divide clrf MTEMP ;Reset sign flag
movf REGB0,w ;Trap division by zero
iorwf REGB1,w
iorwf REGB2,w
iorwf REGB3,w
sublw 0
skpc
call chksgna ;Make dividend (REGA) positive
skpc
call chksgnb ;Make divisor (REGB) positive
skpnc
return ;Overflow
clrf REGC0 ;Clear remainder
clrf REGC1
clrf REGC2
clrf REGC3
movlw D'32' ;Loop counter
movwf MCOUNT
dvloop call slac ;Shift dividend (REGA) msb into remainder (REGC)
movf REGB3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf REGC3,w
skpz
goto dtstgt
movf REGB2,w
subwf REGC2,w
skpz
goto dtstgt
movf REGB1,w
subwf REGC1,w
skpz
goto dtstgt
movf REGB0,w
subwf REGC0,w
dtstgt skpc ;Carry set if remainder >= divisor
goto dremlt
movf REGB0,w ;Subtract divisor (REGB) from remainder (REGC)
subwf REGC0,f
movf REGB1,w
skpc
incfsz REGB1,w
subwf REGC1,f
movf REGB2,w
skpc
incfsz REGB2,w
subwf REGC2,f
movf REGB3,w
skpc
incfsz REGB3,w
subwf REGC3,f
clrc
bsf REGA0,0 ;Set quotient bit
dremlt decfsz MCOUNT,f ;Next
goto dvloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
;*** SQUARE ROOT ***
;sqrt(REGA) -> REGA
;Return carry set if negative
sqrt rlf REGA3,w ;Trap negative values
skpnc
return
call movac ;Move REGA to REGC
call clrba ;Clear remainder (REGB) and root (REGA)
movlw D'16' ;Loop counter
movwf MCOUNT
sqloop rlf REGC0,f ;Shift two msb's
rlf REGC1,f ;into remainder
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
setc ;Add 1 to root
rlf REGA0,f ;Align root
rlf REGA1,f
rlf REGA2,f
movf REGA2,w ;Test if remdr (REGB) >= root (REGA)
subwf REGB2,w
skpz
goto ststgt
movf REGA1,w
subwf REGB1,w
skpz
goto ststgt
movf REGA0,w
subwf REGB0,w
ststgt skpc ;Carry set if remdr >= root
goto sremlt
movf REGA0,w ;Subtract root (REGA) from remdr (REGB)
subwf REGB0,f
movf REGA1,w
skpc
incfsz REGA1,w
subwf REGB1,f
movf REGA2,w
skpc
incfsz REGA2,w
subwf REGB2,f
bsf REGA0,1 ;Set current root bit
sremlt bcf REGA0,0 ;Clear test bit
decfsz MCOUNT,f ;Next
goto sqloop
clrc
rrf REGA2,f ;Adjust root alignment
rrf REGA1,f
rrf REGA0,f
return
;*** SIGNED BINARY TO DECIMAL ***
;REGA -> DIGITS 1 (MSD) TO 10 (LSD) & DSIGN
;DSIGN = 0 if REGA is positive, FF if negative
;Return carry set if overflow
;Uses FSR register
bin2dec
call clrdig ;Clear all digits
clrf MTEMP ;Reset sign flag
call chksgna ;Make REGA positive
skpnc
goto BLANKIT ;Overflow
movlw D'32' ;Loop counter
movwf MCOUNT
b2dloop rlf REGA0,f ;Shift msb into carry
rlf REGA1,f
rlf REGA2,f
rlf REGA3,f
movlw DIGIT10
movwf FSR ;Pointer to digits
movlw D'10' ;10 digits to do
movwf DCOUNT
adjlp rlf INDF,f ;Shift digit and carry 1 bit left
movlw -D'10'
addwf INDF,w ;Check and adjust for decimal overflow
skpnc
movwf INDF
decf FSR,f ;Next digit
decfsz DCOUNT,f
goto adjlp
decfsz MCOUNT,f ;Next bit
goto b2dloop
btfsc MTEMP,0 ;Check sign
comf DSIGN,f ;Negative
clrc
BLANKIT: movlw 48
iorwf DIGIT1,F
iorwf DIGIT2,F
iorwf DIGIT3,F
iorwf DIGIT4,F
iorwf DIGIT5,F
iorwf DIGIT6,F
iorwf DIGIT7,F
iorwf DIGIT8,F
iorwf DIGIT9,F
iorwf DIGIT10,F
movlw 10 ; blank leading zeros
movwf LOOP
movlw DIGIT1
movwf FSR
BLANK: movf LOOP,W
xorwf POINT,W
btfsc STATUS,Z
return
movf INDF,W
andlw 15
btfss STATUS,Z
return
bcf INDF,4
incf FSR,F
decfsz LOOP,F
goto BLANK
movlw 48
iorwf DIGIT10,F
return
; **************
;Negate REGA
;Used by chksgna, multiply, divide, mod, bin2dec, dec2bin
negatea movf REGA3,w ;Save sign in w
andlw 0x80
comf REGA0,f ;2's complement
comf REGA1,f
comf REGA2,f
comf REGA3,f
incfsz REGA0,f
goto nega1
incfsz REGA1,f
goto nega1
incfsz REGA2,f
goto nega1
incf REGA3,f
nega1
incf MTEMP,f ;flip sign flag
addwf REGA3,w ;Return carry set if -2147483648
return
;Check sign of REGA and convert negative to positive
;Used by multiply, divide, bin2dec
chksgna rlf REGA3,w
skpc
return ;Positive
;Set all digits to 0
;Used by bin2dec
clrdig clrf DSIGN
clrf DIGIT1
clrf DIGIT2
clrf DIGIT3
clrf DIGIT4
clrf DIGIT5
clrf DIGIT6
clrf DIGIT7
clrf DIGIT8
clrf DIGIT9
clrf DIGIT10
return
;Shift left REGA and REGC
;Used by multiply, divide
slac rlf REGA0,f
rlf REGA1,f
rlf REGA2,f
rlf REGA3,f
rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
return
;Check sign of REGB and negative convert to positive
;Used by multiply, divide, mod
chksgnb rlf REGB3,w
skpc
return ;Positive
;Negate REGB
;Used by chksgnb, subtract, multiply, divide, mod
negateb movf REGB3,w ;Save sign in w
andlw 0x80
comf REGB0,f ;2's complement
comf REGB1,f
comf REGB2,f
comf REGB3,f
incfsz REGB0,f
goto negb1
incfsz REGB1,f
goto negb1
incfsz REGB2,f
goto negb1
incf REGB3,f
negb1
incf MTEMP,f ;flip sign flag
addwf REGB3,w ;Return carry set if -2147483648
return
movac movf REGA0,w
movwf REGC0
movf REGA1,w
movwf REGC1
movf REGA2,w
movwf REGC2
movf REGA3,w
movwf REGC3
return
;Clear REGB and REGA
;Used by sqrt
clrba clrf REGB0
clrf REGB1
clrf REGB2
clrf REGB3
;Clear REGA
;Used by multiply, sqrt
clra clrf REGA0
clrf REGA1
clrf REGA2
clrf REGA3
return
;Add REGB to REGA (Unsigned)
;Used by add, multiply,
addba movf REGB0,w ;Add lo byte
addwf REGA0,f
movf REGB1,w ;Add mid-lo byte
skpnc ;No carry_in, so just add
incfsz REGB1,w ;Add carry_in to REGB
addwf REGA1,f ;Add and propagate carry_out
movf REGB2,w ;Add mid-hi byte
skpnc
incfsz REGB2,w
addwf REGA2,f
movf REGB3,w ;Add hi byte
skpnc
incfsz REGB3,w
addwf REGA3,f
return
;*** SIGNED SUBTRACT ***
;REGA - REGB -> REGA
;Return carry set if overflow
subtract
call negateb ;Negate and add
skpnc
return ;Overflow
;*** SIGNED ADD ***
;REGA + REGB -> REGA
;Return carry set if overflow
add movf REGA3,w ;Compare signs
xorwf REGB3,w
movwf MTEMP
call addba ;Add REGB to REGA
clrc ;Check signs
movf REGB3,w ;If signs are same
xorwf REGA3,w ;so must result sign
btfss MTEMP,7 ;else overflow
addlw 0x80
return
; *************
SHOWOVERFLOW: movwf OVERFLOW
call CLRLINE2
call LCD21
bsf RSLINE,4
; movf INDCORRECT,W ; author's test section
; movwf REGA0
; movf LARGE,W
; movwf REGA0
; clrf REGA1
; clrf REGA2
; clrf REGA3
; call BIN2DEC
; call SHOWITALL
clrf LOOP
OVER2: movf LOOP,W
call OVERFLOWED
call LCDOUT
incf LOOP,F
btfss LOOP,3
goto OVER2
movlw ' '
call LCDOUT
movf OVERFLOW,W
call LCDOUT
goto MAIN
; ***********
CHECKZERO:
movf TMR1H,W
iorwf TMR1L,W
iorwf TIMEMSB,W
movf STATUS,Z
andlw $00000100
movwf OVERFLOW
TIMEEND: movlw %00000000 ; stop timer 1
movwf T1CON
clrf TMR1H
clrf TMR1L
clrf TIMEMSB
call LCD21
bsf RSLINE,4
clrf LOOP
TIMOUT2: movf LOOP,W
call TIMEDOUT
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TIMOUT2
call LCD1
bsf RSLINE,4
clrf LOOP
btfsc PORTA,4
goto TIMOUT4
TIMOUT3: movf LOOP,W
call CAPTIME
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TIMOUT3
goto MAIN
TIMOUT4: movf LOOP,W
call INDTIME
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto TIMOUT4
goto MAIN
; ******* WRITE DATA TO EEPROM ROUTINE modified for PIC16F62x devices ********
;according to data sheet page 93 (is the same as for 16F87x devices
; except that PIR2 of '87x has become PIR1 for '62x and page 2/3 not used)
;This routine is entered with W holding
;the eeprom byte address at which data
;is to be stored. The data to be stored
;is held in PROMVAL, which is located in both pages at or above $70
SETPRM:
BANK1
movwf EEADR ;copy W into EEADR to set eeprom address
movf PROMVAL,W ;get data value from PROMVAL and hold in W
movwf EEDATA ;copy W into eeprom data byte register
bsf EECON1,WREN ;enable write flag
MANUAL: movlw $55 ;these lines cause the action required by
movwf EECON2 ;by the eeprom to store the data in EEDATA
movlw $AA ;at the address held by EEADR.
movwf EECON2
bsf EECON1,WR ;set the ``perform write'' flag
BANK0
CHKWRT: btfss PIR1,EEIF ;wait until bit 4 of PIR2 is set
goto CHKWRT
bcf PIR1,EEIF ;clear bit 4 of PIR2
return
;******** READ DATA FROM EEPROM ROUTINE modified for PIC16F62x devices ****
; the data sheet page 93 is wrong! This routine here works!
;This routine is entered with W holding
;the eeprom byte address to be read.
PRMGET: BANK1
movwf EEADR ;copy W into EEADR to set eeprom address
bsf EECON1,RD ;enable read flag
movf EEDATA,W ;read eeprom data now in EEDATA into W
BANK0
return
; ***********
CORRECTIT:
call LCD1
bsf RSLINE,4
btfss PORTA,4
goto CAPCRT
INDCRT: movlw 'I'
call LCDOUT
movlw 'N'
call LCDOUT
movlw 'D'
call LCDOUT
clrf CORRECTLOC
goto CORRECT2
CAPCRT: movlw 'C'
call LCDOUT
movlw 'A'
call LCDOUT
movlw 'P'
call LCDOUT
movlw 1
movwf CORRECTLOC
CORRECT2: clrf LOOP
CORRECT3: movf LOOP,W
call CORRECTMSG
call LCDOUT
incf LOOP,F
btfss LOOP,4
goto CORRECT3
COR3: call SHOWCORRECT
COR4: btfsc PORTA,2 ; is S3 (RA2) still pressed?
goto COR4 ; yes
call PAUSIT
COR5: btfss PORTA,2 ; is S3 (RA2) pressed?
goto COR5 ; no
btfsc PORTA,4
goto COR7
COR6: call INCIT
call SHOWCORRECT
call PAUSIT2
call PAUSIT2
goto COR5
COR7: call DECIT
call SHOWCORRECT
call PAUSIT2
call PAUSIT2
goto COR5
INCIT: movf CORRECTLOC,W
call PRMGET
movwf PROMVAL
addlw 1
movwf PROMVAL
xorlw 200
btfsc STATUS,Z
decf PROMVAL,F
movf CORRECTLOC,W
call SETPRM
return
DECIT: movf CORRECTLOC,W
call PRMGET
movwf PROMVAL
decf PROMVAL,F
btfsc STATUS,Z
incf PROMVAL,F
movf CORRECTLOC,W
call SETPRM
return
; **********
SHOWCORRECT:
movf CORRECTLOC,W
call PRMGET
movwf REGA0
clrf REGA1
clrf REGA2
clrf REGA3
call LCD21
bsf RSLINE,4
call BIN2DEC
movf DIGIT8,W
call LCDOUT
movf DIGIT9,W
call LCDOUT
movf DIGIT10,W
call LCDOUT
return
; **************
.org $2100 ; data eeprom values
DE 100,100,0,0,0,0
END
Última edición por un moderador: