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/MSP430F5438A: ADC12 does not read a value

Part Number: MSP430F5438A


Tool/software: Code Composer Studio

Hello,

I am working with a MSP430F5438A in order to acquire 5 analog signals through 5 ADC12 Channels and send these values thorugh UART to the PC. The main problem is ADC12 does not read the value. The program does not go into the ADC interruption routine, with debbugger the program is always in while (1).

The ADC is triggered through Timer A0 every 1 ms. ADCMEMx register changes its value but as the routine is not executed, it never pass these values to the buffer.

Can someone help me please?

This is my code:

/***************************************************************
 ******************   Global variables   ***********************
 ***************************************************************/
#define MAX_SIZE 128 //Buffer's size
#define index_increment 5 // Increment between ADC acquisition

//Data are stored in both buffers
unsigned int buffer_1[MAX_SIZE]; //Buffer 1
unsigned int buffer_2[MAX_SIZE]; //Buffer 2

unsigned int buffer_status=0; //status of buffer 1 and 2


/***************************************************************
 * *************** Configuration functions *********************
 **************************************************************/
//  Peripheral Port initialization
void PORT_init (void)
{
    P1DIR |= 0x03;  // P1.0 & P1.1 output
	P3SEL=0x30;     //P3.4 --> Tx
				    //P3.5--> Rx

	P6SEL=0x80;     //P6.7 --> A7

	P7SEL=0xF0;	    //P7.4 --> A12
				    //P7.5 --> A13
				    //P7.6 --> A14
				    //P7.7 --> A15
}

//Timer A initialization
void TIMER_init (void)
{
	  TA0CCR0 = 33-1;							// Set to 1ms
	  TA0CCR1=0;
	  TA0CTL = TASSEL_1 + MC_1 + TACLR;         // ACLK, upmode, clear TAR
	  TA0CCTL0=OUTMOD_4;
}



// ADC12 Initialization
void ADC12_init (void)
{
	// ADC12 On, S&H 64 cycles, Multiple conversion
	ADC12CTL0=ADC12ON+ADC12SHT0_4+ADC12MSC;

	//Timer A1, SAMPCOM from sampling timer,
	//ADC12CLK=ACLK=32768 Hz and Repeat sequence of channels
	ADC12CTL1=ADC12SHS_1+ADC12SHP+ADC12SSEL_1+ADC12CONSEQ_3;
    ADC12CTL2=ADC12RES_2; //12 bits of resolution (13 cycles)

	ADC12IE = 0x01;                           // Enable interrupt
	ADC12IE = 0x10;                           // Enable ADC12IFG.4

	ADC12MCTL0 = ADC12INCH_7;                  // Channel = A7
	ADC12MCTL1 = ADC12INCH_12;                 // Channel = A12
	ADC12MCTL2 = ADC12INCH_13;                 // Channel = A13
	ADC12MCTL2 = ADC12INCH_14;                 // Channel = A14
	ADC12MCTL3 = ADC12INCH_15+ADC12EOS;        // Channel = A15, end seq.

}



// UART Initialization
void UART_init (void)
{
/*CAMBIAR BAUD RATE*/
    UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
    UCA0CTL1 |= UCSSEL_2;                     // SMCLK
    UCA0BR0 = 6;                              // 1MHz 9600 (see User's Guide)
    UCA0BR1 = 0;                              // 1MHz 9600
    UCA0MCTL = UCBRS_0 + UCBRF_13 + UCOS16;   // Modln UCBRSx=0, UCBRFx=0,
                                              // over sampling

    UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
}

/**************************************************************
 *****************    User's functions    *********************
 **************************************************************/
void UART_TX (unsigned int *vector, unsigned char size)
{
  while(size !=0)
  {
    // Wait for TX buffer to be ready for new data
    while(!(UCA0IFG & UCTXIFG));

    // Push data to TX buffer
    UCA0TXBUF = *vector;
    // Update variables
    size--;
    vector++;
  }

  // Wait until the last byte is completely sent
  while(UCA0STAT & UCBUSY);

}

/**************************************************************
 *******************    Main Program    ***********************
 **************************************************************/

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
	
    //Peripheral initialization
    PORT_init(); // I/O
    TIMER_init(); // Timer
    ADC12_init(); // ADC
    UART_init(); // UART

    ADC12CTL0|=ADC12ENC;

    __bis_SR_register(GIE);

    while(1)
    {

    	ADC12CTL0 |= ADC12SC;      //Start conversions

    	switch (buffer_status)
    	{
    		case 1:
    			UART_TX(buffer_1, MAX_SIZE);
    			break;

    		case 2:
    			UART_TX(buffer_2,MAX_SIZE);
    			break;

    		default:
    			break;
    	}

    }
}

/**************************************************************
 ********************    Interrupts   *************************
 **************************************************************/

//ADC12 Interrupt
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{

  static unsigned int index=0;

  switch(__even_in_range(ADC12IV,34))
  {
  case  0: break;                           // Vector  0:  No interrupt
  case  2: break;                           // Vector  2:  ADC overflow
  case  4: break;                           // Vector  4:  ADC timing overflow
  case  6: break;                           // Vector  6:  ADC12IFG0
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12: break;                           // Vector 12:  ADC12IFG3
  case 14:                                  // Vector 14:  ADC12IFG4

      P1OUT ^= 0x01;                            // Toggle P1.0

      if(buffer_status!=1)
        {
            buffer_1[index]=ADC12MEM0;   //Move A7 results
            buffer_1[index+1]=ADC12MEM1; //Move A12 results
            buffer_1[index+2]=ADC12MEM2; //Move A13 results
            buffer_1[index+3]=ADC12MEM3; //Move A14 results
            buffer_1[index+4]=ADC12MEM4; //Move A15 results

            index=index+index_increment; //Next time acquisition
            if(index>=MAX_SIZE)
            {
                index=0;                 //Restart time value
                buffer_status=1;         //Change status buffer
            }
        }
        else
        {
            buffer_2[index]=ADC12MEM0;   //Move A7 results
            buffer_2[index+1]=ADC12MEM1; //Move A12 results
            buffer_2[index+2]=ADC12MEM2; //Move A13 results
            buffer_2[index+3]=ADC12MEM3; //Move A14 results
            buffer_2[index+4]=ADC12MEM4; //Move A15 results

            index=index+index_increment; //Next time acquisition
            if(index>=MAX_SIZE)
            {
                index=0;                 //Restart time value
                buffer_status=2;         //Change status buffer
            }
        }
      break;

  case 16:break;						    // Vector 16:  ADC12IFG5
  case 18: break;                           // Vector 18:  ADC12IFG6
  case 20: break;                           // Vector 20:  ADC12IFG7
  case 22: break;                           // Vector 22:  ADC12IFG8
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26: break;                           // Vector 26:  ADC12IFG10
  case 28: break;                           // Vector 28:  ADC12IFG11
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break;
  }
}

Thanks in advance,

Best regards,

Miguel

  • Hello Miguel,

    Your EOS is ADC12MCTL3, not ADC12MCTL4 (probably due to duplicate of ADC12MCTL2), and therefore the ADC12IE.4 is invalid since the code sets ADC12IFG.3 after a conversion sequence is completed.

    Regards,
    Ryan
  • Hello Ryan,
    you are right, duplicate ADC12MCTL2 is the problem.

    Another question:
    what is the better configuration for the ADC mode to acquire 5 channels? Single channel single conversion, Sequence of channel, Repeat single channel or Repeat sequence of channels?

    I do not understand very well the difference between them neither the ADC12MSC bit.

    Regards,
    Miguel
  • Hi Miguel,

    Since you are using a timer trigger then sequence-of-channel mode with ADC12MSC & ADC12SHP set is the best solution. Please refer to the Figures in Section 28.2.7 of the User's Guide and be sure to toggle the ADC12ENC bit between each sequence.

    Regards,
    Ryan
  • Hi Ryan,

    Using this code, I receive a distorted signal in the PC. I use a 50 Hz signal in the ADC pins, but I can not shown the same signal in the PC.
    I think maybe is the baud rate or way of sending is wrongly.
    How can I calculate the correct baud rate?

    Thanks,

    Regards,
    Miguel
  • Hey Miguel,

    Your baud rate settings are correct as indicated by Table 36-5 of the User's Guide. You may want to try not using over-sampling mode for more leniency. You can use a logic analyzer or oscilloscope to verify that the data is being sent correctly but I doubt that UART is the issue. The ADC sources ACLK which is far too slow to sample and convert 5 channels before the next timer trigger, your sampling rate is likely much slower than the 1 ms you expect. Of course both ADC12MSC and ADC12SHP are set in repeat-sequence-of-channel-mode so the timer trigger doesn't account for much after the first sequence conversion. Please review the code examples along with Chapter 28 of the User's Guide, and use a GPIO pin toggle inside of the ADC12 ISR to figure out how fast your conversion rate really is.

    Regards,
    Ryan

**Attention** This is a public forum