Notes of PhiL    About    Categories    Tags    Archive    Feed    GitHub Repo

UT.6.03x Embedded Systems - Shape the World - Lab 14: Analog-Digital Conversion (ADC)


After a long time gone, I’m finally back. Today, I’m going to show how Analog-Digital Conversion (ADC) works.



The range of our EK-TM4C123GXL is 3.3 Volts.

For example, \( \Delta V = \frac{ Range }{ Precision } = \frac{ 3\;Volts\;-\;0\;Volts }{ 2^{ 12 } } = 0.7\;millivolts \). Any change in voltage greater than 0.7 mV is detectable.


The first 5 steps are GPIO configuration. The next 6 steps are actually ADC initialization. In this lab, I’ll use PE2 as the ADC port.

  1. Enable the port clock
  SYSCTL_RCGC2_R    |= 0x10;
  delay              = SYSCTL_RCGC2_R;
  GPIO_PORTE_LOCK_R |= 0x4C4F434B;
  GPIO_PORTE_CR_R   |= 0x04;
  1. Make input by writing zero to the DIR register
    GPIO_PORTE_DIR_R &= ~0x04;

  2. Enable the alternate function by writing one to the AFSEL register
    GPIO_PORTE_AFSEL_R |= 0x04;

  3. Disable the digital function by writing zero to the DEN register
    GPIO_PORTE_DEN_R &= ~0x04;

  4. Enable the analog function by writing one to the AMSEL register
    GPIO_PORTE_AMSEL_R |= 0x04;

  5. Enable the ADC clock by setting bit 16 of the SYSCTL_RCGC0_R register

  SYSCTL_RCGC0_R |= 0x10000;
  delay           = SYSCTL_RCGC0_R;
  1. Bits 8 and 9 of the SYS_CTL_RCGC0_R register specify the maximum sampling rate of the ADC. Configure the speed as the following:
    0x03 ~> 1M samples/second
    0x02 ~> 500K samples/second
    0x01 ~> 250K samples/second
    0x00 ~> 125K samples/second
    In this lab, I choose 125 samples/second:
    SYSCTL_RCGC0_R &= ~0x300;

  2. Set the priority of the four sequencers by a 2-bit number
    Because there are 4 sequencers, there are 2 bits in the number of priority. The smaller the number is, the more priority it will be.
    In this lab, I choose priority 0:
    ADC0_SSPRI_R &= ~0x3000;

  3. Disable the sequencer before configuration by writing a zero to bit 3 (ASEN3) of the ADC_ACTSS_Rregister
    ADC0_ACTSS_R &= ~0x08;

  4. Choose the trigger in the ADC_EMUX_R register. Note that, to use a software trigger instead of hardware, write zeros to bits 15-12 (EM3) of the trigger. Also, I use software trigger in this lab – SysTick:
    ADC0_EMUX_R &= ~0xF000;

  5. Configure the corresponding input source in the ADC_SSMUX3_R register (Choosing the channel). There are 12 channels, going from 0 through 11.
    I choose Ain channel 1:
    ADC0_SSMUX3_R |= 0x01;

  6. Set flags on ADC_SSCTL3_R register:
    Bit 3: TS0 - “Temperature”
    Bit 2: IE0 - “Flag”
    Bit 1: END0 - “this is the last sample in sequence”
    Bit 0: D0 - “use differential mode”
    In this case, I set TS0 = 0, IE0 = 1, END0 = 1, and D0 = 0
    ADC0_SSCTL3_R |= 0x06;

  7. Enable the sample sequencer (I chose 3 so I need to open 3) again after setting up by writing ADC0_ACTSS_R |= 0x08;


  1. Initiate SS3 by writing a 1 to PSSI[3]
    ADC0_PSSI_R |= 0x08;

  2. Wait until the conversion is done by looping at RIS[3]
    while ((ADC0_RIS_R & 0x08) == 0) {};

  3. Read data from FIFO masking with 12-bit binary
    result = ADC0_SSFIFO3_R & 0xFFF;

  4. Clear the flag by writing one to ISC[3] to start capturing another sample
    ADC0_ISC_R |= 0x08;

  5. Return the value read from FIFO
    return result;

Important Formula:

In this lab, we use 12-bit ADC as well as 3.3V EK-TM4C123GXL


ADC process is called sampling because we process 1 bit at a time. So, there must be a finite time, Δt, between conversions.If we use SysTick periodic interrupts, then this Δt is the time between SysTick interrupts. We define sampling rate as:

If this information oscillates at frequency f, then according to Nyquist Theorem, we must sample that signal at


Lab 14 is simple and straightforward. It only focuses on ADC. Using a potentiometer, convert the resistor of it into different numbers on the screen. That’s it!






Pin 3 of the potentiometer will go into 3.3V; pin 1 will go into GND; pin 2 will go into PE2. Note that the pinouts of various potentiometers may be different.



Note that to be able to run and grade the labs, you have to follow the software requirements. Unfortunately, the software and the course don’t support Linux. However, if you follow the official instruction from Texas Instruments, you can upload and run your program on the LaunchPad.

See below for my code in adc.c, or view all files of this lab on my GitHub.

 * UTAustinX: UT.6.03x Embedded Systems - Shape the World
 * Lab 14: Analog-Digital Conversion
 * File Name: adc.c
 * Description: Provides functions that initializes ADC0 SS3 to be triggered by
 * software and trigger a conversion, wait for it to finish,
 * and return the result
 * Author: Phi Luu
 * Location: Portland, Oregon, United States
 * Created: May 07, 2016
 * Updated: June 23, 2017

#include "adc.h"
#include "tm4c123gh6pm.h"

 * Sets up the ADC.
 * Max sample rate: <= 125,000 samples/second
 * SS3 triggering event: software trigger
 * SS3 1st sample source: channel 1
 * SS3 interrupts: enabled but not promoted to controller
void InitAdcChannel0(void) {
    volatile unsigned long delay;

    // GPIO Port E Initialization:
    SYSCTL_RCGC2_R     |= 0x10;           // enable port E clock
    delay               = SYSCTL_RCGC2_R; // allow time for clock to start
    GPIO_PORTE_LOCK_R  |= 0x4C4F434B;     // unlock GPIO port E
    GPIO_PORTE_CR_R    |= 0x04;           // allow change to PE2;
    GPIO_PORTE_DIR_R   &= ~0x04;          // PE2 input
    GPIO_PORTE_AFSEL_R |= 0x04;           // enable alternate function on PE2
    GPIO_PORTE_PCTL_R   = 0;              // disable PCTL on port E
    GPIO_PORTE_DEN_R   &= ~0x04;          // disable digital I/O on PE2
    GPIO_PORTE_AMSEL_R |= 0x04;           // enable analog function on PE2
    // Analog Initialization:
    SYSCTL_RCGC0_R |= 0x10000;            // enable the ADC clock
    delay           = SYSCTL_RCGC0_R;     // allow time for clock to start
    SYSCTL_RCGC0_R &= ~0x300;             // configure for 125K samples/second
    ADC0_SSPRI_R   &= ~0x3000;            // Highest Priority = 0
    ADC0_ACTSS_R   &= ~0x08;              // disable sample sequencer 3
    ADC0_EMUX_R    &= ~0xF000;            // use software trigger - SysTick
    ADC0_SSMUX3_R  |= 0x01;               // choose Ain channel 1
    ADC0_SSCTL3_R  |= 0x06;               // clear TS0, D0; set IE0, END0
    ADC0_ACTSS_R   |= 0x08;               // enable sample sequencer 3

 * Busy-wait Analog-Digital Conversion (ADC)
 * @return    12-bit result of ADC
unsigned long AdcChannel0In(void) {
    unsigned long result;

    ADC0_PSSI_R |= 0x08; // initiate SS3

    // wait until conversion is done:
    while ((ADC0_RIS_R & 0x08) == 0) {}
    result      = ADC0_SSFIFO3_R & 0xFFF; // mask with 12-bit binary
    ADC0_ISC_R |= 0x08;                   // clear the flag to start capturing another sample
    return result;                        // return the value of result