You are on page 1of 14

LPC2148 PWM Programming

In this tutorial, we are going to discuss the PWM module of LPC2148. First, we will see how to
configure the PWM registers to generate signals of required PWM, at the end, we will see how to
use the Explore Emdedded PWM library.

LPC2148 PWM Module


LPC2148 has 6 PWM output pins which can be used as 6-Single edged or 3-Double edged.
There as seven-match registers to support these 6-PWM output signals. Below block diagram
shows the PWM pins and the associated Match (Duty Cycle) registers.

PWM Port Pin Functions Associated PINSEL Corresponding Match


Channel Pin Register Register

PWM_1 P0.0 0-GPIO, 1-TXD0, 2- 0,1 bits of PINSEL0 PWMMR1


PWM1,

PWM_2 P0.7 0-GPIO, 1-SSEL0, 2- 14,15 bits of PWMMR2


PWM2, 3-EINT2 PINSEL0

PWM_3 P0.1 0-GPIO, 1-RXD0, 2- 2,3 bits of PINSEL0 PWMMR3


PWM3, 3-EINT0

PWM_4 P0.8 0-GPIO, 1-TXD1, 2- 16,17 bits of PWMMR4


PWM4, PINSEL0

PWM_5 P0.21 0-GPIO, 1-PWM5, 2- 10,11 bits of PWMMR5


CAP1.3, PINSEL1

PWM_6 P0.9 0-GPIO, 1-RXD1, 2- 18,19 bits of PWMMR6


PWM6, 3-EINT3 PINSEL0
LPC2148 PWM Registers
The below table shows the registers associated with LPC2148 PWM.

Register Description

PWMIR Interrupt Register: The IR can be read to identify which of eight possible interrupt
sources are pending. Writing Logic-1 will clear the corresponding interrupt.

PWMTCR Timer Control Register: The PWMTCR is used to control the Timer Counter
functions (enable/disable/reset).

PWMTC Timer Counter: The 32-bit TC is incremented every PR+1 cycles of PCLK. The
PWMTC is controlled through the PWMTCR.

PWMPR Prescaler Register: This is used to specify the Prescaler value for incrementing the
PWMTC.

PWMPC Prescale Counter: The 32-bit PC is a counter which is incremented to the value
stored in PR. When the value in PR is reached, the TC is incremented.

PWMMCR Match Control Register: The PWMMCR is used to control the reseting of PWMTC
and generating of interrupt whenever a Match occurs.

PWMMR0 Match Register: This register hold the max cycle Time(Ton+Toff).

PWMMR1- Match Registers: These registers holds the Match value(PWM Duty) for
PWMMR6 corresponding PWM channels(PWM1-PWM6).

PWMPCR PWM Control Register: PWM Control Register. Enables PWM outputs and selects
PWM channel types as either single edge or double edge controlled.

PWMLER Load Enable Register: Enables use of new PWM values once the match occurs.
Register Configuration
The below table shows the registers associated with LPC2148 PWM.

PWMTCR

31:4 3 2 1 0

Reserved PWM Enable Reserved Counter Reset Counter Enable

Bit 0 – Counter Enable


This bit is used to Enable or Disable the PWM Timer and PWM Prescalar Counters
0- Disable the Counters
1- Enable the Counter incrementing.

Bit 1 – Counter reset


This bit is used to clear the PWM Timer and PWM Prescaler Counter values.
0- Do not Clear.
1- The PWM Timer Counter and the PWM Prescale Counter are synchronously reset on the next
positive edge of PCLK.

Bit 3 – PWM Enable


Used to Enable or Disable the PWM Block.
0- PWM Disabled
1- PWM Enabled

PWM
MCR

31:21 20 19 18 - 5 4 3 2 1 0

Reserv PWM PWMM PWM - PWM PWMM PWM PWM PWMM PWM
ed MR6S R6R MR6I MR1S R1R MR1I MR0S R0R MR0I
PWMMRxI
This bit is used to Enable or Disable the PWM interrupts when the PWMTC matches PWMMRx
(x:0-6)
0- Disable the PWM Match interrupt
1- Enable the PWM Match interrupt.

PWMMRxR
This bit is used to Reset PWMTC whenever it Matches PWMRx(x:0-6)
0- Do not Clear.
1- Reset the PWMTC counter value whenever it matches PWMRx.

PWMMRxS
This bit is used to Stop the PWMTC,PWMPC whenever the PWMTC matches PWMMRx(x:0-
6).
0- Disable the PWM stop o match feature
1- Enable the PWM Stop feature. This will stop the PWM whenever the PWMTC reaches the
Match register value.

PWMPCR

31:15 14-9 8-7 6-2 1-0

Unused PWMENA6-PWMENA1 Unused PWMSEL6-PWMSEL2 Unused

PWMSELx
This bit is used to select the single edged and double edge mode form PWMx (x:2-6)
0- Single Edge mode for PWMx
1- Double Edge Mode for PWMx.

PWMENAx
This bit is used to enable/disable the PWM output for PWMx(x:1-6)
0- PWMx Disable.
1- PWMx Enabled.

PWMLER

31-7 6 5 4 3 2 1 0

Unused LEN6 LEN5 LEN4 LEN3 LEN2 LEN1 LEN0


LENx
This bit is used Enable/Disable the loading of new Match value whenever the PWMTC is
reset(x:0-6)
PWMTC will be continously incremented and whenever it reaches the PWMMRO, timer will be
reset depeding on PWMTCR configuraion. Once the Timer is reset the New Match values will
be loaded from MR0-MR6 depending on bits set in this register.
0- Disable the loading of new Match Values
1- Load the new Match values from MRx when the timer is reset.

PWM Working
After looking into the PWM registers, its time to see how the LPC1768 PWM module works.

The TC is continuously incremented and once it matches the MR1(Duty Cycle) the PWM pin is
pulled Low. TC still continues to increment and once it reaches the Cycle time(Ton+Toff) the
PWM module does the following things:

 Reset the TC value.


 Pull the PWM pin High.
 Loads the new Match register values.
Summary of PWM operations for the above image:
 Slide1: The TC is being incremented as per the Pre-scalar configuration. The PWM output is
high as the TC is still less that duty cycle.
 Slide2: TC is incremented to 40 and still the PWM pin as HIGH.
 Slide3: TC is incremented to 60 and it matches the Duty Cycle(MR1=60).
 Slide4: Now the Comparator1(Green) will trigger the R of SR latch and Pulls the PWM
output to Zero(Q=0). TC still continues to increment.
 Slide5: TC is incremented to 80 and PWM pin is low as TC>Duty Cycle.
 Slide6: Now TC is 100 and it matches the Cycle time(MR0==100).
 Slide7: Now the Comparator2(Red) will trigger the S of SR latch and pulls the PWM output
to ONE(Q==1). It also resets the TC to zero. It updates Shadow buffers with new Match
values from MRO,MR1.

Steps to Configure PWM


1. Configure the GPIO pins for PWM operation in respective PINSEL register.
2. Configure TCR to enable the Counter for incrementing the TC, and Enable the PWM
block.
3. Set the required pre-scalar value in PR. In our case it will be zero.
4. Configure MCR to reset the TC whenever it matches MR0.
5. Update the Cycle time in MR0. In our case it will be 100.
6. Load the Duty cycles for required PWMx channels in respective match registers MRx(x:
1-6).
7. Enable the bits in LER register to load and latch the new match values.
8. Enable the required pwm channels in PCR register.

Example
Program to demonstrates the variable PWM signal generation on PWM_1-
PWM_4(P0_0,P0_7,P0_1,P0_8).
Connect the Leds to the pins P0_0,P0_7,P0_1,P0_8 and observe the led brigthness change
depending on the dutycycle.
#include <lpc214x.h>
#include "stdutils.h"
#include "systemInit.h"

void delay_ms(unsigned int ms)


{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<50000;j++);
}

#define SBIT_CNTEN 0
#define SBIT_PWMEN 3

#define SBIT_PWMMR0R 1

#define SBIT_LEN0 0
#define SBIT_LEN1 1
#define SBIT_LEN2 2
#define SBIT_LEN3 3
#define SBIT_LEN4 4

#define SBIT_PWMENA1 9
#define SBIT_PWMENA2 10
#define SBIT_PWMENA3 11
#define SBIT_PWMENA4 12

#define PWM1_PINSEL 0 //P0_0 (0-1 Bits of PINSEL0)


#define PWM2_PINSEL 14 //P0_7 (14-15 Bits of PINSEL0)
#define PWM3_PINSEL 2 //P0_2 (2-3 Bits of PINSEL0)
#define PWM4_PINSEL 16 //P0_8 (16-17 Bits of PINSEL0)
int main(void)
{
int dutyCycle;
SystemInit();

/* Cofigure pins(P0_0, P0_7, P0_1, P0_8) for PWM mode. */


PINSEL0 = (2<<PWM1_PINSEL) | (2<<PWM2_PINSEL) | (2<<PWM3_PINSEL) | (2<<PWM4_PINSEL);

PWMPR = 0x00; /* No Prescalar */


PWMMCR = (1<<SBIT_PWMMR0R); /*Reset on PWMMR0, reset TC if it matches MR0 */

PWMMR0 = 100; /* set PWM cycle(Ton+Toff)=100) */


PWMMR1 = 50; /* Set 50% Duty Cycle for all four channels */
PWMMR2 = 50;
PWMMR3 = 50;
PWMMR4 = 50;
PWMTC = 0x00;
/* Trigger the latch Enable Bits to load the new Match Values */
PWMLER = (1<<SBIT_LEN0) | (1<<SBIT_LEN1) | (1<<SBIT_LEN2) | (1<<SBIT_LEN3) |
(1<<SBIT_LEN4);

/* Enable the PWM output pins for PWM_1-PWM_4(P2_0 - P2_3) */


PWMPCR = (1<<SBIT_PWMENA1) | (1<<SBIT_PWMENA2) | (1<<SBIT_PWMENA3) | (1<<SBIT_PWMENA4);

/* Enable Counters,PWM module */


PWMTCR = (1<<SBIT_CNTEN) | (1<<SBIT_PWMEN);

while(1)
{
for(dutyCycle=0; dutyCycle<100; dutyCycle++)
{
PWMMR1 = dutyCycle; /* Increase the dutyCycle from 0-100 */
PWMMR2 = dutyCycle;
PWMMR3 = dutyCycle;
PWMMR4 = dutyCycle;
/* Trigger the latch Enable Bits to load the new Match Values */
PWMLER = (1<<SBIT_LEN0) | (1<<SBIT_LEN1) | (1<<SBIT_LEN2) | (1<<SBIT_LEN3) |
(1<<SBIT_LEN4);
delay_ms(5);
}

for(dutyCycle=100; dutyCycle>0; dutyCycle--)


{
PWMMR1 = dutyCycle; /* Decrease the dutyCycle from 100-0 */
PWMMR2 = dutyCycle;
PWMMR3 = dutyCycle;
PWMMR4 = dutyCycle;
/* Trigger the latch Enable Bits to load the new Match Values */
PWMLER = (1<<SBIT_LEN0) | (1<<SBIT_LEN1) | (1<<SBIT_LEN2) | (1<<SBIT_LEN3) |
(1<<SBIT_LEN4);
delay_ms(5);
}
}
}

Using ExploreEmbedded Libraries :


In the above tutorial, we just discussed how to configure and use the PWM module of LPC2148.
Once you know the internals of LPC2148 PWM, you can directly use the ExploreEmbedded
libraries to generate the required PWM signals for different duty cycles.
The below sample code shows how to use the ExploreEmbedded PWM library.

#include <lpc214x.h>
#include "stdutils.h"
#include "systemInit.h"
#include "pwm.h"
#include "delay.h"

#define CYCLE_TIME 255

/* start the main program */


int main()
{
int dutyCycle;
SystemInit(); /* Clock and PLL configuration */
PWM_Init(CYCLE_TIME); /* Initialize the PWM module and the Cycle time(Ton+Toff) is set
to 255(similar to arduino)*/
PWM_Start(PWM_1|PWM_2|PWM_3|PWM_4); /* Enable PWM output on PWM_1-PWM_4 (P0_0, P0_7, P0_1,
P0_8) */

while(1)
{
for(dutyCycle=0;dutyCycle<CYCLE_TIME;dutyCycle++) /* Increase the Brightness of the
Leds */
{
PWM_SetDutyCycle(PWM_1,dutyCycle); //P0_0
PWM_SetDutyCycle(PWM_2,dutyCycle); //P0_7
PWM_SetDutyCycle(PWM_3,dutyCycle); //P0_1
PWM_SetDutyCycle(PWM_4,dutyCycle); //P0_8
DELAY_ms(5);
}

for(dutyCycle=CYCLE_TIME;dutyCycle>0;dutyCycle--) /* Decrease the Brightness of the


Leds */
{
PWM_SetDutyCycle(PWM_1,dutyCycle); //P0_0
PWM_SetDutyCycle(PWM_2,dutyCycle); //P0_7
PWM_SetDutyCycle(PWM_3,dutyCycle); //P0_1
PWM_SetDutyCycle(PWM_4,dutyCycle); //P0_8
DELAY_ms(5);
}
}
}

You might also like