/****** P4_PICC-18.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); /******************************* * main() ******************************* */ void main() { Initial(); // Initialize everything while(1) { } } /******************************* * Initial() * * This subroutine performs all initializations of variables and registers. ******************************* */ void Initial() { DTIMEL = HalfPeriod & 0x0FF; // Load DTIME with HalfPeriod DTIMEH = (HalfPeriod>>8) & 0x0FF; DTIMEX = (HalfPeriod>>16) & 0x0FF; TRISC = 0b11010000; // Set I/O for PORTC T1CON = 0x81; // Turn on TMR1 CCP1CON = 0b00001000; // Select compare mode IPEN = 1; // Enable priority levels TMR1IP = 0; // Assign low priority to TMR1 interrupts CCP1IP = 0; // and to CCP1 interrupts TMR1X = 0; // Make first 24-bit compare occur quickly CCPR1X = 2; CCP1IE = 1; // Enable CCP1 interrupts TMR1IE = 1; // Enable TMR1 interrupts GIEL = 1; // Enable low-priority interrupts to CPU GIEH = 1; // Enable all interrupts } /****** HiPriISR interrupt service routine ***********************************/ void interrupt HiPriISR() // High-priority interrupt service routine { // // // Note that HiTech has not implemented the retfie FAST instruction as // of this writing. However, saving and restoring of registers are // said to be handled automatically by the compiler. } /****** LoPriISR interrupt service routine ***********************************/ void interrupt low_priority LoPriISR() // Low-priority interrupt service routine { while(1) { if (CCP1IF) { CCP1handler(); continue; } if (TMR1IF) { TMR1handler(); continue; } break; } // Return from interrupt, reenabling GIEL } void CCP1handler() { if (TMR1IF) // If Timer1's overflow flag is set if (!(CCPR1H & 0b10000000)) // and compare had occurred after that { TMR1X++; // then increment TMR1 extension TMR1IF = 0; // and clear flag } if (TMR1X == CCPR1X) // Check whether extensions are equal { CCPR1L += DTIMEL; // and add half period to CCPR1 CCPR1H += (char) DTIMEH + CARRY; // Add with CARRY bit CCPR1X += (char) DTIMEX + CARRY; CCP1CON = CCP1CON ^ 1; // Toggle control bit (bit 0) } CCP1IF = 0; // Clear flag } void TMR1handler() { TMR1X++; // Increment Timer1 extension TMR1IF = 0; // Clear flag and return to polling routine }