Using PWM on the LPC1114 and LPC1343 - microbuilder

Using PWM on the LPC1114 and LPC1343 - microbuilder - Open Hardware and Micro-Manufacturing Made Easy(er)

http://www.microbuilder.eu/Projects/LPC1343ReferenceDesign/LPC1343_LPC1114_PWM.aspx

How to generate a PWM signal using any general-purpose timer on the LPC1100 and LPC1300.

The LPC1343 and LPC1114 both have five seperate timers: Two 16-bit and two 32-bit general purpose timers, and a 24-bit systick timer. Each of the 16-bit or 32-bit timers can be configured for pulse-width modulation (see PWM on Wikipedia for more information). PWM can be used for a number of interesting things, such as selectively dimming lights or LEDs, or for driving certain types of motors. Stepper motors, for example, can be very dependably driven with PWM using a common controller like the Allegro A3967.
This quick tutorial will show you how to generate a 0.5KHz signal (that is, 2000 full pulses per second) with a 50-percent duty cycle, meaning that the signal will by high for 1ms, low for 1ms, then high again, etc., etc.

To generate a modulated signal with a timer, you need to make use of a single MAT pin from any general-purpose timer. We will use pin 1.9 in this case, which is multiplexed with CT16B1_MAT0 (MAT 0 on 16-bit timer 1). Look at the code below to see the steps required to configure the PWM output and start generating the signal.

Generating PWM Output with 16-Bit Timer 1

static void timer16PWMInit()
{
  /* Enable the clock for CT16B1 */
  SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B1);

  /* Configure PIO1.9 as Timer1_16 MAT0 Output */
  IOCON_PIO1_9 &= ~IOCON_PIO1_9_FUNC_MASK;
  IOCON_PIO1_9 |= IOCON_PIO1_9_FUNC_CT16B1_MAT0;

  /* Set period (MR3) to 2ms */
  TMR_TMR16B1MR3 = TIMER16_CCLK_1MS * 2;

  /* Set Duty Cycle (MR0) to 50% */
  TMR_TMR16B1MR0 = TIMER16_CCLK_1MS * 1;

  /* Configure match control register to reset on MR3 */
  TMR_TMR16B1MCR = (TMR_TMR16B1MCR_MR3_RESET_ENABLED);

  /* External Match Register Settings for PWM */
  TMR_TMR16B1EMR = TMR_TMR16B1EMR_EMC0_TOGGLE | TMR_TMR16B1EMR_EM0;

  /* Enable PWM0 and PWM3 */
  TMR_TMR16B1PWMC = TMR_TMR16B1PWMC_PWM0_ENABLED | TMR_TMR16B1PWMC_PWM3_ENABLED;

  /* Enable Timer1 */
  TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
}

The pulse you generate is controlled by two different values: the period, which is the total length of time for the pulse from start to finish, and the duty cycle, which is the relationship between how long the signal is high and how long it is is low. For example, the above code will set a 'period' of 2 milliseconds (which can also be written as 0.5KHz), and a duty cycle of 50% (by providing exactly 1/2 the value of the 'period', meaning 1 millisecond). This will create a signal that changes from high to low 2000 times per second, and it will be high for exactly one millisecond, and low for exactly one millisecond. The image below, captured on an inexpensive logic analyser, shows the generated signal:

We can see with the window in the bottom right that the 'period' is indeed 2ms, and that each half of the signal is 1ms, meaning a 50% 'duty-cycle'.

If this was hooked up to a stepper motor driver, this would cause the motor to advance one step every 2 milliseconds, or 500 steps per second.  If the PWM signal was hooked up to an LED, it would cause the LED to be roughly half as bright as normal (though the brightness of LEDs isn't linear, so this wouldn't actually work out so perfectly in the real world).

If you wanted to adjust either the length of the pulses, or the duty cycle you simply need to adjust the values you assign to the corresponding match register in the above sample code (MR3 for period, and MR0 for duty cycle in this case). For example, to have the generate pulse 'on' for 25% of the time, and 'off' for the other 75%, you could make the following changes:

Setting a 25% Duty-Cycle

/* Set period (MR3) to 2ms */
TMR_TMR16B1MR3 = TIMER16_CCLK_1MS * 2;

/* Set Duty Cycle (MR0) to 25% */
TMR_TMR16B1MR0 = TIMER16_CCLK_100US * 15;

You can see now that the total pulse is still 2ms, but that the signal is now high for 25% of the total length, and low for 75%. If this was connected to an LED, the LED would theoretically be half as bright as in the above example (or twice as bright, depending on how it's configured).

Note on timer delays: In this example, we use a 16-bit timer, which is fine for something like basic motor control or for dimming LEDs since the 'period' can be fairly short. 16-bit timers are very limited, though, in the length of time that they can handle. On a system running at 12MHz, the maximum length of time a 16-bit timer can run is ~5.46ms, at 48MHz it's 1.37mS and at 72MHz it's well under 1mS. If you require a longer 'period' you will need to use a 32-bit timer, which can deal with much longer delays.

.END

No comments:

Post a Comment