This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

  • Resolved

MSP430F2122: MSP430F2132

Prodigy 165 points

Replies: 3

Views: 119

Part Number: MSP430F2122

Good morning,

The ADC10 is not always supplying reliable results in the program I am currently developing. I am trying to monitor five analog voltages critical to the operation of the hardware. The values returned from A0 through A4 appear to be accurate except for A2. The value returned from this channel if always in the range of 10 to 20 counts when its count should be about 350, depending on the values of A0 and A1. These values are typically in the range of 650 to 800 and A2 should be about half the value of the other two. I have verified the analog input to the A2 pin is correct so I am puzzled at this result, especially since I have tested 10 to 12 different identical cards with the same result. I have used code similar to the attachments below in other designs with good results so I'm not sure what's wrong with my code this go-around.

Regards, Harvey

Initialization Code:

//================================ Setup the ADC10 ================================
//
// These bits select the channel for a single-conversion sequence, beginning with the highest channel.
//
// Analog to Digital Converter (ADC) initialization.
ADC10CTL1 = 0; // Shutdown ADC10
ADC10CTL0 = 0;

ADC10AE0 |= 0x1F; // Set P3.0 and P2.4 through P2.0 pins as inputs to ADC.
ADC10CTL1 = INCH_4 + ADC10DIV_7 + CONSEQ_1; // Select maximum channel number in sequence (A5)
ADC10CTL0 = ADC10SHT_3 + ADC10ON; // Select Vcc as the positive referance voltage.

ADC10CTL0 |= ADC10IE;
ADC10CTL0 |= ( ENC + ADC10SC ); // Start up ADC block conversion state machine.

Data Capture Code:

if( ADC_CC == ( ADC_CC & ADC_Flags ) ) { ADC_Flags &= ~(ADC_CC); // Clear Conversion Complete flag

switch(ADC_data_state) // ***** Beginning of ADC Data State Machine *****
{
/*
case Acquire_A5: // Analog input A5 - spare analog, currently assigned digital output UCLK.
Ch_A5[8] -= Ch_A5[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A5[ADC_POINTER] = Analog_data; // Save latest sample.
Ch_A5[8] += Ch_A5[ADC_POINTER]; // Add in latest sample.

Analog5 = Ch_A5[8] >> 3; // Average of spare input A5 = sum/8.

ADC10CTL0 |= ADC10SC; // Start next conversion.
ADC_data_state = Acquire_A4;
break;
*/
case Acquire_A4: // Analog input A4 - VREF_2.5
Ch_A4[8] -= Ch_A4[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A4[ADC_POINTER] = Analog_data; // Save latest sample.
Ch_A4[8] += Ch_A4[ADC_POINTER]; // Add in latest sample.

VREF = Ch_A4[8] >> 3; // Ch A4 - 777, Average voltage of the reference.

ADC10CTL0 |= ADC10SC; // Start next conversion.
ADC_data_state = Acquire_A3;
break;

case Acquire_A3: // Analog input A3 - I_Sns_Volt - Current into or out of the cell string.
Ch_A3[8] -= Ch_A3[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A3[ADC_POINTER] = Analog_data - Ipwr_Offset; // Save latest sample less the sensor offset.
Ch_A3[8] += Ch_A3[ADC_POINTER]; // Add in latest sample.

if( ( Ch_A3[ADC_POINTER] < I_Maximum_Neg ) || ( Ch_A3[ADC_POINTER] > I_Maximum_Pos ) ) {
P1OUT &= ~Str_En; // Disconnect the cell string.
LED_Reload_On = 50;
LED_Reload_Off = 50;
Over_Current_Timer = 34; // Give the batteries a chance to cool before allowing a restart.

I_Monitor_state = I_Mon_Max; // Absolute maximum exceeded, go wait for the current to go to zero.
}

I_Sense = Ch_A3[8] >> 3; // Ch A3 - Average current in or out of the cell string.

ADC10CTL0 |= ADC10SC; // Start next conversion.
ADC_data_state = Acquire_A2;
break;

case Acquire_A2: // Analog input A2 - MID_STRING*
Ch_A2[8] -= Ch_A2[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A2[ADC_POINTER] = Analog_data; // Save latest sample.
Ch_A2[8] += Ch_A2[ADC_POINTER]; // Add in latest sample.

MID_STRING = Ch_A2[8] >> 3; // Ch A2 - Average voltage at cell string center tap.

ADC10CTL0 |= ADC10SC; // Start next conversion.
ADC_data_state = Acquire_A1;
break;

case Acquire_A1: // Analog input A1 - Cell_POS*
Ch_A1[8] -= Ch_A1[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A1[ADC_POINTER] = Analog_data; // Save latest sample.
Ch_A1[8] += Ch_A1[ADC_POINTER]; // Add in latest sample.

CELL_POS = Ch_A1[8] >> 3; // Ch A1 - Average voltage on the top cell.

ADC10CTL0 |= ADC10SC; // Start next conversion.
ADC_data_state = Acquire_A0;
break;

case Acquire_A0: // Analog input A0 - BAT_BUS*
Ch_A0[8] -= Ch_A0[ADC_POINTER]; // Subtract oldest sample from sum of all samples.
Ch_A0[ADC_POINTER] = Analog_data; // Save latest sample.
Ch_A0[8] += Ch_A0[ADC_POINTER]; // Add in latest sample.

BATTERY_BUS = Ch_A0[8] >> 3; // Ch A0 - Average voltage on the battery bus.


// Housekeeping
//
ADC10CTL0 &= ~( ENC + ADC10SC ); // Disable ADC

if( ++ADC_POINTER > 7 ) { ADC_POINTER = 0; } // Point to next elements in the arrays.

if( ADC_REAL != ( ADC_REAL & ADC_Flags ) ) {
if( Turn_On_Delay != ( Turn_On_Delay & System_Flags ) ) {
if( Real_Data_Count != 0) { Real_Data_Count--; }
else { ADC_Flags |= ADC_REAL; } // Tell the main loop data is now reliable.
}
}

ADC_Flags |= ADC_BCC; // Set data block complete flag.
ADC10CTL0 |= ( ENC + ADC10SC ); // Start new block conversion

if( Wait_Timer > 0 ) { Wait_Timer--; } // If not already 0, decrement the timer.

ADC_data_state = Acquire_A4; // Go get the next block of conversions
break;

default:
Gen_Msg_Flags1 |= Gen_Msg_0;
ADC_data_state = Acquire_A4;
break;

} // End switch ***** Bottom of ADC Data State Machine *****
} // End if ADC_CC and PACKET_DEFAULT

Interrupt Service Routine:

/* -----------------------------------------
* NAME: evADC_isr
*
* DESCRIPTION:
* Conversion done for the ADC
* set variest process flags
*
*
* ------------------------------------------*/
#pragma vector = ADC10_VECTOR
__interrupt void evADC_isr(void)

{
Analog_data = ADC10MEM; // Save data from ADC in temporary buffer
ADC10CTL0 &= ~ADC10SC; // Hold-off next conversion.
// ADC10CTL0 &= ~(ADC10IFG); // Clear ADC conversion complete interrupt flag
ADC_Flags |= ADC_CC; // Set conversion complete flag
}

  • This seems straightforward enough.

    It may be worth a quick audit of the rest of the code to make sure someone didn't accidentally "adopt" P2.2 for something else. (Keeping in mind: (1) ADC10AE0 only conditions the pin, it doesn't assign an alternate function in the usual sense (2) P2REN on the F2 series has an effect independent of any other configuration.)

    It looks as though the A3 logic (just prior to the A2 conversion) may fiddle something on P1. Is there any chance that could have a side-effect?

  • In reply to Bruce McKenney47378:

    Good morning Bruce,

    Thanks for the help.

    I forgot that the JTAG lines are also used during debugging and was using TDO to enable FET switches to connect the ADC10 inputs to the signals being monitored. This was done to conserve power when the card is inactive but the toggling of TDO during debug was effecting the sampling of channel A2 more profoundly than the other channels.

    Regards, Harvey

  • In reply to Harvey Novak:

    Hi Harvey,

    Glad you were able to resolve your issue!

    Thanks for the help, Bruce!

    -Mitch

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.