Jump to content
Sign in to follow this  
cde

ADC and Interrupt/LPM issue? [Code Review Request]

Recommended Posts

Trying to use the SD16_A ADC on the EZ430 F2013. Have two separate issues. (Coded for IAR)
 
The first, am unable to do a single ADC conversion on Channel 7 (the offset checking channel)
 

     SD16AE |= INPUT;				// Enable P1.6 as A3+
     SD16CTL = SD16SSEL1 | SD16VMIDON | SD16REFON;	// 1.2v Ref On, SMCLK
     SD16CCTL0 = SD16OSR_1024;			// Set to 1024 Oversample Rate

     if (offset == 0) {
          SD16CCTL0 |= SD16DF | SD16SNGL;	// Signed, Single Conversion
          scripted_wait();			// Let Internal Ref Settle
          SD16INCTL0 = SD16INCH_7;		// ADC Channel 7
          SD16CCTL0 |= SD16SC;			// Trigger Converson
          while(!(SD16CCTL0 & SD16IFG));	// Wait for Flag
          offset = SD16MEM0;			// Signed value in Offset
          SD16CCTL0 &= ~SD16DF & ~SD16SNGL;	// Clear Signed, Clear Single Conversion
     }

It gets stuck on the while loop. While skipping this (offset = 1), the rest also has an issue. It gets stuck at __low_power_mode_0(); in the main() (Line 153 of the code below). I think I might not be setting the SD16_A or Watchdog ISR correctly, or the correctly handling the lpm0... While debugging, GIE gets cleared and never gets set again, yet the watchdog isr keeps getting handled?? (my count and _10ths_count variables increase as expected).

 

When 10ths_count is higher than 18000, Demo_State is increased to 1, which on the next loop in the While loop, should break it out, and move it to the next state. It is never getting out of the low_power_mode_0 line.

 

I edited the code to slim it down for the forum. I attached the full version below as well.
 

unsigned char Demo_State = 0;
unsigned int result = 0;

int offset = 0;

void adc_init(void)
{
     // If SD_VREF_ENABLE is defined as 1 in the Common.H, P1.3 is enabled as VREF.
     if (SD_VREF_ENABLE == 1) {
          SD16AE &= ~SD_VRef;
          P1SEL |= SD_VRef;
     }
     
     SD16AE |= INPUT;				// Enable P1.6 as A3+
     SD16CTL = SD16SSEL1 | SD16VMIDON | SD16REFON;	// 1.2v Ref On, SMCLK
     SD16CCTL0 = SD16OSR_1024;			// Set to 1024 Oversample Rate

     if (offset == 0) {
          SD16CCTL0 |= SD16DF | SD16SNGL;	// Signed, Single Conversion
          scripted_wait();			// Let Internal Ref Settle
          SD16INCTL0 = SD16INCH_7;		// ADC Channel 7
          SD16CCTL0 |= SD16SC;			// Trigger Converson
          while(!(SD16CCTL0 & SD16IFG));	// Wait for Flag
          offset = SD16MEM0;			// Signed value in Offset
          SD16CCTL0 &= ~SD16DF & ~SD16SNGL;	// Clear Signed, Clear Single Conversion
     }

     // Continious Mode
     if (Demo_State == 0) {
	  SD16INCTL0 = SD16INCH_3;		// P1.6 ADC A3+
	  SD16CCTL0 |= SD16UNI | SD16IE;
     }

     // On-Demand Mode
     if (Demo_State == 1) {
	  SD16INCTL0 = SD16INCH_3;		// P1.6 ADC A3+
	  SD16CCTL0 |= SD16UNI | SD16SNGL | SD16IE;
     }

     // Temperature Mode
     if (Demo_State == 2) {
	  SD16INCTL0 = SD16INCH_6;		// Temperature Sensor
	  SD16CCTL0 |= SD16DF | SD16IE;
     }
}

volatile int count = 0;
volatile int _10ths_count = 0;
bool blink_led0 = 0;

void timeDog_init(void)
{
     WDTCTL = WDT_MDLY_0_064;	// Happens 15625 times per second! Duh! Every 64 Clock Ticks. DUH!

     IE1 |= WDTIE;		// Enable WatchDog Interrupt
}

// WatchDog interrupt service routine
#pragma vector = WDT_VECTOR
__interrupt void WatchDog_ISR(void)
{
     count++;
     if (count == 1563) {
          count = 0;
          _10ths_count++;
          if (blink_led0 == 1 ) {
               if (_10ths_count % blink_rate) P1OUT ^= LED0;
          }
     }

     if ( _10ths_count >= (timeout_count * 600) ) {
       _10ths_count = 0;
       Demo_State++;
       if (Demo_State >= 3) Demo_State = 0;
//       __low_power_mode_off_on_exit();	// Exit LPM at Interrupt End
       __bis_SR_register_on_exit(GIE);
     }
}

int temp = 0;

// Port 1 interrupt service routine
#pragma vector = PORT1_VECTOR
__interrupt void Port_1_ISR (void)
{
     _BIC_SR_IRQ(LPM0_bits + GIE);
     // Clear LPM, Disable Interrupts to Allow MSP to handle commands before returning to sleep
     P1IFG &= ~PB;					// P1.7 IFG cleared

     if ( _10ths_count < ( temp + long_press_count) ) {		// Button pressed again too soon
          __bis_SR_register_on_exit(LPM0_bits + GIE);	// Return to LPM
          return;
     }

     temp = _10ths_count;
     _10ths_count = 0;

     while (_10ths_count == 0);				// Wait 1 10ths of a second for Debounce
     if ( (P1IN & PB) != 0) {			// If Button not still pressed, False Trigger
          __bis_SR_register_on_exit(LPM0_bits + GIE);	// Return to LPM
     }
     else while ( (P1IN & PB) == 0) {			// While Button is Still Pressed
          if (_10ths_count >= long_press_count) {	// Check for Long Press
               Demo_State++;
               if (Demo_State >= 0x3) Demo_State = 0;
//               __low_power_mode_off_on_exit();
               __bis_SR_register_on_exit(GIE);
               return;					// If Long Pressed, Break out of Interrupt
          }
     }

     if ( Demo_State == 1 ) {
//          __low_power_mode_off_on_exit();
          __bis_SR_register_on_exit(GIE);
          return;
     }
     else _10ths_count = _10ths_count + temp;		// Revert Back to Original 10ths Count
     __bis_SR_register_on_exit(LPM0_bits + GIE);	// Return to LPM
}

// SD16_ISR
#pragma vector = SD16_VECTOR
__interrupt void SD16_ISR(void)
{
     switch (__even_in_range(SD16IV, 16)) {
          case 2:				// Handle overflow;
                  break;
          case 4: result = SD16MEM0 - offset;
                  break;
     }
//     __low_power_mode_off_on_exit();
     __bis_SR_register_on_exit(GIE);
}


int main(void)
{
     cpu_init();
     led_init();
     pushbutton_init();
     timeDog_init();

     __enable_interrupt();

     // Forever Loop
     while (1) {

          // Continuous Mode
          adc_init();
          blink_led0 = 1;			// Set LED0 to Blink
          SD16CCTL0 |= SD16SC;			// Trigger Sample
          while (Demo_State == 0) {
               __low_power_mode_0();		// Sleep Until Done
               __no_operation();
               update_display();		// Display Results
          }
          clear_mode();

          // On-Demand Mode
          adc_init();
          blink_led0 = 0;			// Set LED0 to Not Blink
          P1OUT |= LED0;			// Turn LED0 On
          while (Demo_State == 1) {
               // On-Demand Mode Code
               blink_led0 = 1;			// Set LED0 to Blink
               SD16CCTL0 |= SD16SC;		// Trigger Sample
               __low_power_mode_0();		// Sleep Until Done
               __no_operation();
               blink_led0 = 0;			// Results Gathered, Stop Blinking LED0
               P1OUT |= LED0;			// Leave LED0 On
               update_display();		// Display Results
               __low_power_mode_0();		// Sleep until Button Short Press or Long Press
               __no_operation();
          }
          clear_mode();

          // Temperature Sensor Mode
          adc_init();
          blink_led0 = 0;			// Set LED0 to Not Blink
          P1OUT |= LED0;			// Leave LED0 Off
          SD16CCTL0 |= SD16SC;			// Trigger Sample
          while (Demo_State == 2) {
               __low_power_mode_0();		// Sleep Until Done
               __no_operation();
               update_display();		// Display Results
          }
          clear_mode();

     } // Forever Loop
}

main.c

common.h

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×