;;;;;;; P1_SA for QwikFlash board ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Use 10 MHz crystal frequency. ; Use Timer0 for ten millisecond looptime. ; Blink "Alive" LED every two and a half seconds. ; Toggle C2 output every ten milliseconds for measuring looptime precisely. ; ;;;;;;; Program hierarchy ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Mainline ; Initial ; BlinkAlive ; LoopTime ; ;;;;;;; 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 ;;;;;;; Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cblock 0x000 ;Beginning of Access RAM TMR0LCOPY ;Copy of sixteen-bit Timer0 used by LoopTime TMR0HCOPY INTCONCOPY ;Copy of INTCON for LoopTime subroutine ALIVECNT ;Counter for blinking "Alive" LED 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 $ ;Trap org 0x0018 ;Low priority interrupt vector goto $ ;Trap ;;;;;;; Mainline program ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Mainline rcall Initial ;Initialize everything btg PORTC,RC2 ;Toggle pin, to support measuring loop time rcall BlinkAlive ;Blink "Alive" LED rcall LoopTime ;Make looptime be ten milliseconds ;;;;;;; Initial subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine performs all initializations of variables and registers. Initial MOVLF B'10001110',ADCON1 ;Enable PORTA & PORTE digital I/O pins MOVLF B'11100001',TRISA ;Set I/O for PORTA MOVLF B'11011100',TRISB ;Set I/O for PORTB MOVLF B'11010000',TRISC ;Set I/0 for PORTC MOVLF B'00001111',TRISD ;Set I/O for PORTD MOVLF B'00000000',TRISE ;Set I/O for PORTE MOVLF B'10001000',T0CON ;Set up Timer0 for a looptime of 10 ms MOVLF B'00010000',PORTA ;Turn off all four LEDs driven from PORTA return ;;;;;;; LoopTime subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine waits for Timer0 to complete its ten millisecond count ; sequence. It does so by waiting for sixteen-bit Timer0 to roll over. To obtain ; a period of precisely 10000/0.4 = 25000 clock periods, it needs to remove ; 65536-25000 or 40536 counts from the sixteen-bit count sequence. The ; algorithm below first copies Timer0 to RAM, adds "Bignum" to the copy ,and ; then writes the result back to Timer0. It actually needs to add somewhat more ; counts to Timer0 than 40536. The extra number of 12+2 counts added into ; "Bignum" makes the precise correction. Bignum equ 65536-25000+12+2 LoopTime btfss INTCON,TMR0IF bra LoopTime ;Wait until ten milliseconds are up movff INTCON,INTCONCOPY ;Disable all interrupts to CPU bcf INTCON,GIE ;Disable all interrupts from CPU movff TMR0L,TMR0LCOPY ;Read 16-bit counter at this moment movff TMR0H,TMR0HCOPY movlw low Bignum addwf TMR0LCOPY,F movlw high Bignum addwfc TMR0HCOPY,F movff TMR0HCOPY,TMR0H movff TMR0LCOPY,TMR0L ;Write 16-bit counter at this moment movf INTCONCOPY,W ;Restore GIEH interrupt enable bit andlw B'10000000' iorwf INTCON,F bcf INTCON,TMR0IF ;Clear Timer0 flag return ;;;;;;; BlinkAlive subroutine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This subroutine briefly blinks the LED next to the PIC every two-and-a-half ; seconds. BlinkAlive bsf PORTA,RA4 ;Turn off LED decf ALIVECNT,F ;Decrement loop counter and return if not zero bnz BAend MOVLF 250,ALIVECNT ;Reinitialize BLNKCNT bcf PORTA,RA4 ;Turn on LED for ten milliseconds every 2.5 sec BAend return end