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.

TM4C123GE6PM: ADC multi channel interrupt

Part Number: TM4C123GE6PM

Hi, This is Namha. 

I have an issue implementing the multi-channel ADC interrupt function.

I would like to use two ADC interrupt handlers using timer0 and 1.

(ADC sampling frequency :1Mhz)

But ADC0SS3IntHandler only works and ADC1SS3IntHandler does not work.

ADC initialization and handler code are attached below. Is it a setting problem or another problem? 

//--------------------------------------- ADC initialization -----------------------------------------------// 

void ADCInit(void)
{
//Initialize ADC
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); //ADC peripheral
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

//Pins used for ADC channels
ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0);

// *** ADC
ROM_ADCReferenceSet(ADC0_BASE,ADC_REF_INT);
ROM_ADCReferenceSet(ADC1_BASE,ADC_REF_INT);
ROM_ADCSequenceConfigure(ADC0_BASE,3,ADC_TRIGGER_TIMER,0);
ROM_ADCSequenceConfigure(ADC1_BASE,3,ADC_TRIGGER_TIMER,3);
ROM_ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQUENCE_NUMBER, 0, ADC_CTL_D | ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);
ROM_ADCSequenceStepConfigure(ADC1_BASE, ADC_SEQUENCE_NUMBER, 0, ADC_CTL_D | ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
ROM_ADCSequenceEnable(ADC0_BASE, ADC_SEQUENCE_NUMBER);
ROM_ADCSequenceEnable(ADC1_BASE, ADC_SEQUENCE_NUMBER);
//ROM_ADCHardwareOversampleConfigure(ADC0_BASE, txLeakageOversamplingNumber);
//ROM_ADCHardwareOversampleConfigure(ADC1_BASE, txLeakageOversamplingNumber);

// *** Timer0
ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
samplePeriod = ROM_SysCtlClockGet()/(1000*ADC_MAX_SAMPLING_RATE);
ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, samplePeriod - 1); // sampling frequency 1Mhz
ROM_TimerControlTrigger(TIMER0_BASE, TIMER_A, true);

// *** Timer1
ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, samplePeriod - 1); // sampling frequency 1Mhz
ROM_TimerControlTrigger(TIMER1_BASE, TIMER_A, true);

// *** Interrupts
ROM_IntEnable(INT_TIMER0A);
ROM_IntEnable(INT_TIMER1A);
ROM_TimerIntEnable(TIMER0_BASE,TIMER_TIMA_TIMEOUT);
ROM_TimerIntEnable(TIMER1_BASE,TIMER_TIMA_TIMEOUT);
ROM_IntEnable(INT_ADC0SS3);
ROM_IntEnable(INT_ADC1SS3);
ROM_ADCIntEnable(ADC0_BASE,ADC_SEQUENCE_NUMBER);
ROM_ADCIntEnable(ADC1_BASE,ADC_SEQUENCE_NUMBER);

ROM_IntMasterEnable();
ROM_TimerEnable(TIMER0_BASE,TIMER_A);
ROM_TimerEnable(TIMER1_BASE,TIMER_A);

}

//--------------------------------------------------------- Handler -------------------------------------------------------------------//

void Timer0IntHandler(void)
{
ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}

void Timer1IntHandler(void)
{
ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
}

void ADC0SS3IntHandler(void)
{
ROM_ADCIntClear(ADC0_BASE,3);

ADC0Value[0] = 0;

ROM_ADCSequenceDataGet(ADC0_BASE,3,ADC0Value); // Get Data from ADC and store it in ADC1Value
adcRawData_0[ADCCurrentIndex_0] = *ADC0Value;
ADCCurrentIndex_0++;

if(ADCCurrentIndex_0 >= 2048)
{
ADCCurrentIndex_0 = 0;
}

}

void ADC1SS3IntHandler(void)
{
ROM_ADCIntClear(ADC1_BASE,3);
ADC1Value[0] = 0;

ROM_ADCSequenceDataGet(ADC1_BASE,3,ADC1Value); // Get Data from ADC and store it in ADC1Value
adcRawData_1[ADCCurrentIndex_1] = *ADC1Value;
ADCCurrentIndex_1++;

if(ADCCurrentIndex_1 >= 2048)
{
ADCCurrentIndex_1 = 0;
}

}

Thank you.

  • There is only one trigger signal from the timers to the ADCs. Enabling the trigger from two timers will trigger both ADCs twice. I suspect that you are constantly in the interrupt routine for ADC0 and never have time to service ADC1. If you want both ADC to convert at the same rate and at the same time, just use one timer. You might also need to lower the sample rate until you determine you have enough CPU time to fully handle each interrupt cycle before the next one comes.
  • Hi, Bob.
    Thanks for your reply.
    I tried using one timer. the two handlers were worked as you advised.
    But However, the sample frequency operates only at 640Khz or less and does not operate at frequencies higher than that. And the ADC0 handler operated at the correct frequency, but the ADC1 handler did not work at frequencies above 330KHz. Is it not possible for two ADC handlers to operate above Hz?

    best regards,
    Namha
  • I suspect that the problem is you cannot process the data as fast as you at collecting it. I have attached a project in a .zip file that does simultaneous conversions on 2 channels at 1M samples/second. To do this, I use the uDMA to read the two ADCs. Even when buffering 1000 conversions it takes 80% of the CPU time to do a simple average of the 2000 samples (1000 from each ADC) before then next samples are complete. (Use the "File" "Import" function of CCS to add this project to your CCS workspace.)

    /cfs-file/__key/communityserver-discussions-components-files/908/ADCwDMA2.zip

    Here is a logic analyzer shot showing the execution time. Signal PD2 is high while the CPU is idle and low while it is computing the averages. PD3 is high while computing the average of one of the ADC0 buffers.

  • Hello, Bob
    Thank you for your efforts.
    Your advice has helped me a lot.
    I can not use DMA for any reason.
    But with your advice, I used a single Timer Trigger to get a sampling frequency of 450kHz using two ADC modules.

    Thanks again.

    Best Regards,
    Namha Lee