Professional Documents
Culture Documents
Eq. (2.1)
ECEN 403 Mini Project Part 3 PWM Page 4 of 7
Fig. 2.1. Basic PWM and duty cycle.
Exercise 2.1: Drive a PWM output using different duty cycles
In this exercise we will be setting set up four PWMs with configurable duty cycles
(20%, 60%, 40% and 80%).
/*
* main.c - PWM Lab
*
* Note from the datasheet:
* In PWM mode, timers are configured as 24-bit or 48-bit down-counter with assigned
start value (corresponding to period) defined by GPTMTnILR and GPTMTnPR registers.
*/
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
int main(void)
{
unsigned long ulPeriod; // sets the period, and thus frequency, of our PWM
unsigned long dutyCycle1, dutyCycle2, dutyCycle3, dutyCycle4;
// Configures to drive 400 MHz PLL by sys_clk -> 16 MHz xtal
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAI
N); //Set clock speed = 40MHz
/* Configure specific GPIO pins to use the CCP pins associated with certain
timers.
* More info about GPIO pin options in Table 10-2 of Datasheet.
**/
// Enable the GPIO ports where our CCP GPIO pins are
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // Enable the GPIO port
containing the T0 CCP0 and CCP1 pins
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // Enable port F, containing T1
CCP0, CCP1
/* Reference: DataSheet - 1.3.4.4 CCP Pins (under Architectural Overview)
ECEN 403 Mini Project Part 3 PWM Page 5 of 7
* CCP Pins can be used by GPTM (see Lab 4 in the workbook) to time/count
external events with CCP pin as input. GPTM can also generate a PWM output on CCP
pin.
* For PWM, the GPTM is incremented (or decremented) by system clock. The
PWM signal (which is output) is generated based on match between counter value and
value stored in match register.
*/
// Configure pins PB6, PB7 as Timer_0 CCP0, CCP1
// Configure pins PF2, PF3 as Timer_1 CCP0, CCP1
GPIOPinConfigure(GPIO_PF2_T1CCP0); // Configure pin PF2 as Timer 1_A output
GPIOPinConfigure(GPIO_PF3_T1CCP1); // Configure pin PB3 as Timer 1_B output
GPIOPinConfigure(GPIO_PB6_T0CCP0); // Configure pin PB6 as Timer 0_A output
GPIOPinConfigure(GPIO_PB7_T0CCP1); // Configure pin PB7 as Timer 0_B output
/* Note that if you get errors here, you may have to replace the named terms
for actual hex address, found in header file. */
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_2 ); // Enable pin PF2 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_3 ); // Enable pin PF3 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6 ); // Enable pin PB6 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_7 ); // Enable pin PB7 as output of
timer addressed to it
// SysCtlClockGet() will give you the number of clock cycles in 1 second. This
is convenient for directly converting to clock frequency division, as one second
corresponds to one Hertz.
ulPeriod = (SysCtlClockGet() / 500)/2;
dutyCycle1 = (unsigned long)(ulPeriod-1)*0.8;
dutyCycle2 = (unsigned long)(ulPeriod-1)*0.6;
dutyCycle3 = (unsigned long)(ulPeriod-1)*0.4;
dutyCycle4 = (unsigned long)(ulPeriod-1)*0.2;
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); // Enable Timer 1
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // Enable Timer 0
// Configure the timers as split 16-bit pairs, and set each timer as PWM mode.
TimerConfigure(TIMER1_BASE,
(TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM));
TimerConfigure(TIMER0_BASE,
(TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM));
TimerControlLevel(TIMER1_BASE, TIMER_BOTH, 0); // Timer 1 is trigger low
TimerControlLevel(TIMER0_BASE, TIMER_BOTH, 0); // Timer 0 is trigger low
// For simplicity, we don't use PWM interrupts, for which we would need to
configure the TnEVENT field in GPTMCTL and eanble
// For simplicity, we don't use prescaler load and match set here.
// If we do use prescaler, the API functions would write value to GPTM Timer n
Prescale Reg (GPTMTnPR)
ECEN 403 Mini Project Part 3 PWM Page 6 of 7
// These API functions load the timer start value into Timer n Interval Load
Reg (GPTMTnILR) Reg 10, 11
// Timer 0 Load set
TimerLoadSet(TIMER1_BASE, TIMER_A, ulPeriod -1);
TimerLoadSet(TIMER1_BASE, TIMER_B, ulPeriod -1);
// Timer 0 Load set
TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
TimerLoadSet(TIMER0_BASE, TIMER_B, ulPeriod -1);
// These API functions load the match value into Timer n Match register
(GPTMTnMATCHR)
// Timer 1 Match set
TimerMatchSet(TIMER1_BASE, TIMER_A, dutyCycle1);
TimerMatchSet(TIMER1_BASE, TIMER_B, dutyCycle2);
// Timer 0 Match set
TimerMatchSet(TIMER0_BASE, TIMER_A, dutyCycle3);
TimerMatchSet(TIMER0_BASE, TIMER_B, dutyCycle4);
/* Timers are now configured. */
// Finally, enable the timers, which will now run (API functions will set TnEN
bit in Reg 4 (GPTMCTL)
TimerEnable(TIMER1_BASE, TIMER_BOTH);
TimerEnable(TIMER0_BASE, TIMER_BOTH);
// Continuous while loop, and Timers will be counting in PWM mode
while(1)
{
}
}
Question: Explain the purpose of each header file given in the code.
First Project
Complete Lab 5: ADC12 in the Stellaris Workshop Manual (see required
documents) and successfully demonstrate MCU temperature in degrees Fahrenheit.
You do not need to demonstrate Hardware averaging and Calling APIs from ROM
(i.e. complete all 29 steps outlined in the lab). You can also find a video lecture on
the lab on: http://www.youtube.com/watch?v=XqNAALjC5-k
ECEN 403 Mini Project Part 3 PWM Page 7 of 7
Second Project
This project is essentially an extension of the First project. Similar to the first
project, you will store the ADC values from the data provided by the on-chip
temperature sensor. However, you will instead use interrupts rather than burn CPU
cycles waiting for the ADC conversion to complete (aka the better way
mentioned in step 19 from Lab 5:ADC12 in the Stellaris Launchpad workbook).
Third Project
You will configure the ADC0 module for a single sample from a sine wave or
square wave input source from the function generator. The input waveform will be
sampled by the ADC through a GPIO pin.
Additionally, print out both the raw ADC12 values and the voltage readings in mV
in a UART terminal via PuTTy or a similar program. Note: mV requires no
decimal points. Courtesy: Lucas Kimble
(Extreme Hints: To do this you will configure the GPIO pin specifically as an input
to the ADC i.e. reference gpio.h and gpio.c. You will also need to select the proper
input in your ADC API function calls.)
Fourth Project
Complete the PWM based Exercise 2.1 and answer the question immediately
following it.
Fifth Project
This project will be based on what you have learned and made in this and the
previous lab. Using clocks, timers, interrupts and ADCs generate an output PWM
signal and modulate its duty cycle according to the values input from your ADC.
Restrict your PWM duty cycle to 25% - 75%. To do this, you will need to convert
your ADC readout before setting it as duty cycle.
BONUS!! :- Additionally, use your ADC readout to drive four LED color states.
The lowest 25% of the ADC input voltage range will correspond to a Red LED.
The next quartile will correspond to a Green LED, the third quartile will
correspond to a Blue LED and the last quartile will correspond to a combination of
multiple LEDs. You can choose any LED colors you like (look up Figure 13-9 for
the voltage conversion chart). Courtesy: Arnold Zhang