I am trying to PWM the red LED on a Stellaris LaunchPad, following the recipe in the datasheet p.706, taking a couple shortcuts from the Stellaris® Peripheral Driver Library. I cannot figure out why the LED doesn't glow. I expect a 50% duty cycle @ 5 kHz PWM. Does anybody see what I'm overlooking here?
EDIT:
In the mean while I narrowed the problem. If I include an extra line:
ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PWM);
at bullet 2 the program starts working. This is what I mean in my comments that the ROM calls are not very well documented as it is hard to identify which registers it actually writes.
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/cpu.c"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "inc/hw_sysctl.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.c"
#include <stdint.h>
#define LED_RED GPIO_PIN_1
int main() {
// Set system clock to 80 MHz using PLL and external 16 MHz crystal.
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
// Enable GPIO for LED.
ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF );
ROM_GPIOPinWrite( GPIO_PORTF_BASE , LED_RED , 0x00 );
ROM_GPIOPinTypeGPIOOutput( GPIO_PORTF_BASE , LED_RED );
// Enable timer peripheral.
ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 );
// the GP Timer module clock must be enabled before the registers can be programmed (see page 313 or page 330).
HWREG( SYSCTL_RCGCTIMER ) |= SYSCTL_RCGCTIMER_R0;
// There must be a delay of 3 system clocks after the Timer module clock is enabled before any Timer module registers are accessed.
ROM_SysCtlDelay( 1 );
// Configure output pin for PWM use.
ROM_GPIOPinConfigure( GPIO_PF1_T0CCP1 );
ROM_GPIOPinTypeTimer( GPIO_PORTF_BASE , LED_RED ); //ROM_GPIOPinTypePWM( GPIO_PORTF_BASE , LED_RED ); => No PWM units on board, the timers are used for PWM.
// LED_RED on PF1 is convenient.
// PF1: T0CCP1 => 16/32-Bit Timer 0 Capture/Compare/PWM 1. (muxed with: PB7)
// PWM 1 implies use of Timer B
// PWM Mode
// A timer is configured to PWM mode using the following sequence:
// 1. Ensure the timer is disabled (the TnEN bit is cleared) before making any changes.
ROM_TimerDisable( TIMER0_BASE , TIMER_B );
// 2. Write the GPTM Configuration (GPTMCFG) register with a value of 0x0000.0004.
HWREG( TIMER0_BASE + 0x000 ) = 0x00000004;
// 3.In the GPTM Timer Mode (GPTMTnMR) register, set the TnAMS bit to 0x1, the TnCMR bit to 0x0, and the TnMR field to 0x2.
HWREG( TIMER0_BASE + 0x004 ) |= TIMER_TBMR_TBAMS | TIMER_TBMR_TBMR_PERIOD;
// 4. Configure the output state of the PWM signal (whether or not it is inverted) in the TnPWML field of the GPTM Control (GPTMCTL) register.
HWREG( TIMER0_BASE + 0x00c ) |= 0; // TIMER_CTL_TAPWML
// 5. If a prescaler is to be used, write the prescale value to the GPTM Timer n Prescale Register (GPTMTnPR).
//HWREG( TIMER0_BASE + 0x038 ) = ...
// 6. If PWM interrupts are used, configure the interrupt condition in the TnEVENT field in the
// GPTMCTL register and enable the interrupts by setting the TnPWMIE bit in the GPTMTnMR
// register. Note that edge detect interrupt behavior is reversed when the PWM output is inverted
//HWREG( TIMER0_BASE + 0x00c ) |= ...
// 7. Load the timer start value into the GPTM Timer n Interval Load (GPTMTnILR) register.
HWREG( TIMER0_BASE + 0x02c ) = 16000 - 1; // 16000 @ 80MHz system clock makes 5 kHz PWM
// 8. Load the GPTM Timer n Match (GPTMTnMATCHR) register with the match value.
HWREG( TIMER0_BASE + 0x034 ) = 8000 - 1; // Defines duty cycle
// 9. Set the TnEN bit in the GPTM Control (GPTMCTL) register to enable the timer and begin generation of the output PWM signal.
HWREG( TIMER0_BASE + 0x00c ) |= TIMER_CTL_TBEN;
// In PWM Timing mode, the timer continues running after the PWM signal has been generated. The
// PWM period can be adjusted at any time by writing the GPTMTnILR register, and the change takes
// effect at the next cycle after the write.
while ( 1 ) {
}
}
Best Answer
I was writing to
GPTMTAMR
where I should be writing toGPTMTBMR
(bullet #3 in the comments). In other words I was writing a value to a timerA register where I should be using timerB. Added the final code as a simple proof of concept for PWM the red LED on Stellaris LaunchPad.