yyrkoon 250 Posted June 21, 2016 Share Posted June 21, 2016 So, I have a concern. With the code I have below. I'm using the watchdog timer, an interval upmode timer, and I'm reading from inch5 of the ADC within the program loop. The only peripheral interrupt that I currently have is for TIMER1 A0, and that pretty much sets the pace for the whole program. However, I do need a GPI, and I would really like to use an interrupt to tell when this GPI has been toggled. The problem is, I am not sure how I should deal with that, in the code I have below. Advice would be greatly appreciated. By the way, the Serial stuff is merely for debugging, and will not be staying. If that is important. #include <msp430.h> #include <stdlib.h> #include "hw_serial.h" using namespace uart; volatile unsigned int count = 1; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer UART<9600, 1000000> Serial; // Declare Serial object /* SMCLK */ DCOCTL = 0; DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; BCSCTL2 = DIVS_0; /* ADC */ P1SEL |= BIT5; ADC10CTL1 = INCH_5 + ADC10DIV_3 ; ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON; ADC10AE0 |= BIT5; /* Timer1 A0 */ TA1CCR0 = 1250; // Count overflow frequency TA1CTL = TASSEL_2 + ID_3 + MC_1; // SMCLK/8 upmode // ( 1000000 / 8 ) / 1250 == 10ms tick TA1CCTL0 = CCIE; // Enable timer interrupt __enable_interrupt(); WDTCTL = WDTPW | WDTCNTCL; // Enable WDT Serial.Initialize(); // Initialize serial while(1){ LPM0; // Enter low power mode 0 WDTCTL = WDTPW | WDTCNTCL; // Pet dog if (count > 100){ // ~1 Second count = 1; __delay_cycles(1000); // Wait for ADC Ref to settle ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start Serial.Write(ADC10MEM, 10); Serial.Write("\r"); } } return 0; } __attribute__( (interrupt (TIMER1_A0_VECTOR)) ) void TIMER1_A0_ISR(void) { LPM0_EXIT; count++; } Quote Link to post Share on other sites
yyrkoon 250 Posted June 21, 2016 Author Share Posted June 21, 2016 *OR* would it be better to poll ( test ) the specific pin, and span that test over several timer ticks ? Inquiring yyrkoon's want to know Quote Link to post Share on other sites
chicken 630 Posted June 21, 2016 Share Posted June 21, 2016 Not quite sure what the concern is. Just create the 2nd ISR. The MSP430 will only process one interrupt at a time. If the pin wiggles while you're in the timer ISR, the pin's ISR will be invoked after the timer ISR completes. yyrkoon 1 Quote Link to post Share on other sites
yyrkoon 250 Posted June 21, 2016 Author Share Posted June 21, 2016 Not quite sure what the concern is. Just create the 2nd ISR. The MSP430 will only process one interrupt at a time. If the pin wiggles while you're in the timer ISR, the pin's ISR will be invoked after the timer ISR completes. I guess I was worried about nested interrupts. But after reading and refreshing my memory I suppose nested interrupts has to be enabled first. I was thinking that I had to disable interrupts every time I was in one . . . tripwire 1 Quote Link to post Share on other sites
yyrkoon 250 Posted June 21, 2016 Author Share Posted June 21, 2016 @@chicken Seems to be working fine, thanks for the nod on just using both interrupts no other modifications. To anyone else, heres the code I'm using for a test. I'm not saying it is perfect, but it works, and it's probably not a good idea calling Serial.Write() from within the ISR, but I wanted a quick test . . . #include <msp430.h> #include <stdlib.h> #include "hw_serial.h" using namespace uart; UART<9600, 1000000> Serial; volatile unsigned int count = 1; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer /* SMCLK */ DCOCTL = 0; DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; BCSCTL2 = DIVS_0; /* PINS */ P1OUT &= 0x00; P1DIR &= 0x00; P1SEL |= BIT5; P1REN |= BIT3; P1OUT |= BIT3; P1IE |= BIT3; P1IES |= BIT3; P1IFG &= ~BIT3; /* ADC */ ADC10CTL1 = INCH_5 + ADC10DIV_3 ; ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON; ADC10AE0 |= BIT5; /* Timer1 A0 */ TA1CCR0 = 1250; // Count overflow frequency TA1CTL = TASSEL_2 + ID_3 + MC_1; // SMCLK/8 upmode // ( 1000000 / 8 ) / 1250 == 10ms tick TA1CCTL0 = CCIE; // Enable timer interrupt __enable_interrupt(); WDTCTL = WDTPW | WDTCNTCL; // Enable WDT Serial.Initialize(); // Initialize serial while(1){ LPM0; // Enter low power mode 0 WDTCTL = WDTPW | WDTCNTCL; // Pet dog if (count > 100){ // ~1 Second count = 1; __delay_cycles(1000); // Wait for ADC Ref to settle ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start Serial.Write(ADC10MEM, 10); Serial.Write("\r"); } } return 0; } __attribute__( (interrupt (TIMER1_A0_VECTOR)) ) void TIMER1_A0_ISR(void) { LPM0_EXIT; count++; } __attribute__( (interrupt (PORT1_VECTOR)) ) void PORT1_ISR(void) { LPM0_EXIT; if(P1IFG & BIT3){ Serial.Write("Push button 2 pressed\r\n"); P1IFG &= ~BIT3; } } Quote Link to post Share on other sites
yyrkoon 250 Posted June 21, 2016 Author Share Posted June 21, 2016 A demonstration Video, because . . . I can zeke 1 Quote Link to post Share on other sites
colotron 5 Posted June 27, 2016 Share Posted June 27, 2016 @@chicken Seems to be working fine, thanks for the nod on just using both interrupts no other modifications. To anyone else, heres the code I'm using for a test. I'm not saying it is perfect, but it works, and it's probably not a good idea calling Serial.Write() from within the ISR, but I wanted a quick test . . . I agree... not good to call function that is not specifically re-entrant, and moreover, uses a shared resource (serial port) from an ISR. The simplest way is to set some flag in ISR and check those in the main loop: volatile unsigned int intFlags; typedef enum { ISR1_FLAG = BIT 0, ISR2_FLAG = BIT1, //... and so on }; void isr1(void) { //..do something.. intFlags |= ISR1_FLAG; //:exit low power mode } void isr2(void) { //..do something.. intFlags |= ISR2_FLAG; //:exit low power mode } void main(void) { //.. while(1) { //...other code //:disable interrupts if (intFlags & ISR1_FLAG) { //handle isr1 intFlags &= ~ ISR1_FLAG; } if (intFlags & ISR2_FLAG) { //handle isr2 intFlags &= ~ ISR2_FLAG; } //check all other int flags //:enable interrupts. //The disable/enable interrupts could be done for each flag //(in case a handler takes time), but I choose not clutter //too much this simple example. } } What could happen if you do it as posted?, occasionally you will find in the serial console something like 568 600 605 59Push button 2 pressed 5 600 Quote Link to post Share on other sites
yyrkoon 250 Posted June 27, 2016 Author Share Posted June 27, 2016 I agree... not good to call function that is not specifically re-entrant, and moreover, uses a shared resource (serial port) from an ISR. The simplest way is to set some flag in ISR and check those in the main loop: Yeap, I would only set a variable, of some type and then leave the ISR. For any ISR After turning off low power mode of course. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.