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.

CCS/MSP430G2553: MSP430 2 channel ADC

Part Number: MSP430G2553


Tool/software: Code Composer Studio

Hi, i was able to code a ADC ISR which is triggered by a timer CC ISR with 1 analog input.
I have been trying to code a ADC for 2 pins for some days but wasnt able so far.

the timer ISR is triggered by capture compare mode.
inside my timer ISR i want to make a ADC of my A3 pin and save it to the cariable temp1.
after the 1st ADC i tryed to switch the channel to A4 but the channel never switches.

i have also tryed to switch the channel inside my ADC interrupt but that didnt work aswell.

this is my code: (i hope someone could help me)

#include <msp430.h>
#include <msp430g2553.h>

long temp1;
long temp2;

void main(void) {

	__enable_interrupt();
	WDTCTL = WDTPW | WDTHOLD;		// Stop watchdog timer

	TACTL = TASSEL_1 + MC_1;					// ACLK-clock 	+	CCR up mode mode
	CCTL0 = CCIE;								// CCR0 Interrupt enabled
	CCR0 = 50;

	ADC10CTL1 = INCH_4 + ADC10SSEL_1;			// Channel select A4	+	Conversion sequence mode select ==  Sequence-of-channels 	+ ACLK - clock (no input div)
	ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;	// REF = VCC & VSS + ADC SampleAndHoldTime 16 x ADC10CLKs  + + //
	ADC10AE0 |= BIT3 + BIT4;			// 	 These bits enable the corresponding pin for analog input
	P1SEL |=  BIT3 + BIT4;			//	ADC input select mode P1.4

	P1DIR |= 0x00;	// ADC input P1.3

	P2DIR |= (BIT0 + BIT1 + BIT2) + (BIT3 + BIT4 + BIT5);	// pins as output // P2.0-2 for A3	+	P2.3-5 for A4
	P2OUT = 0x00;					// all pins set to low (input) //port2


}

#pragma vector = TIMER0_A0_VECTOR;
__interrupt void Timer(void){

	ADC10CTL1 = INCH_3;		// select channel A3 for ADC
	ADC10CTL0 |= ADC10SC + ENC;	// ADC10SC == 0 >> no sample start conversation + ENC == EnableConversation
	temp1 = ADC10MEM;	// saves the ADC measure in 1st temp variable
	while(!ADC10BUSY) // wait till ADC is NOT busy anymore
	{
		ADC10CTL0 &= ~ENC;	// disable conversation
	}
	ADC10CTL0 &= ~ADC10IFG;	// deletes the ADC-InterruptFlag for the next conversation

	ADC10CTL1 = INCH_4;		// select channel A4 as input
	ADC10CTL0 |= ADC10SC + ENC;
	if(ADC10CTL1 == INCH_4)temp2 = ADC10MEM;		// save ADC measure in 2nd temp variable
	while(!ADC10BUSY)
	{
		ADC10CTL0 &= ~ENC;
	}

	//TACTL &= ~TAIFG;	// deletes Timer FLag (it will be automatic set by the timer >> when cotinues mode reaches 0xFFFFx)
}


#define A0 0x00
#define A1 BIT0
#define A2 BIT0 + BIT1
#define A3 BIT0 + BIT1 + BIT2

#define B0 0x00
#define B1 BIT3
#define B2 BIT3 + BIT4
#define B3 BIT3 + BIT4 + BIT5

#pragma vector = ADC10_VECTOR;
__interrupt void ADC(void){

	const int output1[4] = {A0, A1, A2, A3};
	const int output2[4] = {B0, B1, B2, B3};

	if(temp1 >= 0 && temp1 <= 50)P2OUT = output1[0];
		else if(temp1 >= 50 && temp1 <= 400) P2OUT = output1[1];
		else if(temp1 >= 400 && temp1 <= 750) P2OUT = output1[2];
		else P2OUT = output1[3];

	if(temp2 >= 0 && temp2 <= 50)P2OUT |= output2[0];
		else if(temp2 >= 50 && temp2 <= 400) P2OUT |= output2[1];
		else if(temp2 >= 400 && temp2 <= 750) P2OUT |= output2[2];
		else P2OUT |= output2[3];

	ADC10CTL1 = INCH_4;		// select channel A4 as input

}

  • i just recognised that the ENC is never reseted because of the redundant while loop.
    the usersguid tells that the enc has to be reseted to make any registry changes in the adc.

    so i refactored my code and now im able to switch between channels.
    it works very well but only in debug mide, when i debug one line by one.

    when i dont set breakpoints my temp values from my ADC10MEM get to 1023 but i dont know why.

    heres my updated code:

    #include <msp430.h>
    #include <msp430g2553.h>
    
    long temp1;
    long temp2;
    
    void main(void) {
    
    	__enable_interrupt();
    	WDTCTL = WDTPW | WDTHOLD;		// Stop watchdog timer
    
    	TACTL = TASSEL_1 + MC_1;					// ACLK-clock 	+	CCR up mode mode
    	CCTL0 = CCIE;								// CCR0 Interrupt enabled
    	CCR0 = 50;
    
    	ADC10CTL1 = INCH_3 + ADC10SSEL_1;			// Channel select A4	+	Conversion sequence mode select ==  Sequence-of-channels 	+ ACLK - clock (no input div)
    	ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;	// REF = VCC & VSS + ADC SampleAndHoldTime 16 x ADC10CLKs  + + //
    	ADC10AE0 |= BIT3 + BIT4;			// 	 These bits enable the corresponding pin for analog input
    	P1SEL |=  BIT3 + BIT4;			//	ADC input select mode P1.4
    
    	P1DIR |= 0x00;	// ADC input P1.3
    
    	P2DIR |= (BIT0 + BIT1 + BIT2) + (BIT3 + BIT4 + BIT5);	// pins as output // P2.0-2 for A3	+	P2.3-5 for A4
    	P2OUT = 0x00;					// all pins set to low (input) //port2
    
    
    
    
    }
    
    #pragma vector = TIMER0_A0_VECTOR;
    __interrupt void Timer(void){
    
    	ADC10CTL1 = INCH_3;		// select channel A3 for ADC
    	ADC10CTL0 |= ADC10SC + ENC;	// ADC10SC == 0 >> no sample start conversation + ENC == EnableConversation
    	temp1 = ADC10MEM;	// saves the ADC measure in 1st temp variable
    	while (ADC10CTL1 & ADC10BUSY);
    	ADC10CTL0 &= ~ENC;	// disable conversation
    	ADC10CTL0 &= ~ADC10IFG;	// deletes the ADC-InterruptFlag for the next conversation
    
    	ADC10CTL1 = INCH_4;		// select channel A4 as input
    	ADC10CTL0 |= ADC10SC + ENC;
    	if(ADC10CTL1 == INCH_4)temp2 = ADC10MEM;		// save ADC measure in 2nd temp variable
    	while (ADC10CTL1 & ADC10BUSY);
    	ADC10CTL0 &= ~ENC;
    
    	//TACTL &= ~TAIFG;	// deletes Timer FLag (it will be automatic set by the timer >> when cotinues mode reaches 0xFFFFx)
    }
    
    
    #define A0 0x00
    #define A1 BIT0
    #define A2 BIT0 + BIT1
    #define A3 BIT0 + BIT1 + BIT2
    
    #define B0 0x00
    #define B1 BIT3
    #define B2 BIT3 + BIT4
    #define B3 BIT3 + BIT4 + BIT5
    
    #pragma vector = ADC10_VECTOR;
    __interrupt void ADC(void){
    
    	const int output1[4] = {A0, A1, A2, A3};
    	const int output2[4] = {B0, B1, B2, B3};
    
    	if(temp1 >= 0 && temp1 <= 50)P2OUT = output1[0];
    		else if(temp1 >= 50 && temp1 <= 400) P2OUT = output1[1];
    		else if(temp1 >= 400 && temp1 <= 750) P2OUT = output1[2];
    		else P2OUT = output1[3];
    
    	if(temp2 >= 0 && temp2 <= 50)P2OUT |= output2[0];
    		else if(temp2 >= 50 && temp2 <= 400) P2OUT |= output2[1];
    		else if(temp2 >= 400 && temp2 <= 750) P2OUT |= output2[2];
    		else P2OUT |= output2[3];
    
    	ADC10CTL1 = INCH_4;		// select channel A4 as input
    
    }
    

  • //***************************************************************************************
    //
    //                MSP430x5xx
    //             -----------------
    //         /|\|              XIN|-
    //          | |                 |
    //          --|RST          XOUT|-
    //            |                 |
    //       ADC->|P1.3         P1.0|-->LED(red)	<-- von ADC P1.3
    //  	 	  |				P2.1|-->LED(red)
    //			  |				P2.2|-->LED(red)
    //			  |-  -  -  -  -  - |
    //		 ADC->|P1.4			P2.3|-->LED(green)	<-- von ADC P1.4
    //			  |					|-->LED(green)
    //			  |					|-->LED(green)
    //
    //***************************************************************************************
    
    
    
    
    
    
    #include <msp430.h>
    #include <msp430g2553.h>
    
    void main(void) {
    
    	__enable_interrupt();
    	WDTCTL = WDTPW | WDTHOLD;		// Stop watchdog timer
    
    	TACTL |= (TASSEL_2 + ID_3 + MC_2 + TAIE);					// ACLK-clock 	+	CCR up mode mode
    	//CCTL0 = CCIE;								// CCR0 Interrupt enabled
    	//CCR0 = 50;
    	TAR = 50000;
    
    	ADC10CTL1 = INCH_3 + ADC10SSEL_1;			// Channel select A4	+	Conversion sequence mode select ==  Sequence-of-channels 	+ ACLK - clock (no input div)
    	ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;	// REF = VCC & VSS + ADC SampleAndHoldTime 16 x ADC10CLKs  + + //
    	ADC10AE0 |= BIT3 + BIT4;			// 	 These bits enable the corresponding pin for analog input
    	P1SEL |=  BIT3 + BIT4;			//	ADC input select mode P1.4
    
    	P1DIR |= 0x00;	// ADC input P1.3
    
    	P2DIR |= (BIT0 + BIT1 + BIT2) + (BIT3 + BIT4 + BIT5);	// pins as output // P2.0-2 for A3	+	P2.3-5 for A4
    	P2OUT = 0x00;					// all pins set to low (input) //port2
    
    }
    
    volatile long temp1;
    volatile long temp2;
    
    #pragma vector = TIMER0_A1_VECTOR;
    __interrupt void Timer(void){
    
    	ADC10CTL1 = INCH_3;		// select channel A3 for ADC
    	ADC10CTL0 |= ADC10SC + ENC;	// ADC10SC == 0 >> no sample start conversation + ENC == EnableConversation
    	temp1 = ADC10MEM;	// saves the ADC measure in 1st temp variable
    	while (ADC10CTL1 & ADC10BUSY);
    	ADC10CTL0 &= ~ENC;	// disable conversation
    	ADC10CTL0 &= ~ADC10IFG;	// deletes the ADC-InterruptFlag for the next conversation
    
    	ADC10CTL1 = INCH_4;		// select channel A4 as input
    	ADC10CTL0 |= ADC10SC + ENC;
    	temp2 = ADC10MEM;		// save ADC measure in 2nd temp variable
    	while (ADC10CTL1 & ADC10BUSY);
    	ADC10CTL0 &= ~ENC;
    
    	TACTL &= ~TAIFG;	// deletes Timer FLag (it will be automatic set by the timer >> when cotinues mode reaches 0xFFFFx)
    }
    
    #define A0 0x00
    #define A1 BIT0
    #define A2 BIT0 + BIT1
    #define A3 BIT0 + BIT1 + BIT2
    
    #define B0 0x00
    #define B1 BIT3
    #define B2 BIT3 + BIT4
    #define B3 BIT3 + BIT4 + BIT5
    
    const int output1[4] = {A0, A1, A2, A3};
    const int output2[4] = {B0, B1, B2, B3};
    
    #pragma vector = ADC10_VECTOR;
    __interrupt void ADC(void){
    
    	if(temp1 >= 0 && temp1 <= 50)P2OUT = output1[0];
    		else if(temp1 >= 50 && temp1 <= 400) P2OUT = output1[1];
    		else if(temp1 >= 400 && temp1 <= 750) P2OUT = output1[2];
    		else P2OUT = output1[3];
    
    	if(temp2 >= 0 && temp2 <= 50)P2OUT |= output2[0];
    		else if(temp2 >= 50 && temp2 <= 400) P2OUT |= output2[1];
    		else if(temp2 >= 400 && temp2 <= 750) P2OUT |= output2[2];
    		else P2OUT |= output2[3];
    }
    

    ok i have fixed the issue.

    i refactored my code and used the timer continues mode ISR and now it works.

    could it be that my capture compare interrupt was faster executed then then my ADC conversion finished?

    heres the working code:

  • Hi,

    It looks like you're trying to setup the timer to trigger an ADC conversion. You can setup the ADC to automatically trigger from the timer and then read the value in the ADC ISR. This ensures that the ADC has completed conversion before reading the result and there is no need to use a Timer ISR as well. I recommend looking at the following code example as a basis for this type of functionality:
    dev.ti.com/.../

    Best regards,
    Caleb Overbay

**Attention** This is a public forum