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.

Compiler/TM4C1290NCPDT: Setup ADC

Part Number: TM4C1290NCPDT

Tool/software: TI C/C++ Compiler

Hi,

I want to setup the ADC to cyclic sampling, which creates an interrupt, when exceeding a limit once.  What already works, is the periodic sampling and generating an Interrupt. The desired interrupt for limits, I can't get running. I cannot find the proper samples for that purpose and I think the documentation is at least "minimalistic" . If i enable the LIMIT_CHECK (see below) I get an interrupt, but this is constantly triggered and the rest of the program is disturbed by this. It seems as if the Interrupt will not be cleared. Any help or hint is welcome.

What's the difference between ADCIntEnableEx(ADC_DEVICE_BASE, ADC_INT_DCON_SS0) and ADCComparatorIntClear( ADC_DEVICE_BASE,ADC_SEQUENCE) ?

Thanks in advance

Micky

#define ADC_SEQUENCE              0
#define ADC_SEQUENCE_PRIO         0
#define ADC_DEVICE_BASE           ADC0_BASE
#define SYSCTL_PERIPH_ADC_DEVICE  SYSCTL_PERIPH_ADC0
#define ADC_INPUT_PIN             GPIO_PIN_2
#define ADC_INPUT_PORT            GPIO_PORTK_BASE
#define ADC_OVERSAMPLING          64
#define ADC_DIGITAL_COMP          0
#define ADC_VAL_LOW               20
#define ADC_VAL_HIGH              750
#define ADC_COMP_RESET            1
#define ADC_CHANNEL               ADC_CTL_CH19
#define ADC_LAST_STEP             0           
#define ADC_INT_SRC               INT_ADC0SS0 
#define TIMER_ADCSRC_100MS        TIMER_A
#define TIMER_ADCSRC_10MS         TIMER_B
#define ADC_SEQUENCER_LEN         8           


vfnInitAdc() {
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC_DEVICE); ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL,24); GPIOPinTypeADC(ADC_INPUT_PORT, ADC_INPUT_PIN); IntDisable(ADC_INT_SRC); ADCIntDisable(ADC_DEVICE_BASE, ADC_SEQUENCE); ADCSequenceDisable(ADC_DEVICE_BASE, ADC_SEQUENCE ); ADCHardwareOversampleConfigure(ADC_DEVICE_BASE, ADC_OVERSAMPLING ); ADCSequenceConfigure(ADC_DEVICE_BASE, ADC_SEQUENCE, ADC_TRIGGER_TIMER, ADC_SEQUENCE_PRIO); #ifdef READ_VALUE ADCSequenceStepConfigure(ADC_DEVICE_BASE, ADC_SEQUENCE, ADC_LAST_STEP, ADC_CHANNEL | ADC_CTL_IE | ADC_CTL_END); #elif defined(LIMIT_CHECK) ADCSequenceStepConfigure(ADC_DEVICE_BASE, ADC_SEQUENCE, ADC_LAST_STEP, ADC_CHANNEL | ADC_CTL_CMP0 | ADC_CTL_END); #else #error "ADC Define READ_VALUE or LIMIT_CHECK " #endif ADCComparatorConfigure( ADC_DEVICE_BASE, ADC_DIGITAL_COMP, ADC_COMP_INT_HIGH_HONCE); ADCComparatorRegionSet(ADC_DEVICE_BASE, ADC_DIGITAL_COMP, ADC_VAL_LOW, ADC_VAL_HIGH); ADCComparatorReset(ADC_DEVICE_BASE, ADC_DIGITAL_COMP, ADC_COMP_RESET, ADC_COMP_RESET ); ADCIntClear(ADC_DEVICE_BASE, ADC_SEQUENCE); ADCIntClearEx(ADC_DEVICE_BASE,ADC_INT_DCON_SS0); ADCComparatorIntClear(ADC_DEVICE_BASE,ADC_SEQUENCE); ADCIntEnable(ADC_DEVICE_BASE, ADC_SEQUENCE); // //ADCIntEnableEx(ADC_DEVICE_BASE, ADC_INT_DCON_SS0); // ADCComparatorIntEnable( ADC_DEVICE_BASE,ADC_SEQUENCE); IntEnable(ADC_INT_SRC); TimerControlTrigger(TIMER_APP_BASE,TIMER_ADCSRC_10MS,true); ADCSequenceEnable(ADC_DEVICE_BASE, ADC_SEQUENCE); } volatile uint32_t uMax=0; volatile uint32_t uMin=4096; void vfnADCSeq0Handler(void) { ADCIntClearEx(ADC_DEVICE_BASE,ADC_INT_DCON_SS0); ADCIntClear(ADC_DEVICE_BASE,ADC_SEQUENCE); ADCComparatorIntClear( ADC_DEVICE_BASE,ADC_SEQUENCE); #ifdef READ_VALUE static uint32_t auADCValue[8]; ADCSequenceDataGet(ADC_DEVICE_BASE,ADC_SEQUENCE,auADCValue); // der interessante Wert ist nun in auADCValue[0] if (uMax<auADCValue[0]) uMax=auADCValue[0]; if (uMin>auADCValue[0]) uMin=auADCValue[0]; #else guLimit=1; ADCComparatorReset(ADC_DEVICE_BASE, ADC_DIGITAL_COMP, ADC_COMP_RESET, ADC_COMP_RESET ); //IntDisable(ADC_INT_SRC); #endif }

  • Hi Michael,

      Unfortunately, we don't have an example code using digital comparator.  You may be the first one in the last two years that I have come across using digital comparator mode. :-)

      Please see below example high hand operation. It looks like you are configuring for hysteresis Once on High Band. You also set the COMP1 and COMP0 to 750 and 20. 750 translates to about 0.18V and 20 is about 4.8mV. Is it possible that your input fluctuates frequently crossing the mid-band region which is between 750 and 20? Please also check the CIC register and CTC register in the register window.  This is the only way I can think of that can continuously trigger the interrupt. Do you have an input profile on your AIN pin? What if you widen the hysteresis or move your upper and lower limits up for experiment. Will you see any difference?

      

      Please see the source code for ADCIntClearEX and ADCIntClear. As you can see the ADCIntClearEX  will clear the specified flags while the ADCIntClear will only bit one of the sequencers. In another word, only one of the bits[3:0] in the ADCISC register.

    void
    ADCIntClear(uint32_t ui32Base, uint32_t ui32SequenceNum)
    {
        //
        // Check the arguments.
        //
        ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE));
        ASSERT(ui32SequenceNum < 4);
    
        //
        // Clear the interrupt.
        //
        HWREG(ui32Base + ADC_O_ISC) = 1 << ui32SequenceNum;
    }
    
    void
    ADCIntClearEx(uint32_t ui32Base, uint32_t ui32IntFlags)
    {
        //
        // Note: The interrupt bits are "W1C" so we DO NOT use a logical OR
        // here to clear the requested bits. Doing so would clear all outstanding
        // interrupts rather than just those which the caller has specified.
        //
        HWREG(ui32Base + ADC_O_ISC) = ui32IntFlags;

      

  • Hi Charles,

    thanks for your explanation.

    "Is it possible that your input fluctuates frequently crossing the mid-band region which is between 750 and 20?"

    See my code above: I've made an Min/Max observation for some seconds,  doing a continuous sampling,  which results in values between 230 and 590. Therefore I did setup the digital comperator with some margin and expected no trigger at all. As I do average the samples I'm not sure, if the averaged samples are fed into the digital comparator or the unaveraged. If the later is the case, this could explain the behavior in the way you did mention it. Is it that way?

    Thanks for your answer & regards

    Micky

  • Hi Micky,

      It is after the average. Please see below. In the vfnADCSeq0Handler can you single step and see if the corresponding flags are cleared. Please check flags in ADCISC register and ADCDCISC register.

      I will suggest you do an experiment. Force an fixed voltage between 20 and 750 but provides just one spike above 750. I just wanted to make sure in such circumstance you only get one interrupt provided that the corresponding flags are cleared after the ISR is entered. 

      

  • Hi Charles,

    If I increase the Upperlimit a bit, the comperator stays calm. I tried going down step by step. The result was: Either no trigger occurs or it triggers so often, that the interrupts flood the processor. The hardware I'm working on, was only made a bit with "on the fly". Perhaps the new stable hardware is a bit more robust, but I would expect, the spikes to hit the boarder once or twice a second, and then if lower, more often. I will check in one/two weeks or so and report.

    Regards

    Micky

  • Hi Micky,

      Thanks, so I think the digital comparator is working accordingly. Yes, please report back your findings in a week/two weeks or so if you have the data to share with the community. I will close the thread for now. But you can always reopen the thread by replying to the thread.