/****************************************************************************** * The following code shows how I am setting up the eCOMP module. * The main clock is running at 1 MHz. * * The comment header for the subroutine Init_eCOMP to see how the eCOMP module * is configured. * * I run the main loop in one of two ways. When the registers configuration of * P1SEL0, P1SEL1, P2SEL0, and P2SEL1 are commented out, the while loop check * the front panel switch (FPS) to see if it is active. If it is active, three * different LEDs are turned on. If the FPS is inactive, all LEDs are turned * off. * * When the P1.0 is configured to drive the eCOMP (the registers configuration of * P1SEL0, P1SEL1, P2SEL0, and P2SEL1 are not commented out), the while loop * always reads P1.0 as low. Which is okay, as the P1.0 signal is routed to the * positive input of the comparator. The output of the comparator is * routed to P2.0. P2.0 should output a low signal. Out of six boards, one * works correctly and the other five to not. * * I understand that there is likely a board problem, but the only reason for * the P2.0 output to be high is when P1.0 is greater than 2.475 volts. Which * is not the case. The input signal P1.0 is low as can be verified by checking * the signal on pin 2. *****************************************************************************/ #include #define MCLK_FREQ_MHZ 1 // Set MCLK here (1 MHz) // Forward function declarations void Init_CS(void); void Init_eCOMP(void); void Software_Trim(void); //***************************************************************************** //************************ FRAM persistent variables ************************ //***************************************************************************** // FRAM persistent variables do not get initialized by the C startup routine, // but rather the debug tool chain initializes them for the first time as the // application code is loaded onto the target. These variables are persistent // across power cycles. #pragma PERSISTENT(FAILSAFE_count) unsigned int FAILSAFE_count = 0; int main(void) { unsigned int FS_temp = 0xE; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer Init_CS(); // Set system clock Init_eCOMP(); // Set up comparator P1DIR = 0xD8; // Set direction of pins P2DIR = 0xFF; P1OUT = 0xD0; // On-board LED on, DTR on, high = MPS off P2OUT = 0x02; // FPS LED high = off // Configure Comparator input & output P1SEL0 |= BIT0; // Select 3rd module function P1SEL1 |= BIT0; // eCOMP input function on P1.0/C0 P2DIR |= BIT0; P2SEL0 &= BIT0; // Select 2nd module function P2SEL1 |= BIT0; // Select CPOUT function on P2.0/COUT PM5CTL0 &= ~LOCKLPM5; while(1) // Capture loop { if(P1IN & BIT0) { P1OUT |= BIT6; // On-board LED on P1OUT &= ~BIT7; // MPS LED on P2OUT &= ~BIT1; // FPS LED on } else { P1OUT &= ~BIT6; // On-board LED off P1OUT |= BIT7; // MPS LED off P2OUT |= BIT1; // FPS LED off } } } //****************************************************************************** // Init_CS - Initialize configuration of clock systems //****************************************************************************** // Configure MCLK for 1MHz. // FLL reference clock is REFO. // ACLK = default REFO ~32768Hz. // SMCLK = MCLK = 1MHz. // Use DCO software trim to lock FLL. If FLL is locked and // DCO tap is closest to 256, the DCOFTRIM value is the best one. //****************************************************************************** void Init_CS(void) { __bis_SR_register(SCG0); // Disable FLL CSCTL3 = SELREF__REFOCLK; // Set REFO as FLL reference source CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_0; // DCOFTRIM=3, //DCO Range=1MHz CSCTL2 = FLLD_0 + 30; // DCODIV = 1MHz __delay_cycles(3); __bic_SR_register(SCG0); // Enable FLL Software_Trim(); // Software Trim to get the best DCOFTRIM value CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) // as ACLK source, ACLK = 32768Hz // default DCODIV as MCLK and SMCLK source } //****************************************************************************** // Init_eCOMP - Initialize configuration of comparator //****************************************************************************** // The eCom module is set up so that the Front panel switch on port pin P1.0 is // connected to the positive input of the comparator. The negative input of the // comparator is connected to the DAC output. The DAC output is controlled by // two buffers. Buffer 1 is set for 3/4 of VCC so that the output of the // comparator goes positive only after the positive input is above 3/4 of VCC. // When the comparator output goes high, the DAC output switches to buffer 2. // Buffer 2 is setup for 1/4 of VCC. Now the positive input must go below 1/4 // of VCC for the comparator output to switch back to a low level. This provides // hysteresis for the switch input. // // The output of the comparator is then filtered to further prevent // oscillations in the output due to switch bounce. // // The output of the comparator is then connected to both the port pin P2.0 and // the capture/compare block 1. The capture 1 register is set up to capture both // the rising and falling edges of the comparator output. The difference // between the rising and falling edges determines how long the switch is pressed. // // When the rising edge is detected, it start the compare block 0. The // compare block 0 is set to trigger an interrupt 6 seconds after the rising // edge. If the falling edge occurs before the 6 second compare interrupt // occurs, then the button press is processed normally. If the 6 second compare // interrupt occurs before the falling edge, then the state changes to the // FAILSAFE mode. //****************************************************************************** void Init_eCOMP(void) { // Configure reference PMMCTL0_H = PMMPW_H; // Unlock the PMM registers PMMCTL2 |= INTREFEN; // Enable internal reference __delay_cycles(400); // Delay for reference settling // Setup comparator CPCTL0 |= CPPSEL_0; // Select C0 as input for V+ terminal CPCTL0 |= CPNSEL_6; // Select DAC as input for V- terminal CPCTL0 |= CPPEN | CPNEN; // Enable both eCOMP inputs CPDACCTL = CPDACEN; // Select VCC as reference and enable DAC CPDACDATA = 0x1030; // CPDACBUF1=VCC *3/4 CPDACBUF2=VCC *1/4 CPCTL1 |= CPFLT | CPFLTDLY_3 | CPMSEL | CPEN; // | | | |--- Turn on eCOMP // | | |------------ Low power low speed mode // | |----------------------- Analog filter delay 3.6 ms // |--------------------------------- Enable analog filter // Setup capture/compare block 0 for compare mode TB0CCTL0 |= CCIS_2; // Defaults to compare mode and load on write // |------------- Input set to GND // Setup capture/compare block 1 for capture mode TB0CCTL1 |= CM_3 | CCIS_1 | CCIE | CAP | SCS; // | | | | |---- Synchronous capture // | | | |---------- Capture mode, not compare mode // | | |---------------- Enable capture interrupt // | |------------------------- Capture input CCI0B = eCOMP output // |-------------------------------- Capture both edges // Timer0_B3 Setup TB0CTL |= TBSSEL_1 | ID_2 | MC_2 | TBCLR; // | | | |---- Clear TB0R and divider logic // | | |------------- Timer in continuous mode // | |-------------------- Input clock divided by 4 (8192 Hz) // |------------------------------ Clock source = ACLK (32768 Hz) } //****************************************************************************** // Software_Trim - To get the best DCOFTRIM value //****************************************************************************** // Code provided by TI examples //****************************************************************************** void Software_Trim() { unsigned int oldDcoTap = 0xffff; unsigned int newDcoTap = 0xffff; unsigned int newDcoDelta = 0xffff; unsigned int bestDcoDelta = 0xffff; unsigned int csCtl0Copy = 0; unsigned int csCtl1Copy = 0; unsigned int csCtl0Read = 0; unsigned int csCtl1Read = 0; unsigned int dcoFreqTrim = 3; unsigned char endLoop = 0; do { CSCTL0 = 0x100; // DCO Tap = 256 do { CSCTL7 &= ~DCOFFG; // Clear DCO fault flag }while (CSCTL7 & DCOFFG); // Test DCO fault flag __delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable // Suggest to wait 24 cycles of divided FLL reference clock while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0)); csCtl0Read = CSCTL0; // Read CSCTL0 csCtl1Read = CSCTL1; // Read CSCTL1 oldDcoTap = newDcoTap; // Record DCOTAP value of last time newDcoTap = csCtl0Read & 0x01ff; // Get DCOTAP value of this time dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value if(newDcoTap < 256) // DCOTAP < 256 { newDcoDelta = 256 - newDcoTap; // Delta value between DCPTAP and 256 if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256 endLoop = 1; // Stop while loop else { dcoFreqTrim--; CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4); } } else // DCOTAP >= 256 { newDcoDelta = newDcoTap - 256; // Delta value between DCPTAP and 256 if(oldDcoTap < 256) // DCOTAP cross 256 endLoop = 1; // Stop while loop else { dcoFreqTrim++; CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4); } } if(newDcoDelta < bestDcoDelta) // Record DCOTAP closest to 256 { csCtl0Copy = csCtl0Read; csCtl1Copy = csCtl1Read; bestDcoDelta = newDcoDelta; } }while(endLoop == 0); // Poll until endLoop == 1 CSCTL0 = csCtl0Copy; // Reload locked DCOTAP CSCTL1 = csCtl1Copy; // Reload locked DCOFTRIM while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked }