;;;;;;; P4 for QwikFlash board ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Generate a jitterfree 10 Hz square wave on CCP1 output using compare mode ; with extension. ; Use 10 MHz crystal and 2.5 MHz internal clock rate. ; ;;;;;;; Program hierarchy ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;Mainline ; Initial ; ;HiPriISR (included just to show structure) ; ;LoPriISR ; CCP1handler ; TMR1handler ; ;;;;;;; Assembler directives ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; list P=PIC18F452, F=INHX32, C=160, N=0, ST=OFF, MM=OFF, R=DEC, X=ON #include P18F452.inc __CONFIG _CONFIG1H, _HS_OSC_1H ;HS oscillator __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_ON_2L & _BORV_42_2L ;Reset __CONFIG _CONFIG2H, _WDT_OFF_2H ;Watchdog timer disabled __CONFIG _CONFIG3H, _CCP2MX_ON_3H ;CCP2 to RC1 (rather than to RB3) __CONFIG _CONFIG4L, _LVP_OFF_4L ;RB5 enabled for I/O errorlevel -311 ;Turn off message when 3-byte variable is loaded HalfPeriod equ 125000 ;Number of 0.4 us clock cycles in 0.05 seconds ;;;;;;; Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cblock 0x000 WREG_TEMP STATUS_TEMP TMR1X ;Eight-bit extension to TMR1 CCPR1X ;Eight-bit extension to CCPR1 DTIMEL ;Half-period value DTIMEH DTIMEX endc ;;;;;;; Macro definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MOVLF macro literal,dest movlw literal movwf dest endm ;;;;;;; Vectors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x0000 ;Reset vector nop goto Mainline org 0x0008 ;High priority interrupt vector goto HiPriISR org 0x0018 ;Low priority interrupt vector goto LoPriISR ;;;;;;; Mainline program ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Mainline rcall Initial ;Initialize everything ;LOOP_ L1 ;ENDLOOP_ bra L1 PL1 ;;;;;;; Initial subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine performs all initializations of variables and registers. Initial MOVLF low HalfPeriod,DTIMEL ;Load DTIME with HalfPeriod MOVLF high HalfPeriod,DTIMEH MOVLF upper HalfPeriod,DTIMEX MOVLF B'11010000',TRISC ;Set I/O for PORTC MOVLF 0x81,T1CON ;Turn on TMR1 MOVLF B'00001000',CCP1CON ;Select compare mode bsf RCON,IPEN ;Enable priority levels bcf IPR1,TMR1IP ;Assign low priority to TMR1 interrupts bcf IPR1,CCP1IP ; and to CCP1 interrupts clrf TMR1X ;Make first 24-bit compare occur quickly MOVLF 2,CCPR1X bsf PIE1,CCP1IE ;Enable CCP1 interrupts bsf PIE1,TMR1IE ;Enable TMR1 interrupts bsf INTCON,GIEL ;Enable low-priority interrupts to CPU bsf INTCON,GIEH ;Enable all interrupts return ;;;;;;; HiPriISR interrupt service routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HiPriISR ;High-priority interrupt service routine ; ; retfie FAST ;Return and restore STATUS, WREG, and BSR ; from shadow registers ;;;;;;; LoPriISR interrupt service routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LoPriISR ;Low-priority interrupt service routine movff STATUS,STATUS_TEMP ;Set aside STATUS and WREG movwf WREG_TEMP ;LOOP_ L2 ;IF_ PIR1,CCP1IF == 1 btfss PIR1,CCP1IF bra L3 rcall CCP1handler ;CONTINUE_ bra L2 ;ENDIF_ L3 ;IF_ PIR1,TMR1IF == 1 btfss PIR1,TMR1IF bra L4 rcall TMR1handler ;CONTINUE_ bra L2 ;ENDIF_ L4 ;BREAK_ bra PL2 ;ENDLOOP_ bra L2 PL2 movf WREG_TEMP,W ;Restore WREG and STATUS movff STATUS_TEMP,STATUS retfie ;Return from interrupt, reenabling GIEL CCP1handler ;IF_ PIR1,TMR1IF == 1 ;If Timer1's overflow flag is set btfss PIR1,TMR1IF bra L5 ;IF_ CCPR1H,7 == 0 ; and compare had occurred after that btfsc CCPR1H,7 bra L6 incf TMR1X,F ; then increment TMR1 extension bcf PIR1,TMR1IF ; and clear flag ;ENDIF_ L6 ;ENDIF_ L5 movf TMR1X,W ;Check whether extensions are equal subwf CCPR1X,W ;IF_ .Z. bnz L7 btg CCP1CON,0 ;Toggle control bit movf DTIMEL,W ;and add half period to CCPR1 addwf CCPR1L,F movf DTIMEH,W addwfc CCPR1H,F movf DTIMEX,W addwfc CCPR1X,F ;ENDIF_ L7 bcf PIR1,CCP1IF ;Clear flag return TMR1handler incf TMR1X,F ;Increment Timer1 extension bcf PIR1,TMR1IF ;Clear flag and return to polling routine return end