TM4C123G LaunchPad - PWM

From EdWiki

Lab 7: PWM

Pulse Width Modulation (PWM) is a method of digitally encoding analog signal levels. High-resolution digital counters are used to generate a square wave of a given frequency, and the duty cycle of that square wave is modulated to encode the analog signal.

Typical applications for PWM are switching power supplies, motor control, servo positioning and lighting control.


  • The TM4C123GH6PM has two PWM modules
  • Each PWM module consists of:
    • Four PWM generator blocks
    • A control block which determines the polarity of the signals and which signals are passed to the pins
  • Each PWM generator block produces:
    • Two independent output signals of the same frequency or
    • A pair of complementary signals with dead-band generation (for H-bridge circuit protection)
    • Eight outputs total


  • Configure the PWM outputs and frequency
    We will configure the pin (PD0) as M1PWM0. Any PWM output would have been acceptable, but this one happened to be right next to the Vcc and ground pins on the BoosterPack connector.
  • Add code to control a DC motor
  • Connect the DC motor to the LaunchPad
  • Test

Create Lab7 Project

Create a lab7 project with an empty main.c, a startup file and all necessary project and build options as described in the lab3 project. When the wizard completes, click the Expand icon.png next to lab7 in the Project Explorer pane to expand the project.

► Open main.c and add (or copy/paste) the following lines to the top of the file:

  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include "inc/hw_memmap.h"
  4. #include "inc/hw_types.h"
  5. #include "driverlib/sysctl.h"
  6. #include "driverlib/gpio.h"
  7. #include "driverlib/debug.h"
  8. #include "driverlib/pwm.h"
  9. #include "driverlib/pin_map.h"
  10. #include "inc/hw_gpio.h"

hw_mwmmap: Macros defining the memory map of the Tiva C Series device. This includes defines such as peripheral base address locations such as GPIO_PORTF_BASE

hw_types: Defines common types and macros

sysctl.h: Defines and macros for System Control API of DriverLib. This includes API functions such as SysCtlClockSet and SysCtlClockGet.

gpio.h: Defines and macros for GPIO API of DriverLib. This includes API functions such as GPIOPinTypePWM and GPIOPinWrite.

pwm.h: Defines the PWM functions.

Pin_map.h: Mapping of peripherals to pins for all parts. (In this example: GPIOPinConfigure function)


  1. int main( void )
  2. {
  4. }

Inside the main function setup the clock

  • System clock Divider: 5
  • Use PLL or OSC.
  • Select External Frequency: here it is 16 MHz.
  • Configure the system clock to run using a 16MHz crystal on the main oscillator, driving the 400MHz PLL. The 400MHz PLL oscillates at only that frequency, but can be driven by crystals or oscillators running between 5 and 25MHz. There is a default /2 divider in the clock path and we are specifying another /5, which totals 10. That means the System Clock will be 40MHz.

Setup the PWM Clock

The PWM module is clocked by the system clock through a divider, and that divider has a range of 2 to 64. By setting the divider to 1, it will run the PWM clock at the same rate as the system clock i.e 40 MHz.

SysCtlPWMClockSet( SYSCTL_PWMDIV_64 );

It can be divided by 1, 2, 4, 8, 16, 32 and 64. For example, if it is divided by 64, then the PWM clock is set at 625 KHz. (40MHz/64)

Enable the system peripherals

First we enable the PWM peripheral, where we select PWM0 module. Then we enable GPIO pins. PD0 is M1PWM0

SysCtlPeripheralEnable( SYSCTL_PERIPH_PWM1 );
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );

Configure the PWM Pin on GPIO Port D Pin 0.

Select the Pin Type for PWM:

GPIOPinConfigure( GPIO_PD0_M1PWM0 );

M1PWM0 corresponds to Motion Control Module 1 PWM 0. This signal is controlled by Module 1 PWM Generator 0.


This function is used to set the mode of operation for a PWM generator which can be counting mode, synchronization mode, also a PWM generator can count in two different modes: countdown mode or count up/down mode.



This function sets the period of the specified PWM generator block, where the period of the generator block is defined as the number of PWM clock ticks between pulses on the generator blocks zero. In this case, we set the period to 2500.

Set the PWM period to 250Hz. To calculate the appropriate parameter, use the following equation:

N = (1 / f) * PWMClk.  

Where N is the function parameter, f is the desired frequency, and PWMClk is the PWM clock frequency. In this case you get: (1 / 250Hz) * 625KHz = 2500 cycles.

PWMGenPeriodSet( PWM1_BASE, PWM_GEN_0, 2500 );


This function sets the pulse width for the specified PWM output, where the pulse width is defined as the number of PWM clock ticks.

PWMPulseWidthSet( PWM1_BASE, PWM_OUT_0, PWMGenPeriodGet(PWM1_BASE,PWM_GEN_0) / 2 );

For period/2, we get 50% Duty cycle. For period/4, we get 25% Duty Cycle. Division by 1.3 gives us a 75% Duty Cycle approximately.

We use PWMGenPeriodGet function to calculate the period of the specified PWM generator block, or you can simply write 64000 as the period, like how we have defined it in the previous step. This function is useful when the PWM period has not been defined.

We are enabling the selected PWM output signal (true).

PWMOutputState( PWM1_BASE, PWM_OUT_0_BIT, true );

This function allows the PWM clock to drive the timer/counter for the specified generator block.


Source Code

Your final code should look something like this:

  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include "inc/hw_memmap.h"
  4. #include "inc/hw_types.h"
  5. #include "driverlib/sysctl.h"
  6. #include "driverlib/gpio.h"
  7. #include "driverlib/debug.h"
  8. #include "driverlib/pwm.h"
  9. #include "driverlib/pin_map.h"
  10. #include "inc/hw_gpio.h"
  12. int main( void )
  13. {
  16.     SysCtlPWMClockSet( SYSCTL_PWMDIV_64 );
  17.     SysCtlPeripheralEnable( SYSCTL_PERIPH_PWM1 );
  18.     SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );
  21.     GPIOPinConfigure( GPIO_PD0_M1PWM0 );
  23.     PWMGenConfigure( PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN );
  24.     PWMGenPeriodSet( PWM1_BASE, PWM_GEN_0, 2500 );     //Total Pulse Period
  26.     PWMPulseWidthSet( PWM1_BASE, PWM_OUT_0,  ( PWMGenPeriodGet(PWM1_BASE, PWM_GEN_0) / 2) ); 
  27.     PWMOutputState( PWM1_BASE, PWM_OUT_0_BIT, true );
  28.     PWMGenEnable( PWM1_BASE, PWM_GEN_0 );
  30.     while( 1 ) {
  31.         ;
  32.     }
  33. }

► Open main.c and copy/paste the above code.

INCLUDE Path, Driverlib, Debug Config

► Link the TivaWare libdriver.a file to your project
► Add the INCLUDE search paths for the header files
Configure CCS Debugger

It’s been quite a while since we configured our workspace and verified all the settings that are needed to find the libraries, resolve the symbols and allow the compiler and linker to work.

PATH Variables

► Right-click on lab7 in the Project Explorer and select Properties. Expand the Resource category on the left and click on Linked Resources. Make sure that the symbol TIVAWARE_INSTALL is in the Path Variables list as shown below:

This symbol was created when you imported vars.ini.

Include Search Path

► On the left of the Build Properties window click on
Build → GNU Compiler → Directories Options. Verify that ${TIVAWARE_INSTALL} is in the include search path as shown below:

Build Symbols

► On the left of the Build Properties window click on
Build → GNU Compiler → Symbols, and assure that PART_TM4C123GH6PM and TARGET_IS_BLIZZARD_RB1 are listed as shown below. If it isn’t, click the add button for top pane and add PART_TM4C123GH6PM and TARGET_IS_BLIZZARD_RB1 as the define symbols as shown below. Please follow this link to add new Symbols.

These names are required in order for the pin map to select the correct pins when configured and to link to the correct ROM location for ROM-coded API’s. Click OK to close the Properties window.

TARGET_IS_BLIZZARD_RB1 = Blizzard is the internal TI product name for the device family on your LaunchPad. This symbol will give the libraries access to the proper API’s in ROM


► Click the Debug button to build and download your program to the TM4C123GH6PM memory.

► Connect the ground part of probe to GND on the board and Positive part of the probe to PD0.