Monday 23 July 2018

PWM in ARM Microcontroller (LPC2148)

Aim:

Pulse Width Modulation (PWM) is a comparatively recent power switching technique for providing intermediate amounts of electrical power between fully on and fully off levels. Usually, digital pulses have same on and off time period, but in some situations we need the digital pulse to have more/less on time/offtime. In PWM technique, we create digital pulses with unequal amount of on and off state to get required intermediate voltage values.

Description:


In this tutorial we will explore the use of PWM in LPC2148 ARM7 Microcontroller. Pulse Width Modulation (PWM) is very useful technique for controlling analog circuits with processors digital outputs. PWM used in a wide variety of applications ranging from measurement and communications to power control. As PWM is famous technique to generate a signal of varying duty cycle. Here we will use it to control brightness of LED using LPC2148.

Why we need PWM?

As we all know that microcontrollers do everything with ones and zeros. That means microcontroller works with 3.3V and 0V as digital 1 & 0. It can’t produce for example 1V or 2.5V or any other value different than 0V and 3.3V. Here PWM feature allows us to generate any voltage level between 0V and 3.3V. Now we will see how it’s been done using PWM so that we will control brightness of LED. This is probably the best way to see effect of PWM. Before we proceed any further let’s discuss little bit about duty cycle.

Duty Cycle:  

When signal is HIGH, we call this “ON time”. To describe amount of “on time”(TON), we use the concept of duty cycle. Duty cycle is measured in percentage. The percentage duty cycle describe the performance of a digital signal ON over an interval or period of time. This period is the inverse of the frequency of the waveform. If digital signal spends half of time ON and remaining OFF, we would say this digital signal has duty cycle of 50%. If percentage is higher than 50% that means digital signal spends more time in HIGH state than LOW state then we would say duty cycle is higher than 50%.


PWM Duty Cycle Pulse

Above graph represents waveform of 50%, 75% & 25% duty cycle. 100% duty cycle would be the same as setting the voltage to 3.3V (HIGH). 0% duty cycle would be same as 0V or grounding the signal. The relation and calculation has been evaluated by following equations:


Equation for Calculation Duty Cycle

PWM in LPC2148 ARM7

PWM in LPC2148 ARM7 looks complicated than the general purpose timers. However it is really an extra general purpose timer with some additional hardware. The PWM in LPC2148 is capable of producing six channels of single edge controlled PWM or three channel of dual edge controlled PWM. The Phillips LPC2148 has 6 channels of pulse width modulation. There are 7 registers to accommodate the PWM with register 0 being used to set base frequency (f =1/T). Thus since there is only one base frequency register all 6 channels must have base frequency.


Single Edge and Double Edge PWM Waveforms

As shown in figure above. PWM in LPC2148 can be single edge or double edge. In double edge PWM ending point of pulse and starting point of the pulse is a variable and can be set each cycle. In single edge PWM only the ending edge of the PWM is a variable and the starting edge is always set at the base frequency. Single edge requires one register (plus the base register) so that you can have 6-single edge channels of PWM on the LPC2148. For double edge PWM. You need a base register plus a starting edge register plus and ending edge register so that only 3-channels of double edge PWM is available on the LPC2148. You can mix single and double edge channels as long as you don’t run out of 6 available registers. Instead of spending more time I would prefer to start straight to implement example project. But before we get any further let’s have a quick look at PWM registers in LPC2148 Microcontroller.

Registers: PWM in LPC2148 ARM7 

PWMTCRPWM Timer Control Register– PWMTCR is used to control the timer counter functions. The Timer Counter can be disable or reset through the PWMTCR.
PWMPRPWM Prescale Register– The PWMTC (PWM Timer Counter) is incremented every PWMPR+1 cycles of PCLK.
PWMMR0-PWMMR6PWM Match Register 0- PWM Match Register 6– PWMMR0-6 can be enabled through PWMMCR to reset the PWMTC, stop both the PWMTC and PWMPC, and/or generate an interrupt when it matches the PWMTC. In addition, a match between PWMMR0-PWMMR6 and the PWMTC sets all PWM outputs that are single edge mode and sets PWM1 if it is in double-edge mode.
PWMMCRPWM Match Control Register– The PWMMCR is used to control if an interrupt is generated and if the PWMTC is reset when match occurs.
PWMIRPWM Interrupt Register– The PWMIR can be written to clear interrupt. The PWMIR can be read to identify which of the possible interrupt sources are pending.
PWMLERPWM Latch Enable Register– Enables use of new PWM Match values
PWMPCRPWM Control Register– Enables PWM outputs and selects PWM channel types as either single edge or double edge controlled.

Block Diagram

pwm

Schematic


Code

// ***********************************************
// Project: Interfacing PWM to LPC2148
// Author: Hack Projects India
// Module description: Operate array of LED's
// ***********************************************
#include <lpc214x.h>

void initPWM(void);      // Initialize PWM
void initClocks(void);        // Setup PLL and Clock Frequency

int main(void)
{
 initClocks(); //Initialize CPU and Peripheral Clocks @ 60Mhz
 initPWM(); //Initialize PWM

  //IO1DIR = 0x1; This is not needed!
 //Also by default all pins are configured as Inputs after MCU Reset.
   
    while(1)
    {
   PWMMR4 = 2500; //T-ON=25% , Hence 25% Bright
   PWMLER = (1<<4); //Update Latch Enable bit for PWMMR4
    }
    //return 0; //normally this wont execute ever
}

void initPWM(void)
{
 PINSEL0 = (PINSEL0 & ~(1 << 16)) | (1 << 17); // Select PWM4 output for Pin0.8
 PWMPCR = 0x0; //Select Single Edge PWM - by default its single Edged so this line can be removed
 PWMPR = 60-1; // 1 micro-second resolution
 PWMMR0 = 10000; // 10ms period duration
 PWMMR4 = 500; // 0.5ms - pulse duration i.e width (Brigtness level)
 PWMMCR = (1<<1); // Reset PWMTC on PWMMR0 match
 PWMLER = (1<<0)|(1<<4); // update MR0 and MR4
 PWMPCR = (1<<12); // enable PWM output
 PWMTCR = (1<<1) ; //Reset PWM TC & PR

 //Now , the final moment - enable everything
 PWMTCR = (1<<0) | (1<<3); // enable counters and PWM Mode

 //PWM Generation goes active now - LED must be 25% Bright after boot!!
 //Now you can get the PWM output at Pin P0.8!
}

void initClocks(void)
{
 PLL0CON = 0x01;   //Enable PLL
 PLL0CFG = 0x24;   //Multiplier and divider setup
 PLL0FEED = 0xAA;  //Feed sequence
 PLL0FEED = 0x55;
 
 while(!(PLL0STAT & 0x00000400)); //is locked?
  
 PLL0CON = 0x03;   //Connect PLL after PLL is locked
 PLL0FEED = 0xAA;  //Feed sequence
 PLL0FEED = 0x55;
 VPBDIV = 0x01;    // PCLK is same as CCLK i.e.60 MHz
}

Downloads:

The code was compiled in Keil uvision4 and simulation was made in Proteus v7.7.
To download code and proteus simulation click here.

Further Reading suggestions:

No comments:

Post a Comment