//*************************************************************************************** // gp1 General Test Board for MSP-EXP430G2ET Launchpad // gp1-sw2.c // MSP430G2553 to make it usable by all of the programs // Remove the pin jumper at P1.0 on the Launchpad // Test the switches // Debounce the switches and toggle the respective LEDs // A switch that has been held down long enough can be used for a different purpose // Uses Uses 16 MHz DCO // Requires that optimization be turned off in 'Project'. // Otherwise the compiler might remove software timers // Jed Margolin 11/18/2018. // Built with Code Composer Studio v7 //*************************************************************************************** // main.c #include #define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz #define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz #define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz #define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz void wait(unsigned int); void wait1(void); void wait2(void); void wait4(unsigned int); void Set_DCO(unsigned int Delta); void wait10ms(void); // Globals // For reading, debouncing, and processing the switches struct myswitch { unsigned char debounce; // debounce byte unsigned char state; // debounced state of the switch unsigned char old; // old state unsigned char press; // switch has been pressed unsigned char count; // how long the press clock has been running unsigned char release; // how long the release clock has been running unsigned char clockrun; // is the clock running? }; struct myswitch switch1 = {0xFF,0x01,0x01,0x00, 0x00, 0x00, 0x00}; struct myswitch switch2 = {0xFF,0x01,0x01,0x00, 0x00, 0x00, 0x00}; struct myswitch switch3 = {0xFF,0x01,0x01,0x00, 0x00, 0x00, 0x00}; struct myswitch switch4 = {0xFF,0x01,0x01,0x00, 0x00, 0x00, 0x00}; void do_switch(unsigned char, unsigned char, struct myswitch *); // PortIn, Bit, switch structure volatile unsigned int timer_flag = 0; //================================================ int main(void) { unsigned char caldata1, caldata2; // Temp. storage for MSP430 constants unsigned char count=0, save, temp; unsigned int n = 250; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer wait(150); // give the crystal 500ms to stabilize P1SEL &= ~BIT0; // In PBSW1 P1SEL2 &= ~BIT0; P1REN |= BIT0; // pullup/pulldown enabled P1OUT |= BIT0; // pullup P1DIR &= ~BIT0; // In P1SEL &= ~BIT1; // In PBSW2 P1SEL2 &= ~BIT1; P1REN |= BIT1; // pullup/pulldown enabled P1OUT |= BIT1; // pullup P1DIR &= ~BIT1; // In P1SEL &= ~BIT2; // In PBSW3 P1SEL2 &= ~BIT2; P1REN |= BIT2; // pullup/pulldown enabled P1OUT |= BIT2; // pullup P1DIR &= ~BIT2; // In P1SEL &= ~BIT3; // In PBSW4 P1SEL2 &= ~BIT3; P1REN |= BIT3; // pullup/pulldown enabled P1OUT |= BIT3; // pullup P1DIR &= ~BIT3; // In P1SEL &= ~(BIT4); // Out - LED1 P1SEL2 &= ~(BIT4); P1DIR |= BIT4; // out P1OUT &= ~(BIT4); // init to 0 P1SEL &= ~(BIT5); // Out - LED2 P1SEL2 &= ~(BIT5); P1DIR |= BIT5; // out P1OUT &= (~BIT5); // init to 0 P1SEL &= ~(BIT6); // Out - LED3 P1SEL2 &= ~(BIT6); P1DIR |= BIT6; // out P1OUT &= (~BIT6); // init to 0 P1SEL &= ~(BIT7); // Out - LED4 P1SEL2 &= ~(BIT7); P1DIR |= BIT7; // Out P1OUT &= ~BIT7; // init to 0 // Port 2 for later use of 16x2 LCD P2SEL &= ~(0x3F); // Out P2SEL2 &= ~(0x3F); P2DIR |= 0x3F; // Out P2OUT &= 0x3F; // LCD D4-7 = 0; LCD E = 0; LCD RS = 0 // Lock the DCO to the 32768 crystal - 16 MHz Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants caldata1 = DCOCTL; // for debugging caldata2 = BCSCTL1; BCSCTL2 = 0x00; // DIVM0 | DIVS0 | // MCLK and SMCLK dividers // Set up timer Interrupts - 4ms CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 16000; // 4ms interrupts TACTL = TASSEL_2 | ID1 | MC_2; // SMCLK, contmode TACTL |= TACLR; // clear timer Resets TAR, clock divider, count direction __bis_SR_register(GIE); // Timer interrupts without LPM0 //=========================================== while (1) // main loop { while(!timer_flag) { } // wait for timer_flag to go high, 4 ms interrupt timer_flag = 0; // Debounce and process the switches do_switch(P1IN, BIT0, &switch1); // PortIn, Bit mask, switch structure do_switch(P1IN, BIT1, &switch2); // PortIn, Bit mask, switch structure do_switch(P1IN, BIT2, &switch3); // PortIn, Bit mask, switch structure do_switch(P1IN, BIT3, &switch4); // PortIn, Bit mask, switch structure if(switch1.press == 1) {P1OUT ^= BIT4;} // P1.4 = LED1 switch1.press = 0; // reset the flag if(switch2.press == 1) {P1OUT ^= BIT5;} // P1.5 = LED2 switch2.press = 0; // reset the flag if(switch3.press == 1) {P1OUT ^= BIT6;} // P1.6 = LED3 switch3.press = 0; // reset the flag if(switch4.press == 1) {P1OUT ^= BIT7;} // P1.7 = LED4 switch4.press = 0; // reset the flag } // end while main loop } // end main //================================== void wait(unsigned int time) // 500 uS { volatile unsigned int i,j; for(i=time; i>0; i--) { for(j=382; j>0; j--); { } } return; } //========================================================== void wait4(unsigned int time) // 500 uS { volatile unsigned int i,j; for(i=time; i>0; i--) { for(j=20; j>0; j--); { } } return; } //========================================================== void wait2() { volatile unsigned int i; for(i=0; i<48; i++){} return; } //========================================================== void wait1() { volatile unsigned int i; i = 0; // for(i=0; i<1; i++){} return; } //======================================================== void Set_DCO(unsigned int Delta) // Set DCO to selected frequency { unsigned int Compare, Oldcapture = 0; // XT2OFF; LF Mode; DIVA_3: ACLK = LFXT1CLK/1 BCSCTL1 |= DIVA_3; // MCLK is DCOCLK; Divider /1; SIMCLK is DCOCLK; SMCLK Divider /1; DCOR // BCSCTL2 = 0; Reset = 0 anyway // Oscillator capacitor 12.5pF // BCSCTL3 |= XCAP_3; // MSP-EXP430G2ET has them on the board // Timer/Capture TACCTL0 = CM_1 + CCIS_1 + CAP; // Timer A Control TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear while (1) { while (!(CCIFG & TACCTL0)); // Wait until capture occured TACCTL0 &= ~CCIFG; // Capture occured, clear flag Compare = TACCR0; // Get current captured SMCLK Compare = Compare - Oldcapture; // SMCLK difference Oldcapture = TACCR0; // Save current captured SMCLK if (Delta == Compare) break; // If equal, leave "while(1)" else if (Delta < Compare) { DCOCTL--; // DCO is too fast, slow it down if (DCOCTL == 0xFF) // Did DCO roll under? if (BCSCTL1 & 0x0f) BCSCTL1--; // Select lower RSEL } else { DCOCTL++; // DCO is too slow, speed it up if (DCOCTL == 0x00) // Did DCO roll over? if ((BCSCTL1 & 0x0f) != 0x0f) BCSCTL1++; // Sel higher RSEL } } TACCTL0 = 0; // Stop TACCR0 TACTL = 0; // Stop Timer_A BCSCTL1 &= ~DIVA_3; // 0 = ACLK is divide by 1 } //========================================================== // wait 10 ms void wait10ms(void) { wait(41); } //========================================================== // Timer A0 interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_A (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void) #else #error Compiler not supported! #endif { CCR0 += 16000; // Add Offset to CCR0 timer_flag = 1; } //========================================================== void do_switch(unsigned char port, unsigned char bit, struct myswitch *sptr) // PortIn, Bit, switch structure { unsigned char temp; // Debounce and process the switch // sptr points to the switch's data block sptr->debounce = sptr->debounce <<1; // shifts in a zero if(port & bit) // a zero has already been shifted in { sptr->debounce++ ; // so make LSB a one } // Debounced state is either 0x00 or 0xFF if(sptr->debounce == 0x00) {sptr->state = 0x00;} if(sptr->debounce == 0xFF) {sptr->state = 0x01;} // process the switch if(sptr->state != sptr->old) // we have a change in switch state { if( (sptr->old == 0x01) && (sptr->state == 0x00) ) // we have a switch press { sptr->press = 0x01; sptr->count = 0; // clear the switch counter } if( (sptr->old == 0x00) && (sptr->state== 0x01) ) // we have a switch release { sptr->release = 0x01; } sptr->old = sptr->state; // the new state is now the old state } // Operating modes if(sptr->press) { sptr->count = 0; sptr->clockrun = 1; } if( sptr->clockrun && (sptr->count <200) ) { sptr->count++; } if( sptr->clockrun && (sptr->count >=200) ) { sptr->count = 160; // maximum count } if(sptr->release) { // sptr->release = 0; sptr->count = 0; sptr->clockrun = 0; } // We now know if a switch has been pressed (and how long it has been pressed) // and if a switch has been released temp = port; // PortIn data temp = bit; temp = sptr->debounce; temp = sptr->state; temp = sptr->old; temp = sptr->press; temp = sptr->count; temp = sptr->release; temp = sptr->clockrun; asm(" nop"); // for emulator } //===================================================