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.

ADC setting on TM4C123GH6PZ-LQFP100

I'm using TM4C123GH6PZ-LQFP100

In main.c, setting ADC

//The ADC0 and ADC1 peripheral must be enabled for use.

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);

// ADC0 is used with AIN0/PE3, AIN1/PE2.
// ADC1 is used with AIN6/PD5, AIN7/PD4, AIN19/PH3 
// GPIO port E, D and H needs to be enabled
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); 

// Select the analog ADC function for these pins.
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2 | GPIO_PIN_3); //AIN1, AIN0
GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); //AIN7, AIN6
GPIOPinTypeADC(GPIO_PORTH_BASE, GPIO_PIN_3); //AIN19

//set external Vrev
ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
ADCReferenceSet(ADC1_BASE, ADC_REF_EXT_3V);

ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceConfigure(ADC1_BASE, 1, ADC_TRIGGER_PROCESSOR, 1);

ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);

ADCSequenceStepConfigure(ADC1_BASE, 1, 0, ADC_CTL_CH6 );
ADCSequenceStepConfigure(ADC1_BASE, 1, 1, ADC_CTL_CH7 );
ADCSequenceStepConfigure(ADC1_BASE, 1, 2, ADC_CTL_CH19 | ADC_CTL_IE | ADC_CTL_END);

//Set Build in ADC convert average = 16
ADCHardwareOversampleConfigure(ADC0_BASE, 16); //Avg=16
ADCHardwareOversampleConfigure(ADC1_BASE, 16); //Avg=16

IntMasterEnable();

// Since sample sequence 1 is now configured, it must be enabled.
ADCSequenceEnable(ADC0_BASE, 1);
ADCSequenceEnable(ADC1_BASE, 1);

// Clear the interrupt status flag. This is done to make sure the
// interrupt flag is cleared before we sample.
ADCIntClear(ADC0_BASE, 1);
ADCIntClear(ADC1_BASE, 1);
//
ADCIntEnable(ADC0_BASE, 1);
ADCIntEnable(ADC1_BASE, 1);
//End ADC setting

...

//In timer subroutine

...

// Clear the ADC interrupt flag.
ADCIntClear(ADC0_BASE, 1);
ADCIntClear(ADC1_BASE, 1);

// Read ADC Value.
ADCSequenceDataGet(ADC0_BASE, 1, pui32BinADCValue); //Ain0, Ain1
ADCSequenceDataGet(ADC1_BASE, 1, pui32BinADC1Value); //Ain6, Ain7, Ain19

//Load ADC1 value
A = pui32BinADC1Value[0];
B = pui32BinADC1Value[1];
C = pui32BinADC1Value[2];
//...
I can get value from A and B, but C always read zero. all input have value when operation.

I don't know why Ain19 is no active in this setting.

  • Hello Lung,

    Is the read of the ADC Values being done in a single Interrupt routine or are they two separate interrupt routines for ADC0 and ADC1. Also can you check and confirm if ADCIntRegister function is being used in your code?

    Regards
    Amit
  • Yes, read ADC0 and ADC1 in one interrupt routine and process their values are also in same time.
    Ain19 is added in routine later, before that(no Ain19), the program is running properly.
    I guess, may I miss some init setting for Ain19.

  • Hello Lung,

    That is an incorrect method to handle the interrupt for each ADC. Note that each ADC controller has a separate interrupt line and thus requires to have a specific interrupt handler so that data is read only when the ADC conversion for that instance of the controller is completed.

    Regards
    Amit
  • This refer to ADC example in Tiwaware, I just move it from main to Timer0 interrupt routine. I have tried use ADC interrupt before but not success,
    so I continue use this method.
  • I think, I'm using polling method, it run in timer interrupt routine, 0.1sec once.

    Re-post the timer interrupt routine:
    ...
    //Enable ADC
    // Trigger the ADC conversion.
    ADCProcessorTrigger(ADC0_BASE, 1);
    ADCProcessorTrigger(ADC1_BASE, 1);

    // Wait for conversion to be completed.
    while(!ADCIntStatus(ADC0_BASE, 1, false))
    {
    }

    // Clear the ADC interrupt flag.
    ADCIntClear(ADC0_BASE, 1);
    ADCIntClear(ADC1_BASE, 1);

    // Read ADC Value.
    ADCSequenceDataGet(ADC0_BASE, 1, pui32BinADCValue); //Ain0, Ain1
    ADCSequenceDataGet(ADC1_BASE, 1, pui32BinADC1Value); //Ain6, Ain7, Ain19

    //Load ADC1 value
    A = pui32BinADC1Value[0];
    B = pui32BinADC1Value[1];
    C = pui32BinADC1Value[2];
    ...
    //end timer interrupt
  • Hello Lung

    Then what is interrupt being enabled for?

    Also even then you have an issue. If the ADC0 completes conversion while ADC1 is still converting you may end up with the same result

    Would suggest adding the following after the while loop to make sure both ADC's have completed conversion

    // Wait for conversion to be completed.
    while(!ADCIntStatus(ADC1_BASE, 1, false))
    {
    }

    Regards
    Amit
  • I solved the problem after changing the wait ADC conversion point to ADC1.

    Thank you Amit.

  • Hello Lung,

    Note that the conversion results "must" only be read when the interrupt status shows that all channels for the sequencer have been completed not based on anything other than it's own status.

    Regards
    Amit