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.

MSP430FR6043: ADC conversion start trigger

Part Number: MSP430FR6043
Other Parts Discussed in Thread: MSP430WARE,

Tool/software:

Hello,

I want to start the ADC conversion for every 1seconds.Instead of continuous conversion. After conversion, the ADC should go to sleep.

  1. Sampling Time 1ms
  2. ACD12_B clock is ACLK 32Khz
  3. I am sensing the data from two ADC channel (A8 and A14) (Sequence of channel)

Is there any driverlib example available for this.

I found the below screenshot in the Datasheet, Could please explain me the below data.

Thanks in advance,

Sarwath

  • Hi Sarwath,

    Thanks for the question! I think a good starting point for what you are trying to do would be the msp430fr6043_adc12_11 example within the MSP430Ware 3.80.14.01 SDK. This example has the timer code so you can adjust this to trigger the ADC sampling every second. There are also some examples in this SDK that provide code for placing the MCU in low power modes, sampling multiple ADC channels, etc.  

    With respect to the data in the chart, this is showing the different available external trigger source connections for the ADC. You can also use a software-based trigger which is the first one on the table. 

    -Brian 

  • Hi Brian Dempsey,

    Thanks for your response.

    I went through the msp430fr6043_adc12_11 example, and I made a similar setup in my ADC application.

    I am running the ADC and Timer_A1 with an ACLK of 32 kHz.

    ADC Setup:

    Fadcclock=32Khz

    1 cycle = 31.25us

    "My sampling time is 1 ms, so I am setting ADC12_B_CYCLEHOLD_32_CYCLES in the ADC12_B_setupSamplingTimer function

    void adcSetup()
    {
        /***** adc hw setup ******/
        adc_init.clockSourceSelect = ADC12_B_CLOCKSOURCE_ACLK;
        adc_init.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
        adc_init.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
        adc_init.internalChannelMap = ADC12_B_NOINTCH;
        adc_init.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_4;
    
        /*****  sc bat channel A8 setup ******/
        memory_init1.memoryBufferControlIndex = ADC12_B_MEMORY_0;
        memory_init1.inputSourceSelect = ADC12_B_INPUT_A8;
        memory_init1.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
        memory_init1.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;
        memory_init1.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
        memory_init1.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    
        /***** bat inv channel A14 setup ******/
        memory_init2.memoryBufferControlIndex = ADC12_B_MEMORY_1;
        memory_init2.inputSourceSelect = ADC12_B_INPUT_A14;
        memory_init2.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
        memory_init2.endOfSequence = ADC12_B_ENDOFSEQUENCE;
        memory_init2.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
        memory_init2.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    
        /***** adc initialization ******/
        ADC12_B_init(ADC12_B_BASE, &adc_init);
    
        /***** adc sampling timer ******/
        ADC12_B_setupSamplingTimer(ADC12_B_BASE, ADC12_B_CYCLEHOLD_32_CYCLES,
                                   ADC12_B_CYCLEHOLD_4_CYCLES,
                                   ADC12_B_MULTIPLESAMPLESENABLE);
    
        /***** configuring Memory 0 ******/
        ADC12_B_configureMemory(ADC12_B_BASE, &memory_init1);
    
        /***** configuring Memory 1 ******/
        ADC12_B_configureMemory(ADC12_B_BASE, &memory_init2);
    
        /***** clear adc interrupt ******/
        ADC12_B_clearInterrupt(ADC12_B_BASE, 0, 0);
    
        /***** enable adc interrupt on memory 1 ******/
        //ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE1, 0, 0);
    
        /***** enable adc ******/
        ADC12_B_enable(ADC12_B_BASE);
    
        /***** start conversion ******/
        ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0,
                                ADC12_B_SEQOFCHANNELS);
    
    
    }

    Timer A1 Setup:

    FtimerA1 clock: 32Khz/8 : 4Khz

    One cycle is 250 µs. I want to generate a 10-second ISR. Every 10 seconds, the ADC starts the conversion in the Timer_A1 ISR, and I am reading the ADC digital conversion data through polling

    void timerSetup()
    {
        TA1CCTL0 = CCIE;
        TA1CCR0 = 40000-1;                       // PWM Period
        TA1CCTL1 = OUTMOD_3;                    // TACCR1 set/reset
        TA1CCR1 = 39999;                         // TACCR1 PWM Duty Cycle
        TA1CTL = TASSEL__ACLK|ID__8| MC__UP;         // ACLK, up mode
    }
    
    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void Timer1_A0_ISR (void){
        /**** enable adc *****/
        ADC12_B_enable(ADC12_B_BASE);
    
        /***** start conversion *****/
        ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0,
                                ADC12_B_SEQOFCHANNELS);
    }

    At runtime, I am getting ADC data for the first conversion only. If I change the voltage, the ADC data remains the same (previous data).

    how to find out the ADC conversion time. Is there any formulae available

    Thanks in advance,

    Sarwath

  • You appear to be mixing modes here: startConversion starts a conversion using ADC12SC (as though ADC12SHS=0), but by setting ADC12SHS=4, the timer is also triggering a conversion. 

    A conversion takes (sample_time + 13*adc_clock_period), or roughly (1ms + 13 * 32usec), or about 1.4ms. Since the timer trigger happens (8*32usec)=~250usec before the timer interrupt, it is highly probable that the ADC is still running when startConversion starts it again. This (plus your symptom) suggests you're tripping over Erratum ADC42, where triggering a new conversion while a previous conversion is active stalls the ADC [Ref Errata (SLAZ715B) p. 5]. 

    Given the code you've shown, the simplest/smallest change is probably to keep the startConversion call in the ISR, but switch to ADC12_B_SAMPLEHOLDSOURCE_0 (software trigger). 

  • Hello Bruce McKenney,

    I have made the changes in the code as per the above suggestion.

    1. ADC conversion trigger: ADC12_B_SAMPLEHOLDSOURCE_SC

    void adcSetup()
    {
        /***** adc hw setup ******/
        adc_init.clockSourceSelect = ADC12_B_CLOCKSOURCE_ACLK;
        adc_init.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
        adc_init.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
        adc_init.internalChannelMap = ADC12_B_NOINTCH;
        adc_init.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;
    
        /*****  sc bat channel A8 setup ******/
        memory_init1.memoryBufferControlIndex = ADC12_B_MEMORY_0;
        memory_init1.inputSourceSelect = ADC12_B_INPUT_A8;
        memory_init1.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
        memory_init1.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;
        memory_init1.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
        memory_init1.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    
        /***** bat inv channel A14 setup ******/
        memory_init2.memoryBufferControlIndex = ADC12_B_MEMORY_1;
        memory_init2.inputSourceSelect = ADC12_B_INPUT_A14;
        memory_init2.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
        memory_init2.endOfSequence = ADC12_B_ENDOFSEQUENCE;
        memory_init2.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
        memory_init2.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    
        /***** adc initialization ******/
        ADC12_B_init(ADC12_B_BASE, &adc_init);
    
        /***** adc sampling timer ******/
        ADC12_B_setupSamplingTimer(ADC12_B_BASE, ADC12_B_CYCLEHOLD_32_CYCLES,
                                   ADC12_B_CYCLEHOLD_4_CYCLES,
                                   ADC12_B_MULTIPLESAMPLESENABLE);
    
        /***** configuring Memory 0 ******/
        ADC12_B_configureMemory(ADC12_B_BASE, &memory_init1);
    
        /***** configuring Memory 1 ******/
        ADC12_B_configureMemory(ADC12_B_BASE, &memory_init2);
    
    }

    2. ADC start conversion in 10 Seconds Timer1_A0_ISR trigger.

    void timerSetup()
    {
        TA1CCTL0 = CCIE;
        TA1CCR0 = 40000-1;                       // PWM Period
        TA1CCTL1 = OUTMOD_3;                    // TACCR1 set/reset
        TA1CCR1 = 39999;                         // TACCR1 PWM Duty Cycle (39999 cycles is 10seconds)
        TA1CTL = TASSEL__ACLK|ID__8 | MC__UP;         // ACLK, up mode
    }
    
    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void Timer1_A0_ISR (void){
    
       /**** enable adc *****/
        ADC12_B_enable(ADC12_B_BASE);
    
        /**** start conversion *****/
        ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_START_AT_ADC12MEM0,
                                ADC12_B_SEQOFCHANNELS);
    }

    In my application, I am using ADC12_B_SEQOFCHANNELS instead of ADC12_B_REPEATED_SEQOFCHANNELS. The ADC conversion starts in the Timer ISR and completes after the conversion time. To initiate the next conversion, the ADC must wait for the Timer ISR to trigger it again.

    My concern is about the wait time between conversions: during this wait time, will the ADC enter auto shutdown mode? In my application, I am also utilizing Low Power Mode 3 (LPM3) to conserve energy.

    Thank You!

  • Yes, it will auto-powerdown between bursts. [Erratum ADC65 applies only within bursts, and so doesn't really matter when you use ADC12_B_MULTIPLESAMPLESENABLE.]

    If you want to be very sure, you could call ADC12_B_disableConversions() within your ADC completion ISR, which will set ADC12ENC=0.  Your later ADC12_B_startConversion() will set ADC12ENC=1 for you.

  • 1.Will it go to auto auto-powerdown when I use ADC12_B_MULTIPLESAMPLESENABLE.

    2. Yeah, I understand your point. After the ADC conversion is complete and the ISR is triggered, I will read the data and then disable the ADC conversion. In my 10-second Timer ISR, I will enable the ADC conversion. Is it better to use ADC12_B_disableConversions to disable the ADC conversion, or is ADC12_B_disable a better option?

  • 1) Yes, once the burst is done -- at that point it has done everything it was asked to do.

    2) ADC12_B_disable sets ADC12ON=0. (It also sets ADC12ENC=0, which saves you a step.) I don't know if setting ADC12ON=0, or for that matter ADC12ENC=0, will save you anything measurable (I haven't measured it). On the other hand, if you're only doing this once per 10 seconds, this might be considered "cheap insurance" (emphasis on "cheap"). Just don't forget to call ADC12_B_enable (ADC12ON=1) when you come back, since startConversion won't.

**Attention** This is a public forum