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.

ADC of msp430

Other Parts Discussed in Thread: MSP430F1232, MSP430F2132

Hello,

I am  tringto read multiple channels from adc of msp430f1232 but having some problems. can someone please help me?

My code looks like this..

I initialized ADC as

ADC10CTL1 = 0x401E;
ADC10AE0 = 0x1C; //Port A2, A3 and A4 Enabled for Analogue
ADC10AE1 = 0x00;
ADC10DTC0 = 0x00;
ADC10DTC1 = 0x01;

void main()
//———————————
{
	Init();
	value1 = (unsigned int *)0x20B;
	value2 = (unsigned int *)0x20D;
	value3 = (unsigned int *)0x20F;
	// value = &MOD_Ua;
	__enable_interrupt(); // Enable all interrupts
	for(;;)
	{
		if (!(ADC10CTL1 & BIT0))                      // if not busy

		{

			ADC10SA = 0x20B; // Data buffer start

			ADC10CTL0 |= ENC + ADC10SC; // Start sampling and conversion
		}
	}
}

#pragma vector = ADC10_VECTOR

__interrupt void ADC10_ (void)
//————————————————————————————————
//--------------------------------------------------------------------------------
// ADC10 interrupt
//--------------------------------------------------------------------------------
{
	{
		P1OUT = P1OUT ^ BIT3;
		MOD_Uc = *value1;
		MOD_Ub = *value2;
		MOD_Ua = *value3;
	}
}

When i start debugging it enters in adc interrupt once and after that adc busy bit stays high and does not allow me to start sampling again. i saw in the debugger that adcmem register values keep on changing.

Also can you help me when it is said in the document that write to register ADC10SA is required to initiate DTC transfer.

Any help will be appreciated.

  • Hi Usman,

    In the future, please use the SyntaxHighlighter tool when pasting code so it's easier to read. I modified your original post to have that.

    Here we have some example code for continuous data transfer on multiple channels: dev.ti.com/.../

    It seems like in lines 2-3 that you have, the register you should be modifying is ADC10AE, whereas ADC10AE0 and ADC10AE1 are the individual bits within that register. You should change that line to ADC10AE = 0x1c to sample from channels A4-2.

    Regards,
    Akash Patel
  • Hello,

    Thanks for your reply!

    Actually I am working with msp430f2132 that has two ADC10AE registers i.e. ADC10AE0 and ADC10AE1 that why i have two registers up.

    Any way thanks for the support. It has started working now! :d

  • The problem was that i was not reading the correct register and also now I have used _bis_SR_register(CPUOFF+GIE) just after where I start sampling. Code in my main look like this

          ADC10CTL0 &= ~ENC;
          if (!(ADC10CTL1 & BIT0))                           // if not busy
          {
          	ADC10SA = 0x212;                                 // Data buffer start
        	ADC10CTL0 |= ENC + ADC10SC;                      // Start sampling and conversion
            __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit
          }

    I do switch off lpmo when i call ADC_interrupt like 

    __bic_SR_register_on_exit(CPUOFF);      // Clear CPUOFF bit from 0(SR)

    I just want to know that what benefits and drawbacks will I have by using the above mentioned intrinsic functions.

    Another thing is that my ADC interrupt is called after every 400 micro.second that I think is very slow for me i want faster sampling. reading the data sheet of msp430f2132 it is mentioned that it can sample upto 200 ksample/sec but i am having it only at 2.5 ksample/sec

    can you see and help me know why i am getting this slow rate.

    I re-post all my code below so that you can see!

    main.c code is as:

    #include "msp430_f2132.h"
    #include "HCB.h"
    
       void Init()
    //————————————
      {
        WDTCTL = WDTPW + WDTHOLD;   // Stop watchdog timer
      
      // CLOCK FREQUENCY    
        DCOCTL =CALDCO_16MHZ;  
        BCSCTL1 = CALBC1_16MHZ;  
        BCSCTL2 = 0x00;
        BCSCTL3 = 0x00;
      
      // OUTPUT RESET LEVEL
        P1OUT = 0x00;
        P2OUT = 0x00;
        P3OUT = 0x00;
    
      // PORT DIRECTION  
        P1DIR = 0xFF;
        P2DIR = 0xE3; 
        P3DIR = 0xFF;
      
        ADC10CTL0 = 0x0898;
        ADC10CTL1 = 0x401E;
        ADC10AE0   = 0x1C;                //Port A2, A3 and A4 Enabled for Analogue
        ADC10AE1   = 0x00;
        ADC10DTC0 = 0x00;                // Not used
        ADC10DTC1 = 0x03;                // Not used
    
        P1SEL  = 0x00;
        P1SEL2 = 0x00;
        P2SEL  = 0x00;
        P2SEL2 = 0x00;
        P3SEL  = 0x00;
    }
    int f;
    unsigned int counter;
    unsigned int ANIN_CH;
    
      void main()
    //———————————
    {
        Init();
      __enable_interrupt();                                  // Enable all interrupts
        for(;;)
        {
          ADC10CTL0 &= ~ENC;
          if (!(ADC10CTL1 & BIT0))                           // if not busy
          {
          	ADC10SA = 0x212;                                 // Data buffer start
        	ADC10CTL0 |= ENC + ADC10SC;                      // Start sampling and conversion
            __bis_SR_register(CPUOFF + GIE);                 // LPM0, ADC10_ISR will force exit
          }
        }
    }
    

    Interrupts.c is as:

     

    #include "msp430_f2132.h"
    #include "HCB.h"
    unsigned int ANIN_CH;
    
    #define ADC_MAX              3.3
    #define ADC_RANGE            1024
    unsigned int ADC_value;
    unsigned int * ANIN_CH4 = (unsigned int *) 0x212;
    unsigned int * ANIN_CH3 = (unsigned int *) 0x214;
    unsigned int * ANIN_CH2 = (unsigned int *) 0x216;
    float MOD_Ua;
    float MOD_Ub;
    float MOD_Uc;
    
    #pragma vector = ADC10_VECTOR
    
      __interrupt void ADC10_ (void)
    //————————————————————————————————
    //--------------------------------------------------------------------------------
    // ADC10 interrupt
    //--------------------------------------------------------------------------------
    {
      __bic_SR_register_on_exit(CPUOFF);      // Clear CPUOFF bit from 0(SR)
    
      {
        P1OUT = P1OUT ^ BIT3;
        MOD_Uc = (float) ((*ANIN_CH4) * ADC_MAX) * (float)1/ADC_RANGE;
        MOD_Ub = (float) ((*ANIN_CH3) * ADC_MAX) * (float)1/ADC_RANGE;
        MOD_Ua = (float) ((*ANIN_CH2) * ADC_MAX) * (float)1/ADC_RANGE;
      }
    }
    

    Please suggest why I am having ADC_Interrupt called at 400 micro-sec. I want to call this interrupt to at least at 100 micro-sec so that i could get a sampling of at least 10 ksamples/sec.

    Thanks in advance!

    BR,

    Usman

     

  • Actually each float calculation is causing me 180 micro-seconds summing up to around 540 micro-seconds as I have three lines (instructions) doing the float calculations.
    Is there anyway that I can improve that or I can achieve this faster?

    BR,
    Usman
  • Hi Usman,

    In your original post you mentioned MSP430F1232 instead of the MSP430F2132 so that is why I was confused.

    "Using the intrinsic functions allows the C programmer to take advantage of these instructions, maximizing memory and power efficiency." This is from section 3.3 in this application report: www.ti.com/.../slaa294a.pdf
    Using those intrinsic functions will put the MCU in LPM0 while it is waiting for the interrupt thus saving power.

    Performing float operations requires more processing than other math operations. For some of our MSP devices, we have the Floating Point Math Library which improves performance: www.ti.com/.../mspmathlib
    Also, the MSP432 contains an FPU which greatly improves performance with floating point operations.

    Regards,
    Akash Patel
  • Hello,

    Thanks for the reply. Is there any iqmath library for msp430f2132? If yes, please share link .

    Thanks in advance!

    BR,
    Usman
  • Hi Usman,

    We have the Fixed Point Math Library for MSP found here: www.ti.com/.../msp-iqmathlib

    However, I'm not aware of any floating point math library.

    Regards,
    Akash Patel
  • Hello Akash,

    I hope you are fine and doing well.

    I am still struggling in achieving the desired sampling rate with msp430f2132. I have posted my main and interrupt code above that you can see. I still have the same main code and therefore not re-reposting the main code however i have changed/updated the interrupt code i.e. calculations on ADC data.

    MY interrupt code is as:

    #pragma vector = ADC10_VECTOR
    
      __interrupt void ADC10_ (void)
    //————————————————————————————————
    //--------------------------------------------------------------------------------
    // ADC10 interrupt
    //--------------------------------------------------------------------------------
    {
    	ADC_int_running = 1;
    	__bic_SR_register_on_exit(CPUOFF);      // Clear CPUOFF bit from 0(SR)
        ///// Analogue data
        P1OUT = P1OUT ^ BIT3;
    
        MOD_Uc = (((long)(*ANIN_CH4) * ADC_MAX) >> 10);     // divison by 1024
        MOD_Ub = (((long)(*ANIN_CH3) * ADC_MAX) >> 10);     // divison by 1024
        MOD_Ua = (((long)(*ANIN_CH2) * ADC_MAX) >> 10);     // divison by 1024
        MOD_Uab = MOD_Ua - MOD_Ub;
        MOD_Ubc = MOD_Ub - MOD_Uc;
        MOD_Ualpha = _IQdiv(_IQmpy2(MOD_Uab) , 3000) +  _IQdiv(MOD_Ubc , 3000);
        MOD_Ubeta  = _IQdiv(MOD_Ubc , SQRT_3);
    
        ADC_int_running = 0;
        P1OUT = P1OUT ^ BIT3;
    }

    Now i have IQ library and i can see that without IQ library this code takes around 800 micro-sec and with  IQ usage it takes 400 micro-sec.  I have two problems that I would like you to help me (hopefully).

    1 - I want to achieve sampling+calculations done in around 100 micro-sec but this time increases repidly if I add some calculations as I have noticed that if have only one (first) calculation command then it takes around 12 micro-second and if i have 2 then it takes 25 micro-sec. I am surprised that why does it takes so much time to execute the commands. I have also confirmed that my SMCL clock is running at 16 MHz and i dont have clock divider. 

    2- My second problem is that sometime this code takes around 400 micro-sec in execution and sometime it takes around 600 micro-sec but i want fix sampling rate as i will process my data in other calculations and for those calculations i assume a fix sampling rate.

    Please help me and let me know that i I can achieve such calculations with msp430f2132 or should i change my processor.

    Thanks in advance!

    BR.

    Usman

  • > I have also confirmed that my SMCL clock is running at 16 MHz and i dont have clock divider.
    Note that CPU is running from MCLK, you shall check it too.

    >sometime this code takes around 400 micro-sec in execution and sometime it takes around 600 micro-sec but i want fix sampling rate
    You shall trigger ADC conversions using timer then.

    If you generate data so fast (each 600 micro-sec), then what you do with it after it is acquired? From what you say it seems that CPU does not have any spare time to do anything else than just calculate Ualpha and Ubeta...
  • Hello,

    I have made sure that my clock works fine. I think the additional it is taking in execution is because my IQlib is placed in flash memory.

    Can anybody help me to know how to place the IQ library into the ram memory so that I can get speed executions.
  • usman akhtar said:
    Can anybody help me to know how to place the IQ library into the ram memory so that I can get speed executions.

    For flash based devices such as msp430f1232 executing from flash is as fast as executing from RAM. i.e. placing the IQ library in RAM won't speed up the execution but it may lower the operating current.

    See msp430f5438A: How to copy mathematical library from flash to RAM?

**Attention** This is a public forum