/****** P4_MCC18.c ************************************************************* * * 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 * ******************************************************************************* */ #include /******************************* * Definitions and equates ******************************* */ #define HalfPeriod 125000 // Number of 0.4 us clock cycles in 0.05 seconds /******************************* * Global variables ******************************* */ char WREG_TEMP; char STATUS_TEMP; char TMR1X; // Eight-bit extension to TMR1 char CCPR1X; // Eight-bit extension to CCPR1 char DTIMEL; // Half-period value char DTIMEH; char DTIMEX; /******************************* * Function prototypes ******************************* */ void Initial(void); void CCP1handler(void); void TMR1handler(void); void HiPriISR(void); void LoPriISR(void); #pragma code highVector=0x08 void atHighVector(void) { _asm GOTO HiPriISR _endasm } #pragma code #pragma code lowVector=0x18 void atLowVector(void) { _asm GOTO LoPriISR _endasm } #pragma code /******************************* * main() ******************************* */ void main() { Initial(); // Initialize everything while(1) { } } /******************************* * Initial() * * This subroutine performs all initializations of variables and registers. ******************************* */ void Initial() { DTIMEL = HalfPeriod; // Load DTIME with HalfPeriod DTIMEH = (HalfPeriod>>8); DTIMEX = (HalfPeriod>>16); TRISC = 0b11010000; // Set I/O for PORTC T1CON = 0x81; // Turn on TMR1 CCP1CON = 0b00001000; // Select compare mode RCONbits.IPEN = 1; // Enable priority levels IPR1bits.TMR1IP = 0; // Assign low priority to TMR1 interrupts IPR1bits.CCP1IP = 0; // and to CCP1 interrupts TMR1X = 0; // Make first 24-bit compare occur quickly CCPR1X = 2; PIE1bits.CCP1IE = 1; // Enable CCP1 interrupts PIE1bits.TMR1IE = 1; // Enable TMR1 interrupts INTCONbits.GIEL = 1; // Enable low-priority interrupts to CPU INTCONbits.GIEH = 1; // Enable all interrupts } /****** LoPriISR interrupt service routine ***********************************/ #pragma interrupt HiPriISR // High-priority interrupt service routine void HiPriISR(void) // Included to show form // Supports retfie FAST automatically { } #pragma interruptlow LoPriISR // Low-priority interrupt service routine void LoPriISR(void) { while(1) { if (PIR1bits.CCP1IF) { CCP1handler(); continue; } if (PIR1bits.TMR1IF) { TMR1handler(); continue; } break; } } void CCP1handler() { if (PIR1bits.TMR1IF) // If Timer1's overflow flag is set if (!(CCPR1H & 0b10000000)) // and compare had occurred after that { TMR1X++; // then increment TMR1 extension PIR1bits.TMR1IF = 0; // and clear flag } if (TMR1X == CCPR1X) // Check whether extensions are equal { CCP1CON = CCP1CON ^ 1; // Toggle control bit (bit 0) CCPR1L += DTIMEL; // and add half period to CCPR1 if (STATUSbits.C) CCPR1H++; CCPR1H += DTIMEH; if (STATUSbits.C) CCPR1X++; CCPR1X += DTIMEX; } PIR1bits.CCP1IF = 0; // Clear flag } void TMR1handler() { TMR1X++; // Increment Timer1 extension PIR1bits.TMR1IF = 0; // Clear flag and return to polling routine }