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.

EK-TM4C123GXL: Having trouble understanding the workings of the sample sequencer

Part Number: EK-TM4C123GXL
Other Parts Discussed in Thread: EK-TM4C1294XL

Tool/software:

Hello, I'm working on a project using the sample sequencer and am having a little trouble understanding the operations. My understanding is that:

  • the sample sequencer (e.g. SS0) will sample the analog pins designated via MUXn in the ADCSSMUXn register until it reaches the end of sequence as defined by an END bit defined in ADCSSCTL0.
  • the TPTR and HPTR indicate where the head and tail of the circular buffer and I expect these to be upto and including the MUXn value corresponding to the end of sequence

However, I'm seeing the head and tail going beyond what I have defined as the end of sequence. Here is my ADC module configuration code:

//Macro Definitions:
/* Ports used in project*/
#define PORT_D 3
#define PORT_E 4
#define PORT_F 5

/* Pins used in project*/
#define PD0 0
#define PD1 1
#define PD2 2
#define PD3 3

#define PE0 0
#define PE1 1
#define PE2 2
#define PE3 3

#define PF0 0
#define PF1 1
#define PF2 2
#define PF3 3

/********* CONFIGURE THE PORT TO BE USED AS AN ADC INPUT *********/
    // Configure Port E3 (AIN0) as input sensor using ADC
    SYSCTL->RCGCADC |= (1U << 0); /* enable ADC0 module */

    SYSCTL->GPIOHBCTL |= (1U << PORT_E); /* enable AHB for GPIOE */
    SYSCTL->RCGCGPIO  |= (1U << PORT_E); /* enable Run mode for GPIOE */

    GPIOE_AHB->AFSEL |= ((1 << PE3) | (1 << PE1)); /* configure PE1 & PE3 as alternate function - this pin can only be ADC input */

    GPIOE_AHB->DEN &= ~( (1 << PE3) | (1 << PE1)); /*clear bit to configure PE1 & PE3 as analog*/
    GPIOE_AHB->AMSEL |= ((1 << PE3) | (1 << PE1)); /* for pin PE1 & PE3: analog function of the pin is enabled, the isolation is disabled, and the pin is capable of analog functions */

    /********* CONFIGURE SAMPLE SEQUENCER FOR APPLICATION USAGE *********/

    //First disable all the sequencer for programming
    ADC0->ACTSS &= 0xFFFFFFF0UL;

    uint32_t MUX0 = 0x0;  // mux0 assigned to AIN0
    uint32_t MUX1 = 0x2;  // mux1 assigned to AIN2

    ADC0->EMUX |= 0x0000000FUL;  // make ADC0 always sample TODO: update sampling scheme to be more efficient
    ADC0->SSMUX0 |= ( (MUX1 << 4)  | ((MUX0 << 0)) ) ;  // configure lowest byte for mux0 and mux1 assignments, leave all other mux's unchanged)
    ADC0->SSCTL0 |= (1U<<5);  // configure end sampling after the first sample
    ADC0->IM &= 0xFFF0FFF0UL;  // disable all interrupt/triggers

    //Enable the SS0 after programming is finished (only using SS0)
    ADC0->ACTSS |= 0x00000001UL;

Here is the register view to confirm the configuration is as expected for the sequencer:

Here is the head and tail pointer at a point in time (in this instance to me it seems like it is sampling MUX7):

Hoping someone can help clarify my understanding of the ADC module

  • Hi,

      Is there a strong reason to code in DRM (Direct Register Manipulation) style? TivaWare SDK has peripheral drivers to easily configure the ADC sequencer. There are ADC examples in the SDK to help you started. 

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\adc

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\adc_udma_pingpong  

    If you must use DRM to write your code, you can reference the peripheral driver source code on how the registers are configured. The ADC driver can be found at C:\ti\TivaWare_C_Series-2.2.0.295\driverlib\adc.c. Refer to the ADCSequenceStepConfigure() and it should answer you questions on how TPTR, HPTR and ADCSSMUXn are configured. 

    Below would be a simple code sequence using the peripheral driver to sample four ADC channels (AIN0, AIN2 and AIN3, Internal Temp Sensor) using Sample Sequencer 0 (SS0). 

        //Onboard ADC Configuration to read 3 external analog inputs on pins 13,14,15 and internal temperature
        //read on sequence 0 with highest priority
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_3);
    
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0))
        {
        }
        //ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0); //Base, SequenceNum, Trigger, Priority
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); //Base, SequenceNum, Trigger, Priority
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, (ADC_CTL_CH1)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, (ADC_CTL_CH2)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, (ADC_CTL_CH3)); //Base, SequenceNum, Step, Config
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, (ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END)); //Base, SequenceNum, Step, Config
        ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
        ADCSequenceEnable(ADC0_BASE, 0); //Base, SequenceNum

  • Hi Charles, thanks a lot for your prompt response. I was able to use your suggestion to clarify for myself some of my questions. 

    As for why use DRM -> I'm trying to learn the embedded aspects of MCUs (mostly worked on the application side of things thus far) and for me the best way to learn is to throw myself into the deep end and struggle through it. I felt that if I used the driver library I wouldn't be able to learn as much even though it would make life easier for development.