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.

MSP430G2553: ADC10 convert problem

Part Number: MSP430G2553


Hello I have ADC problem,

code

-----

int adc_value;

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
ADC10CTL0 = SREF_0 | ADC10SHT_2 | ADC10ON ;
ADC10CTL1 = INCH_0 | SHS_0 | ADC10DIV_0 | ADC10SSEL_2 | CONSEQ_0;
while(1)
{
ADC10CTL0 = ADC10CTL0 | ENC | ADC10SC;
while(ADC10CTL1 & BUSY)
{
ad_value=ADC10MEM;
ADC10CTL0 &= ENC;
}
}
}

I have see datasheet of MSP430G2553 and set CONSEQ at 00 mode

and see process picture;

I sure that SHS=0,ENC=1,ADCSC=1;but in debug i always see SHS=0,ENC=1,ADC10SC=0 BUSY=0; 

and it should goto convert process and busy should change to 1; but ADC10SC & BUSY always =0 ;why??

and it change convert.....at adc10MEM get value; it should get busy for 1 at convert; and complete busy sholud auto goto zero, but it doesn't

please see video ;

how to explain ;  i want my code enter to     "while(ADC10CTL1 & BUSY)" loop

  • >while(ADC10CTL1 & BUSY)
    >{
    > ad_value=ADC10MEM;
    >ADC10CTL0 &= ENC;
    >}

    Try:

    > while(ADC10CTL1 & ADC10BUSY) /*EMPTY*/; // Wait for not-busy
    > ad_value = ADC10MEM; // Fetch result
    > ADC10CTL0 &= ~ENC; // Disable until next time
  • NO,it doesn't go to the while....busy alway 0 and not change for 1
  • Hello,

    It wasn't clear in the video that it's an ADC problem or maybe something wrong with debugging/in the project. You may need to clean then rebuild you project and try running it again.

    There are many ADC10 example code projects available here: dev.ti.com/.../

    Can you test with one of those examples on the launcpad? You can import them directly into CCS via view-> Resource explorer.

    Thanks,
    JD

  • It is highly improbable that you will ever see ADC10BUSY=1 in the debugger (with CONSEQ=0), since the conversion will complete in the background while the debugger is doing its breakpoint bookkeeping.

    It is possible (17 MCLKs) that your loop will detect ADC10BUSY=1 (once), but I'm not sure how you would tell.

    If your goal is to do an ADC conversion and retrieve the result, I recommend the code I suggested above. If your goal is different, you probably need to explain it in more detail.

    Unsolicited: You will get better conversion results if you add:
    > ADC10AE0 |= BIT0; // Disable digital circuitry on A0
  • you suggestion is not useful,and u supply the example of the code by adc10 then it is not eample for conseq=00 mode
    ok,i ask u if i want to use conseq=00 mode how should i set the adc10 register??
    i don't want to change repeat i only want on ins change onece adc channel.
  • https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/166/4540.MSP430G2553_5F00_tiny_5F00_printf.7z

    First i am noob in msp430g2553,so I don't know how to use adc10.and datasheet is not clear to detail.
    I reference the book of "MSP430 Microcontroller Basics",and get the a knowledge if the adc is converting then the state of busy should be 1.
    but in video my register busy always is zero, and it can change complete for ADC_VAULE????
    the process of figure22-5 picture say register set SHS=0 and ENC + ADC10sc set 1 and 1 ins then it should get start of convert,
    isn't? so then it is coverting then the register of busy bit should be 1.anther say how can i check the covert is complete in conseq_0 mode.
    maybe the datasheet official is not write detial? oh maybe the busy bit will not support at conseq_0 mode?????

    and i open my ez430FET step by step i don't see it always stop at while(ADC10CTL0&ADC10busy);

    oh i am sure that it is not change for bit busy. but it some times i will get ad covert value???

    oh maybe i post my project. it is strange and it jump out the while routine if it is not at debug mode???

    and strange thing is i put code for ad channel change by 2 channel and i get a1 value by A0PIN,get  a0 value by A1PIN .

    it it big trouble,if it is use at project it is terrible please explain . and see project comment adc part.

  • Maybe u can run this code , i am sure that adc have big problem then my machine can;t work.
    #include <msp430.h>

    #define Vref 3.3
    float Switch_Out;
    float Dc_Current;
    int current_temp;
    int pwm_temp;
    int Pwm_Out;
    int Adc_flag;
    int Bkin;
    int not;
    int test;
    void printf(char *, ...);
    void float_to_int(float v,int flag);
    void Read_Bkin();
    void open();
    void main(void)
    {
    // Disable watchdog
    WDTCTL = WDTPW + WDTHOLD;
    // Use 1 MHz DCO factory calibration
    DCOCTL = 0;
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;
    BCSCTL2 = DIVS_3; // 1MHZ/8 = 125KHZ
    //Set GPIO for Alarm LED
    P2DIR|=BIT0;
    P1DIR|=BIT5;
    //Set GPIO for BKIN INPUT
    P2DIR&=~BIT7;
    //PWM
    P2DIR|=BIT6;
    P2SEL|=BIT6;
    P2SEL &= ~BIT7; //disable XTAL pin select TA0.1 PWM
    P2SEL2 &= ~(BIT6 | BIT7); //disable XTAL pin select TA0.1 PWM
    //Timer A1 for interrupt
    TA1CCTL1=CCIE;
    TA1CCR0=1523; // for 0.1 sec int
    TA1CTL=TASSEL_2+ID_3+TAIE+TACLR+MC_1; //125KHZ/8=15.625KHZ 1/15.625=0.064ms
    //PWM TIMER for Timer A0
    TA0CTL=TASSEL_2+MC_1+ID_3; //125KHZ/8=15.625KHZ
    TA0CCTL1=OUTMOD_7;
    TA0CCR0=1023-1; //1/15.625KHZ=0.064ms , 0.064*1023=65.472ms, 1/65.472ms=15.27Hz,PWM peroid = 15.27Hz
    //ADC_channel
    P1REN|=BIT0;
    P1REN|=BIT1;
    P2OUT&=~BIT0;
    __bis_SR_register(GIE);
    while(1)
    {
    //flag=0 , adc channel =A1; get switch_out value
    if(Adc_flag==0)
    {
    ADC10CTL0 = SREF_0 | ADC10SHT_2 | ADC10ON ;
    ADC10CTL1 = INCH_1 | SHS_0 | ADC10DIV_0 | ADC10SSEL_2 | CONSEQ_0; //CONSEQ_0 = 00 mode ,ADC channel changer 1 times.
    ADC10CTL0 = ADC10CTL0 | ENC | ADC10SC; // open ADC;
    while(ADC10CTL1&ADC10BUSY)
    {

    pwm_temp=ADC10MEM;
    Switch_Out=Vref/1023*pwm_temp;
    float_to_int(Switch_Out,Adc_flag);
    ADC10CTL0&=~ENC;
    Adc_flag=1;
    // printf("pwm_temp = %i\n",pwm_temp);
    }
    }
    //flag=1 , adc channel =A0; Dc_Current
    if(Adc_flag==1)
    {
    ADC10CTL0 = SREF_0 | ADC10SHT_2 | ADC10ON ;
    ADC10CTL1 = INCH_0 | SHS_0 | ADC10DIV_0 | ADC10SSEL_2 | CONSEQ_0; //CONSEQ_0 = 00 mode ,ADC channel changer 1 times.
    ADC10CTL0 = ADC10CTL0 | ENC | ADC10SC; // open ADC;
    while(ADC10CTL1&ADC10BUSY)
    {
    current_temp=ADC10MEM;
    Dc_Current=Vref/1023*current_temp;
    float_to_int(Dc_Current,Adc_flag);
    ADC10CTL0&=~ENC;
    Adc_flag=0;
    // printf("current_temp = %i\n",current_temp);
    }
    }
    open();
    Read_Bkin();
    if(Bkin==0)
    {
    TA0CCR1=pwm_temp;
    }
    else
    {
    TA0CCR1=0;
    }
    //printf("BKIN = %i\n",Bkin);

    //if(a>10){P2OUT&=~BIT0;}
    //if(a>=100)a=0;
    //printf("A = %i\n",a);

    if(not>5)P2OUT&=~BIT0;
    if(not<5)P2OUT|=BIT0;

    }
    }
    void open()
    {
    if(Dc_Current>2.67)
    {
    P1OUT|=BIT5;
    // TA1CTL=MC_1;
    }
    else
    {
    // TA1CTL=MC_0;
    P1OUT&=~BIT5;
    }
    }
    void Read_Bkin()
    {
    if((P2IN & BIT7)==0)
    {
    Bkin=0;
    }
    else
    {
    Bkin=1;
    }
    }
    void float_to_int(float v,int flag)
    {
    int temp[1];
    int full;
    full=(int)v;
    temp[1]=v;
    temp[0]=(v-full)*10;
    if(flag==0){printf("Switch_Out = %i",temp[1]);printf(".");printf("%i\n",temp[0]);}
    if(flag==1){printf("DC_Current = %i",temp[1]);printf(".");printf("%i\n",temp[0]);}
    }
    #pragma vector = TIMER1_A1_VECTOR
    __interrupt void Timer1_A1_ISR( void )
    {
    switch(TA1IV) // Read interrupt vector for TA1
    {
    case 2: // TA1CCR1
    {
    not++;
    if(not>=10)
    {
    not=0;
    }

    break;
    }

    case 14: // Overflow - TA1IFG
    {

    break;
    }
    }
    }
  • Hello,

    MSP430g2x33_adc10_01 is a single conversion on P1.1. It's extremely similar to what you are trying to but interrupt driven. I just downloaded it and ran in on my MSP-EXP430G2 launchpad and it's working well. I would suggest comparing to this exact example: dev.ti.com/.../

    Comparing your code to the above example, I don't see you setting register ADC10AE0. This register enables the GPIO as an analog input and is required for making ADC measurements.

    I would recommend running and debugging the above example, and then adjusting the example to fit your exact application.

    Thanks,
    JD

  • hey …u wasnt answer me any question . I have see that example for single convert once for repeat and then conseq is 01 ,I just say I need conseq=0 mode example,r u listen?

  • Maybe this is the missing piece: When you set ADC10SC, ADC10BUSY immediately goes to 1 (busy), and once the conversion is complete it automatically goes back to 0 (no longer busy). After this entire sequence, the conversion is complete. (I thought this was explicitly said in the User Guide (SLAU144J), but I can't seem to find it.)

    This process (0->1->0) is very quick. The debugger is much too slow for you to see ADC10BUSY=1. Your program may or may not ever see it at 1 (depending on what code the compiler generated). But you're only interested in the point after it has gone back to 0, meaning the conversion is complete.

    You should not be touching any of the registers while ADC10BUSY=1.

    That's why the code I suggested above spins as long as ADC10BUSY=1, and only afterward reads ADC10MEM. You can also see this in Example msp430g2x33_adc10_05.c here:
    dev.ti.com/.../

    That program is using an internal channel (INCH_11) so it doesn't set ADC10AE0. But your program should (see above).

    [Edit: Re-worded slightly.]

  • MSP430G2553_tiny_printf.rarok,thx for u ,but anther question ,please see my project file

    i want to ask why i see P1.0(A0) get adc_cahnnel for A1 value, P1.1(A1) get adc_cahnnel for A0 value

    open my project and burn code see print; and operate by hardware u will find this strange;

  • This appears to be the same code you posted earlier. It always reads from A1 since you're checking incorrectly for ADC completion, so Adc_flag is always =0. it's always reading the result too early and getting the previous result.

    If you make the change I've recommended (3 times so far) I expect it will switch back and forth between A0 and A1. you will match the results correctly.

    Also, I don't recommend setting the P1REN bits for P1.0/1 (A0/1). Based on the schematics in the data sheet (SLAS735j) just before Table 16, setting ADC10AE0 doesn't appear to disable the resistors.

    Also, "not" should be declared "volatile".

    [Edit: I misread the first time due to the code formatting.]

  • ok,thx i modify the code

    ****
    if(Adc_flag==0)
    {
    ADC10CTL0 = SREF_0 | ADC10SHT_2 | ADC10ON ;
    ADC10CTL1 = INCH_1 | SHS_0 | ADC10DIV_0 | ADC10SSEL_2 | CONSEQ_0; //CONSEQ_0 = 00 mode ,ADC channel changer 1 times.
    ADC10CTL0|= ENC + ADC10SC; // open ADC;
    while(ADC10CTL1&ADC10BUSY);
    A1=ADC10MEM;
    A1_Voltage=Vref/1023*A1;
    float_to_int(A1_Voltage,Adc_flag);
    ADC10CTL0&=~ENC;
    Adc_flag=1;
    }
    if(Adc_flag==1)
    {
    ADC10CTL0 = SREF_0 | ADC10SHT_2 | ADC10ON ;
    ADC10CTL1 = INCH_0 | SHS_0 | ADC10DIV_0 | ADC10SSEL_2 | CONSEQ_0; //CONSEQ_0 = 00 mode ,ADC channel changer 1 times.
    ADC10CTL0|= ENC + ADC10SC; // open ADC;
    while(ADC10CTL1&ADC10BUSY);
    A0=ADC10MEM;
    A0_Voltage=Vref/1023*A0;
    float_to_int(A0_Voltage,Adc_flag);
    ADC10CTL0&=~ENC;
    Adc_flag=0;
    }
    ***

    and it work,and correct with a0 & a1 value.

    thx very much

    this code is you mean?
    i didn't foud while(); I always think while(){;} , haha so big mistake by me

    another question is that how fast sample  speed in this code loop of converting time ~ convert complete

    is 1MHZ*8=8MHZ for tsample peroid. and tconvert time is 13*ADC10CLK =13MHZ ??

  • The ADC conversion time with SHT=2,SSEL=2 (MCLK=1MHz) would be (16+12+1)*1usec=29usec. [Ref User Guide (SLAU144J) Fig 22-5]

    The sampling here is not paced by the ADC, but rather by the other work the MCU is doing -- I see some floating-point arithmetic and a couple of printf() calls for each conversion, which will add up to much more than the ADC time. I don't think I could make a reasonable estimate for how long all that takes.

    If you have a scope, the simplest measurement would be to adopt an unused GPIO pin and toggle it just before each conversion, then use the scope to measure the time between the edges.

    If you don't have a scope, you can capture e.g. TA1R just before each conversion and subtract the previous value (modulo TA1CCR0). I expect this value will be less than the TA1 time span (98.24 msec), so it should fit.

    Keep in mind that these timings, and thus the sample rate, will change every time you change anything in the code (or optimization level).

**Attention** This is a public forum