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.

LP-MSPM0L1306: Incorrect ADC result after Re-enable Conversion. ADC is triggered by Comparator event.

Part Number: LP-MSPM0L1306
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi TI,

 

I am trying to use comparator output to trigger ADC sampling. This part works. But I need to disable the sampling at certain time during my application. When re-enable the sampling back, the adc samples incorrect result.

Here is how to replicate the problem on LP-MSPM0L1306.

 

Sysconfig(see attached photo):

Use PWM to generate 1khz, 50% duty cycle square wave at PA3

Set comparator to use PA26 as positive input, internal voltage reference as negative input. generate event signal with DL_COMP_EVENT_OUTPUT_EDGE to trigger ADC

Set ADC to event trigger, single conversion, disable repeat mode, sample PA15

Connect to comparator positive input and ADC channel.

 

Connect PA3, PA15, PA26 together on board

 

Run the code attached in debug mode, it should stop after 5 second, adc_raw buffer will be filled with 3300. This is correct because when ADC samples, PWM is at logic high.

 

#include "ti_msp_dl_config.h"
#include "main.h"


volatile uint16_t adc_raw[32];
volatile uint8_t debugCnt=0;

void record_ADC_res(){
    uint16_t res = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
    adc_raw[debugCnt]=res*3300/1023;
    debugCnt++;
    if(debugCnt>=32) {
        debugCnt=0;
        __BKPT();
    }
}
bool adcTriggered=false;
int main(void)
{
    SYSCFG_DL_init();
    for(uint16_t i=0;i<5000;i++){
        delay_cycles(32000);//1ms delay
    }
    DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
    DL_ADC12_enableConversions(ADC12_0_INST);
    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

    while (1) {
        if(adcTriggered){
            adcTriggered=false;

            record_ADC_res();
            //DL_COMP_disableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
            //delay_cycles(32*1500);
            //DL_COMP_clearEventsStatus(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
            //DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
            DL_ADC12_enableConversions(ADC12_0_INST);

        }

    }
}

void ADC12_0_INST_IRQHandler(void)
{
        switch(DL_ADC12_getPendingInterrupt(ADC12_0_INST))
        {
        case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
            adcTriggered=true;
            break;
        }
}

Then, uncomment the "delay_cycles(32*1500);". This simulate disabling the sampling because adc conversion will only be enabled after this delay.

When running the code, you can see the result sometimes become logic 0.

 

My question is:

  1. What cause the adc to sample the wrong value?
  2. How to configure the ADC, or comparator, or event correctly, so the sampling result will still be correct after  re-enable the sampling

Note that I cannot use PWM to trigger ADC, because PWM is just to simulate an external signal for easy troubleshooting.

I am using CCS 12.8.1, sysconfig 1.21.0, sdk 2.2.0.05

I appreciate your prompt response. Thank you!

  • Have you disable and re-enable the event? Actually I think you should observe the register directly.

    For example, use IO instead PWM to trigger(for test),

    1. after re-enable breakpoint first, observe the register
    2. then IO trigger,
    3. then breakpoint again, observe the register again
  • i have tried enable and disable event by line 33 and 35. the result is the same.
    i will try the IO method.
    is there any register i should pay extra attention too?
    all register can be seen from "registers" window right?

  • i have removed PWM, connect only PA15, PA26 together, a capacitor to ground to remove switch debouncing, and a switch to 3v3.

    both register value for adc and comp are observed

    first experiment 
    step 0: the breakpoint is at line37, i start debugging when switch is off(voltage is at 0V), but debugger still stop at line 37 somehow.

    step1: then i resume(F8), the program only stopped after i turn on the switch. changes are: ADC0_SVT_MEMRES[0], ADC0_SVT_FIFODATA, COMP0_STATE become high, ADC_CTRL0.ENC change from on to off

    step2: then i resume(F8), the program only stopped after until i turn off and on the switch a 2nd time. only slight change in ADC0_SVT_MEMRES[0], ADC0_SVT_FIFODATA

    step3: then i turn off and on the switch a 3rd time when program is still stoped, then resume(F8), program immediately stopped again, only slight change in ADC0_SVT_MEMRES[0], ADC0_SVT_FIFODATA.

    first experiment seems to prove that ADC is not automatically disabled even if the "repeat mode" tick box in sysconfig is unchecked.

    second experiment
    similar to first experiment, but with line 33, 35, 36 enabled, breakpoint change to line 35. step 0 to 3 produces the same result. 

    second experiment seems to prove that disable and clearing event does not stop the ADC from triggering

    looks like ADC just keep triggering no matter what

  • You need to change the trigger mode.

  • i changed trigger mode to "Valid trigger will step to next memory conversion register", the rest is the same with experiment 2. step 0 to step 3 produces the same result. anything else i can try?

  • Hi Yuhao, any update? 

  • Sorry for late reply, let me have a test and I will feedback soon.

    For your question, do you mean that you change the trigger mode but ADC is still keep triggering(without enable repeat mode)?

  • I have not changed the trigger mode. I just wish to disable "comparator event trigger ADC" for a while, and get the correct ADC result on the first sample after re-enable. what I see now is after I disable the event or adc conversion, ADC still falsely trigger.

  • Hi,

    I tested the launchpad with your code, but the test result looks good.

    #include "ti_msp_dl_config.h"
    //#include "main.h"
    
    
    volatile uint16_t adc_raw[32];
    volatile uint8_t debugCnt=0;
    
    void record_ADC_res(){
        uint16_t res = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
        adc_raw[debugCnt]=res*3300/1023;
        debugCnt++;
        if(debugCnt>=32) {
            debugCnt=0;
            //__BKPT(0);
        }
    }
    volatile bool adcTriggered=false;
    int main(void)
    {
        SYSCFG_DL_init();
    //    for(uint16_t i=0;i<5000;i++){
    //        delay_cycles(32000);//1ms delay
    //    }
        DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
        DL_ADC12_enableConversions(ADC12_0_INST);
        NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
        DL_ADC12_startConversion(ADC12_0_INST);
        while (1) {
            if(adcTriggered){
                adcTriggered=false;
    
                record_ADC_res();
                DL_COMP_disableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
                delay_cycles(32*1500);
                DL_COMP_clearEventsStatus(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
                DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE));
                DL_ADC12_enableConversions(ADC12_0_INST);
                DL_ADC12_startConversion(ADC12_0_INST);
            }
    
        }
    }
    
    void ADC12_0_INST_IRQHandler(void)
    {
            switch(DL_ADC12_getPendingInterrupt(ADC12_0_INST))
            {
            case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
                adcTriggered=true;
                break;
            default:
                break;
            }
    }
    

  • One modification in the code.

    volatile bool adcTriggered=false;

  • Here is my syscfg file. Use ''valid trigger will step to next memory conversion register''

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/comp_5F00_dac_5F00_to_5F00_timer_5F00_event.syscfg

  • it seems like you have uploaded the wrong sysconfig file. it does not contain any information about ADC.

    here is my project that replicate the bug. if you connect PA3, PA15, PA26 together, remove jumper on J1 and J12, no other external circuit component involved. run the project for 7 second, it should stop and shows the adc_raw record value that jump between 3300mV and 0V.

    in this project, i have implemented your advice of "volatile bool adcTriggered=false;" and  ''valid trigger will step to next memory conversion register''

    if our results are different, then maybe we can start troubleshooting on the hardware differences

    min_adc_debug.zip

  • https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/adc12_5F00_single_5F00_conversion.syscfg

  • Quick question, your event for COMP is 'Rising or falling edge of comparator output'. So for PWM, it will trigger ADC for not only rising edge, but also falling edge. If you connect ADC to PWM too, ADC will first sample PWM's high level(3.3V), then low level(0V), then high level again(3.3V)...

    Is that right?

  • no, it is triggered by "Rising or falling edge of comparator output (selected by IES bit)". in this case it is rising edge. if you remove the delay at line 67, you can see the system trigger consistently on rising edge

  • Yes I reproduce the problem in my board. It seems that when the event is disabled, comp still set the COMPIFG in RIS, and when calling the clearEventsStatus it did not work. So when you enable the comp event, it will trigger ADC immediately.

  • Let me check with my team about the root cause. I am not sure why ICLR register did not work. For a temporary workaround, do you think it is ok to disable the whole comp?

  • great to hear you are able to replicate the bug!
    can you recommend some disable function other than power down the whole comparator peripheral? because we have timing constraint 

  • For the issue, my team is working on it and we need some more time to find a better workaround. 

    And for your question, I think you can try to re-configure the mux for comparator rather than re-init the whole comparator. What do you think?

  • Please try the following steps to re-enable the COMP.

      • When COMP need to be enabled,
        • DL_COMP_setPublisherChanID(COMP_0_INST, 0); // remove the actual publisher
        • DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE)); // Enable the COMP events in IMASK
        • DL_COMP_enable(COMP_0_INST); // Enable the COMP module
        • DL_COMP_disableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE)); // Disable the COMP events by clearing in IMASK
        • DL_COMP_setPublisherChanID(COMP_0_INST, COMP_0_INST_PUB_CH); // configure the actual publisher
        • DL_COMP_enableEvent(COMP_0_INST, (DL_COMP_EVENT_OUTPUT_EDGE)); // Re-enable COMP events in IMASK
  • Thank you! it seems to work on the demo project. I will try it in the real project soon.