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.

TM4C123 - ADC Continuous Oversampling

Hi,


I would like to read two channels with Trigger_Always. The samples I have low prioritized. If I implement this as below, then the interrupt is triggered with the end of the second sample. It works. My problem is:
When the first sample is triggered(64x Oversampling), the second sample is not detected for 256us(1(250kHz/64)).
When the second sample is triggered(64x Oversampling),, the first sample for is not detected for 256us. How can I oversampling at the same time? (For your information: ADC0 is reserved and works with Processor_Trigger)

HWREG(ADC1_BASE + ADC_O_PC) = (ADC_PC_SR_250K);
ADCHardwareOversampleConfigure(ADC1_BASE, 64);
ADCIntRegister(ADC1_BASE, 2, adcget2_isr_continuous);
ADCSequenceConfigure(ADC1_BASE, 2, ADC_TRIGGER_ALWAYS, 2);
ADCSequenceStepConfigure(ADC1_BASE, 2, 0, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC1_BASE, 2, 1, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);


void adcget2_isr_continuous(void)
{
    uint32_t data[4];

    ADCIntClear(ADC1_BASE, 2);
    ADCSequenceDataGet(ADC1_BASE, 2, data);

    adc_data_004[(adcChannel_t)LARGE_ADC_20].adcValue = data[0];
    adc_data_004[(adcChannel_t)LARGE_ADC_7].adcValue = data[1];

    //Toggle output for test
    if(iopin_get(IOPIN_MASTER_SUPPLY_DISABLE) == true)
    {
        iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, false);
    }
    else
    {
        iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, true);
    }
}

Thank you.

  • Hello Veysel

    The sequencers in a single ADC instance are "sequenced" one after the other. If you wish to have them working in parallel then map it to the 2 ADC modules instead of mapping them to two sequencers in the same ADC.
  • Hello Amit,

    the other ADC module(ADC0) is already used and works with single-shot method (ADC_TRIGGER_PROCESSOR). 

    As far as I know, I can not use ADC_TRIGGER_PROCESSOR and ALWAYS_TRIGGER in one module at the same time. A module with different triggers can not be configured, right? Are the samples of a sequence processed one after the other? Are there other possibilities?

    Regards,

    Veysel

  • Hello Veysel

    Yes that is correct. The two cannot be mixed as the always trigger shall continuously utilize the ADC not leaving any conversion duration for Processor Trigger.

    Each Sequencer can however be configured by different triggers, but always trigger and another trigger must not be mixed. One solution however can be to use a timer to trigger and when processor trigger is required, to halt the timer for processor trigger.
  • Hello Amit, Hello Community,

    the solution with a Timer_Trigger is great. I put the two channels in different sequences (2 and 3). Unfortunately, I still have the following problem:

    Can I use the Timer_Trigger for hardware oversampling? I have the problem that the interrupt (IE_CTL | END_CTL) is always called and not after the 8 times (8x Oversampling)? Instead of 2 kHz I have 16kHz? It had worked with Always_Trigger. Here is my code section:

    TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC);
    TimerControlTrigger(TIMER3_BASE, TIMER_A, true);
    TimerLoadSet(TIMER3_BASE, TIMER_A, 1205/*(SysCtlClockGet() / 10000)*/); //20MHz each clock is 50nS.  Then 60.25uS/.050uS  =  1205 clock ticks.  (check 1205 * .050 = 60.25us)
    TimerEnable(TIMER3_BASE, TIMER_A);
    
    //......
    //......
    MAP_ADCHardwareOversampleConfigure(ADC1_BASE, 8/*4*/); /* Hardware Oversampling for ADC1 */

    Thank you.

  • Hello Veysel

    That is strange. The hardware oversampling should have worked. Can you try the same with just one sample sequencer and one timer? Does it still work at 16KHz instead of 2KHz? If it still does, please share a simplified code for testing.
  • Hello Amit,

    I have only one timer for the ADC module. Both sequences are located in the same module ADC1_BASE.
    It also does not work with a sequence. I still have 16kHz. Is the loadValue too small?
    Please check my code, thank you.
    void adc_init()
    {
    
    TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC); 
    TimerControlTrigger(TIMER3_BASE, TIMER_A, true); 
    TimerLoadSet(TIMER3_BASE, TIMER_A, 1205/*(SysCtlClockGet() / 10000)*/); //20MHz each clock is 50nS.  Then 60.25uS/.050uS  =  1205 clock ticks.  (check 1205 * .050 = 60.25us) 
    TimerEnable(TIMER3_BASE, TIMER_A); 
    
    
    MAP_ADCHardwareOversampleConfigure(ADC1_BASE, 8/*4*/); /* Hardware Oversampling for ADC1 
    MAP_ADCPhaseDelaySet(ADC1_BASE, ADC_PHASE_0); /* Set Phase Delay to 0 */
    ADCIntRegister(ADC1_BASE, 2, adcget2_isr_continuous); 
    MAP_ADCSequenceConfigure(ADC1_BASE, 2, ADC_TRIGGER_TIMER, 2);
    MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 0, sequenceArray[stepsPosition]->pinconfig->channel | ADC_CTL_IE | ADC_CTL_END);
    ADCIntRegister(ADC1_BASE, 3, adcget3_isr_continuous);
    MAP_ADCSequenceStepConfigure(ADC1_BASE, 3, 0, sequenceArray[stepsPosition]->pinconfig->channel | ADC_CTL_IE | ADC_CTL_END);
    MAP_ADCSequenceConfigure(ADC1_BASE, 3, ADC_TRIGGER_TIMER, 3);
    IntMasterEnable();
    
    
    ADCSequenceEnable(ADC1_BASE, 2);
    ADCSequenceEnable(ADC1_BASE, 3);
    ADCIntClear(ADC1_BASE, 2);
    ADCIntClear(ADC1_BASE, 3);
    ADCIntEnable(ADC1_BASE, 2);
    ADCIntEnable(ADC1_BASE, 3);
    
    }
    
    #define PERIODIC_TIME_100HZ    11    /* The smallest grid frequency is 47,50Hz -> 1/(47,50Hz*2) = 10,5ms */
    static timer1ms_t periodTime = 0;
    static uint16_t voltageAkkuMinMax[2];
    static uint16_t tempVoltageAkkuMinMax[2];
    static uint16_t voltagePackMinMax[2];
    static uint16_t tempVoltagePackMinMax[2];
    
    void adcget2_isr_continuous(void)
    {
        uint32_t data[4];
    
        ADCIntClear(ADC1_BASE, 2);
        ADCSequenceDataGet(ADC1_BASE, 2, data);
    
        if(timer1ms_isElapsed(periodTime + PERIODIC_TIME_100HZ))
        {
            //Stored valid value
            memcpy((uint8_t*)voltagePackMinMax, (uint8_t*)tempVoltagePackMinMax, sizeof(tempVoltagePackMinMax));
            //Reset temporary value
            tempVoltagePackMinMax[0] = 0x0FFF; // minimum pack adc value
            tempVoltagePackMinMax[1] = 0x0000; // maximum pack adc value
        }
    
        if(data[0] < tempVoltagePackMinMax[0])
        {
            tempVoltagePackMinMax[0] = data[0];
        }
        if(data[0] > tempVoltagePackMinMax[1])
        {
            tempVoltagePackMinMax[1] = data[0];
        }
    
        //Toggle pin for test
        iopin_init(IOPIN_MASTER_SUPPLY_DISABLE);
        if(iopin_get(IOPIN_MASTER_SUPPLY_DISABLE) == true)
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, false);
        }
        else
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, true);
        }
    }
    
    
    void adcget3_isr_continuous(void)
    {
        uint32_t data3[1];
    
        ADCIntClear(ADC1_BASE, 3);
        ADCSequenceDataGet(ADC1_BASE, 3, data3);
    
        if(timer1ms_isElapsed(periodTime + PERIODIC_TIME_100HZ))
        {
            //Stored valid value
            memcpy((uint8_t*)voltageAkkuMinMax, (uint8_t*)tempVoltageAkkuMinMax, sizeof(tempVoltageAkkuMinMax));
            //Reset temporary value
            tempVoltageAkkuMinMax[0] = 0x0FFF; // minimum akku adc value
            tempVoltageAkkuMinMax[1] = 0x0000; // maximum akku adc value
        }
    
        if(data3[0] < tempVoltageAkkuMinMax[0])
        {
            tempVoltageAkkuMinMax[0] = data3[0];
        }
        if(data3[0] > tempVoltageAkkuMinMax[1])
        {
            tempVoltageAkkuMinMax[1] = data3[0];
        }
    
        //Toggle pin for test
        iopin_init(IOPIN_MASTER_SUPPLY_DISABLE);
        if(iopin_get(IOPIN_MASTER_SUPPLY_DISABLE) == true)
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, false);
        }
        else
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, true);
        }
    }

  • Hello Amit,

    I have only one timer for the ADC module. Both sequences are located in the same module ADC1_BASE.
    It also does not work with a sequence. I still have 16kHz. Is the loadValue too small?
    Please check my code, thank you.
    void adc_init()
    {
    
    TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC); 
    TimerControlTrigger(TIMER3_BASE, TIMER_A, true); 
    TimerLoadSet(TIMER3_BASE, TIMER_A, 1205/*(SysCtlClockGet() / 10000)*/); //20MHz each clock is 50nS.  Then 60.25uS/.050uS  =  1205 clock ticks.  (check 1205 * .050 = 60.25us) 
    TimerEnable(TIMER3_BASE, TIMER_A); 
    
    
    MAP_ADCHardwareOversampleConfigure(ADC1_BASE, 8/*4*/); /* Hardware Oversampling for ADC1 
    MAP_ADCPhaseDelaySet(ADC1_BASE, ADC_PHASE_0); /* Set Phase Delay to 0 */
    ADCIntRegister(ADC1_BASE, 2, adcget2_isr_continuous); 
    MAP_ADCSequenceConfigure(ADC1_BASE, 2, ADC_TRIGGER_TIMER, 2);
    MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 0, sequenceArray[stepsPosition]->pinconfig->channel | ADC_CTL_IE | ADC_CTL_END);
    ADCIntRegister(ADC1_BASE, 3, adcget3_isr_continuous);
    MAP_ADCSequenceStepConfigure(ADC1_BASE, 3, 0, sequenceArray[stepsPosition]->pinconfig->channel | ADC_CTL_IE | ADC_CTL_END);
    MAP_ADCSequenceConfigure(ADC1_BASE, 3, ADC_TRIGGER_TIMER, 3);
    IntMasterEnable();
    
    
    ADCSequenceEnable(ADC1_BASE, 2);
    ADCSequenceEnable(ADC1_BASE, 3);
    ADCIntClear(ADC1_BASE, 2);
    ADCIntClear(ADC1_BASE, 3);
    ADCIntEnable(ADC1_BASE, 2);
    ADCIntEnable(ADC1_BASE, 3);
    
    }
    
    #define PERIODIC_TIME_100HZ    11    /* The smallest grid frequency is 47,50Hz -> 1/(47,50Hz*2) = 10,5ms */
    static timer1ms_t periodTime = 0;
    static uint16_t voltageAkkuMinMax[2];
    static uint16_t tempVoltageAkkuMinMax[2];
    static uint16_t voltagePackMinMax[2];
    static uint16_t tempVoltagePackMinMax[2];
    
    void adcget2_isr_continuous(void)
    {
        uint32_t data[4];
    
        ADCIntClear(ADC1_BASE, 2);
        ADCSequenceDataGet(ADC1_BASE, 2, data);
    
        if(timer1ms_isElapsed(periodTime + PERIODIC_TIME_100HZ))
        {
            //Stored valid value
            memcpy((uint8_t*)voltagePackMinMax, (uint8_t*)tempVoltagePackMinMax, sizeof(tempVoltagePackMinMax));
            //Reset temporary value
            tempVoltagePackMinMax[0] = 0x0FFF; // minimum pack adc value
            tempVoltagePackMinMax[1] = 0x0000; // maximum pack adc value
        }
    
        if(data[0] < tempVoltagePackMinMax[0])
        {
            tempVoltagePackMinMax[0] = data[0];
        }
        if(data[0] > tempVoltagePackMinMax[1])
        {
            tempVoltagePackMinMax[1] = data[0];
        }
    
        //Toggle pin for test
        iopin_init(IOPIN_MASTER_SUPPLY_DISABLE);
        if(iopin_get(IOPIN_MASTER_SUPPLY_DISABLE) == true)
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, false);
        }
        else
        {
            iopin_set(IOPIN_MASTER_SUPPLY_DISABLE, true);
        }
    }
    
    
    void adcget3_isr_continuous(void)
    {
        uint32_t data3[1];
    
        ADCIntClear(ADC1_BASE, 3);
        ADCSequenceDataGet(ADC1_BASE, 3, data3);
    
        if(timer1ms_isElapsed(periodTime + PERIODIC_TIME_100HZ))
        {
            //Stored valid value
            memcpy((uint8_t*)voltageAkkuMinMax, (uint8_t*)tempVoltageAkkuMinMax, sizeof(tempVoltageAkkuMinMax));
            //Reset temporary value
            tempVoltageAkkuMinMax[0] = 0x0FFF; // minimum akku adc value
            tempVoltageAkkuMinMax[1] = 0x0000; // maximum akku adc value
        }
    
        if(data3[0] < tempVoltageAkkuMinMax[0])
        {
            tempVoltageAkkuMinMax[0] = data3[0];
        }
        if(data3[0] > tempVoltageAkkuMinMax[1])
        {
            tempVoltageAkkuMinMax[1] = data3[0];
        }
    }

     

  • Hello Veysel

    The function TimerEnable(TIMER3_BASE, TIMER_A); must be called after the ADC is setup and enabled. Based on the fact that the system clock s 20MHz (as given in the comment) the timer would be working at 16KHz. This is sufficiently low.

    If you remove one of the sequencer then does it work as expected?
  • According to datasheet, if I set system clock 16 Mhz then only for 1msps setting, conversion time will be 1us.

    What will be conversion time if I set System clock 40 Mhz, 1msps setting..?? OR

    What will be conversion time if I set System clock 80 Mhz, 1msps setting..??

  • Hello Krishnat,

    Please top adding the same message on every post that you can find. If you have a real question here, open a new post.