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.

TM4C1231D5PZ: Multiple ADC sequences over both ADCs at the same time

Part Number: TM4C1231D5PZ

Hi

I am having some troubles using both ADC on the TM4C1231D5PZ.
Both ADC seem to be configured correctly and pinmuxing seems ok as well.
For some reason I am undable to read all channels.

I am using channel 0 - 11 and 20.
Channel 0 - 7 on ADC0, 8 - 11 + 20 on ADC 1.
The readout of channel 10 + 11 + 20 is 0 (while there certainly is some voltage on the pin after measuring it with a scope or multimeter)..
It is no 0'ish, it is just 0. 
Looks like the ADC does not do its job for some reason.

Both ADC are configured in sequence 0 and are using a ADC_TRIGGER_ALWAYS.
The processor is running at 80 mHz.

  • Hi,

      I'm not too sure why you would measure 0 on channel 10, 11 and 20. Can you do three experiments?

      1. Turn off ADC0. Only use ADC1 to measure 8-11 + 20. Will you get correct reading for 10, 11 and 20?

      2. Turn off ADC0. Only use ADC1 to measure three channels for 10, 11 and 20? What is the result. 

      3. Use ADC0 for only 8 - 11 + 20. What is the result?

  • Thanks for the quick reply.

    1. Doing so gives me the same output. Channel 10, 11 and 20 remain 0 while 8 and 9 have readouts.

    2. Using only channel 10, 11 and 20 gives me the read from 10 and 11

    3. Swapping ADC1 for ADC0, gives me correct readouts of the channels

  • Hi Ayrton,

      Thank you for gather these data points. 

      - Can you please share your code?

      - How do you configure the clock? I want to know if it is related to the below errata. 

      - Do you have another board that you can replicate the same problem?

      Sorry, can you try two more experiments as I have never come across a problem reporting as such?

      - Turn off ADC0 and only use ADC1. Use ADC1 to sample in this order 10, 11, 20, 8, 9 instead of 8, 9, 10, 11, 20. Will you still see 10, 11, 20 equal to 0 while 8 and 9 are sampled correctly?

      - Turn off ADC0 and only use ADC1. Use ADC1 to sample   10, 11, 20 in one sequencer (e.g. SS0) while sampling 8, 9 on another sequencer (eg. SS1) .  Will you still see 10, 11, 20 equal to 0 while 8 and 9 are sampled correctly?

  • Hi

    I added below code. This is only the ADC part of the code. 

    #define MAX_ADC0_CHANNELS       8
    #define MAX_ADC1_CHANNELS       5
    
    #define ADC_5V                  ADC_CTL_CH0
    #define ADC_3V3                 ADC_CTL_CH1
    #define ADC_2V5                 ADC_CTL_CH2
    #define ADC_1V8                 ADC_CTL_CH3
    #define ADC_1V5                 ADC_CTL_CH4
    #define ADC_1V2                 ADC_CTL_CH5
    #define ADC_1V1                 ADC_CTL_CH6
    #define ADC_3V3A                ADC_CTL_CH7
    #define ADC_12V                 ADC_CTL_CH8
    #define ADC_1V8A                ADC_CTL_CH9
    #define ADC_n5V                 ADC_CTL_CH10
    #define ADC_1V                  ADC_CTL_CH11
    #define ADC_1V8B                ADC_CTL_CH20
    
    struct adc_channel {
        uint32_t channel;
        int nominal_voltage_d;
        int nominal_voltage_a;
        int min_voltage;
        int max_voltage;
    };
    
    enum adc0_index {
        _5V,
        _1V,
        _1V8,
        _1V5,
        _1V2,
        _3V3,
        _2V5,
        _1V1
    };
    
    enum adc1_index {
        _3V3A,
        _12V,
        _1V8A,
        _n5V,
        _1V8B
    };
    
    const struct adc_channel adc0[] = {
        {ADC_5V,    _5V_DIGITAL,    _5V_ANALOG,        _5V_DIGITAL - _5V_DIFF,          _5V_DIGITAL + _5V_DIFF},
        {ADC_1V,    _1V_DIGITAL,    _1V_ANALOG,        _1V_DIGITAL - _1V_DIFF,          _1V_DIGITAL + _1V_DIFF},
        {ADC_1V8,   _1V8_DIGITAL,   _1V8_ANALOG,       _1V8_DIGITAL - _1V8_DIFF,        _1V8_DIGITAL + _1V8_DIFF},
        {ADC_1V5,   _1V5_DIGITAL,   _1V5_ANALOG,       _1V5_DIGITAL - _1V5_DIFF,        _1V5_DIGITAL + _1V5_DIFF},
        {ADC_1V2,   _1V2_DIGITAL,   _1V2_ANALOG,       _1V2_DIGITAL - _1V2_DIFF,        _1V2_DIGITAL + _1V2_DIFF},
        {ADC_3V3,   _3V3_DIGITAL,   _3V3_ANALOG,       _3V3_DIGITAL - _3V3_DIFF,        _3V3_DIGITAL + _3V3_DIFF},
        {ADC_2V5,   _2V5_DIGITAL,   _2V5_ANALOG,       _2V5_DIGITAL - _2V5_DIFF,        _2V5_DIGITAL + _2V5_DIFF},
        {ADC_1V1,   _1V1_DIGITAL,   _1V1_ANALOG,       _1V1_DIGITAL - _1V1_DIFF,        _1V1_DIGITAL + _1V1_DIFF},
    };
    
    const struct adc_channel adc1[] = {
       {ADC_3V3A,   _3V3A_DIGITAL,  _3V3A_ANALOG,      _3V3A_DIGITAL - _3V3A_DIFF,      _3V3A_DIGITAL + _3V3A_DIFF},
       {ADC_12V,    _12V_DIGITAL,   _12V_ANALOG,       _12V_DIGITAL - _12V_DIFF,        _12V_DIGITAL + _12V_DIFF},
       {ADC_1V8A,   _1V8A_DIGITAL,  _1V8A_ANALOG,      _1V8A_DIGITAL - _1V8A_DIFF,      _1V8A_DIGITAL + _1V8A_DIFF},
       {ADC_n5V,    _n5V_DIGITAL,   _n5V_ANALOG,       _n5V_DIGITAL - _n5V_DIFF,        _n5V_DIGITAL + _n5V_DIFF},
       {ADC_1V8B,   _1V8B_DIGITAL,  _1V8B_ANALOG,      _1V8B_DIGITAL - _1V8B_DIFF,      _1V8B_DIGITAL + _1V8B_DIFF},
    };
    
    void irq_handler()
    {
    	//handle IRQ
    }
    
    int setup_adc_sequence0(uint32_t adc_base,const struct adc_channel * adc_channels, int channels)
    {
        int i = 0;
    
        ADCClockConfigSet(adc_base, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_EIGHTH, 1);
    
        for(i = 0; i < channels; i++) {
            if(i != channels - 1)
                ADCSequenceStepConfigure(adc_base, 0, i,  adc_channels[i].channel);
            else
                ADCSequenceStepConfigure(adc_base, 0, i,  adc_channels[i].channel | ADC_CTL_IE | ADC_CTL_END);
        }
    
        ADCSequenceConfigure(adc_base, 0, ADC_TRIGGER ALWAYS, 3);
    
        ADCIntClear(adc_base, 0);
    	ADCSequenceEnable(adc_base, 0);
    
        ADCIntRegister(adc_base, sequence, irq_handler);
    	ADCIntEnable(adc_base, 0);
    
        return 0;
    }
    
    int setup_adc()
    {
        int i = 0;
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
    
        ADCReferenceSet(ADC0_BASE, ADC_REF_INT);
        ADCReferenceSet(ADC1_BASE, ADC_REF_INT);
    
        for(i = 0; i <= 5; i++)
            GPIOPinTypeADC(GPIO_PORTE_BASE, 0x01 << i);
    
        for(i = 4; i <= 7; i++)
            GPIOPinTypeADC(GPIO_PORTD_BASE, 0x01 << i);
    
        GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);
        GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_5);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7);
    
        setup_adc_sequence0(ADC0_BASE, adc0, MAX_ADC0_CHANNELS);
        setup_adc_sequence0(ADC1_BASE, adc1, MAX_ADC1_CHANNELS);
    
        return 0;
    }
    
    int main(void)
    {
        SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_OSC_INT);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    	
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC1);
    	
    	setup_adc();
    	
    	//do other stuff
    	
    	return 0;
    }
    

    Clock configuration is done in the code above.
    For the main clock I use  SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_OSC_INT); and the ADC is set with ADCClockConfigSet(adc_base, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_EIGHTH, 1);

    Tried it with already 3 boards all using TM4C1231D5PZ. All encounter the same issue.

    1. In this case, 10 and 11 are read correclty. the others are not.
    2. This I will have to try, I come on this when I have

  • Channel 0 - 7 on ADC0, 8 - 11 + 20 on ADC 1.

    This is not what I see on your code. 

    Based on what I see from your below code, the five channels for ADC1 are for 7, 8, 9, 10 and 20, not 8, 9, 10, 11, and 20. You are actually skipping CH11. I don't know if there are other issues in your code. 

    const struct adc_channel adc1[] = {
    {ADC_3V3A, _3V3A_DIGITAL, _3V3A_ANALOG, _3V3A_DIGITAL - _3V3A_DIFF, _3V3A_DIGITAL + _3V3A_DIFF},
    {ADC_12V, _12V_DIGITAL, _12V_ANALOG, _12V_DIGITAL - _12V_DIFF, _12V_DIGITAL + _12V_DIFF},
    {ADC_1V8A, _1V8A_DIGITAL, _1V8A_ANALOG, _1V8A_DIGITAL - _1V8A_DIFF, _1V8A_DIGITAL + _1V8A_DIFF},
    {ADC_n5V, _n5V_DIGITAL, _n5V_ANALOG, _n5V_DIGITAL - _n5V_DIFF, _n5V_DIGITAL + _n5V_DIFF},
    {ADC_1V8B, _1V8B_DIGITAL, _1V8B_ANALOG, _1V8B_DIGITAL - _1V8B_DIFF, _1V8B_DIGITAL + _1V8B_DIFF},
    };

    #define ADC_3V3A ADC_CTL_CH7
    #define ADC_12V ADC_CTL_CH8
    #define ADC_1V8A ADC_CTL_CH9
    #define ADC_n5V ADC_CTL_CH10
    #define ADC_1V ADC_CTL_CH11
    #define ADC_1V8B ADC_CTL_CH20

    I understand you are trying to use the for-loop to initialize ADC in a compact manner. However, in light of debugging your issue, I would suggest you literally configure the channels like below at least for right now. It may not be the most elegant way but it is much more readable. You might want to do the same for ADC0 as such. Can you repeat the same issue? 

    ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH8 ); // Channel 8 is the step 0 of SS0.
    ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH9 ); // Channel 9 is the step 1 of SS0.
    ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH10 ); // Channel 10 is the step 2 of SS0.
    ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH11 ); // Channel 11 is the step 3 of SS0.
    ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH20 | ADC_CTL_IE | ADC_CTL_END) // 

    On your line 73, why do you want to use ADC_CLOCK_RATE_EIGHTH to skip a sample? Why don't you remove this line for now? If you need to use it for whatever reason in your application perhaps add it back later after you understand what is causing the current problem. It is always a best practice to start with a simple configuration and then upgrade later.