8051 microcontroller 8051 microcontroller
Pulse Width Modulation (PWM): 8051 Code example


►Idea Behind Implementation

The basic idea behind PWM implementation on 8051 is using timers and switching port pin high/low at defined intervals. As we have discussed in the introduction of PWM that by changing the Ton time, we can vary the width of square wave keeping same time period of the square wave.

We will be using 8051 Timer0 in Mode 0. Values for high and low level will be loaded in such a way that total delay remains same. If for high level we load a value X in TH0 then for low level TH0 will be loaded with 255-X so that total remains as 255.

►Assembly Code Example

►Timer setup for PWM
CODE:
        PWMPIN EQU P1.0         ; PWM output pin
PWM_SETUP:
        MOV TMOD,#00H           ; Timer0 in Mode 0
        MOV R7, #160            ; Set pulse width control
        ; The value loaded in R7 is value X as
        ; discussed above.
        SETB EA         ; Enable Interrupts
        SETB ET0                ; Enable Timer 0 Interrupt
        SETB TR0                ; Start Timer
        RET
 


►Interrupt Service Routine
CODE:
TIMER_0_INTERRUPT:
        JB F0, HIGH_DONE        ; If F0 flag is set then we just finished
                                ; the high section of the
LOW_DONE:                       ; cycle so Jump to HIGH_DONE
        SETB F0                 ; Make F0=1 to indicate start of high section
        SETB PWMPIN             ; Make PWM output pin High
        MOV TH0, R7             ; Load high byte of timer with R7
                                ; (pulse width control value)
        CLR TF0                 ; Clear the Timer 0 interrupt flag
        RETI                    ; Return from Interrupt to where
                                        ; the program came from
HIGH_DONE:
        CLR F0                  ; Make F0=0 to indicate start of low section
        CLR PWMPIN              ; Make PWM output pin low
        MOV A, #0FFH    ; Move FFH (255) to A
        CLR C                   ; Clear C (the carry bit) so it does
                                        ; not affect the subtraction
        SUBB A, R7              ; Subtract R7 from A. A = 255 - R7.
        MOV TH0, A              ; so the value loaded into TH0 + R7 = 255
        CLR TF0                 ; Clear the Timer 0 interrupt flag
        RETI                    ; Return from Interrupt to where
                                ; the program came from
 


In your main program you need to call this PWM_SETUP routine and your controller will have a PWM output. Timer Interrupt service routine will take care of PWM in the background. The width of PWM can be changed by changing the value of R7 register. In above example I am using 160, you can choose any value from 0 to 255. R7 = 0 will give you o/p 0V approx and R7 = 255 will give you 5V approx.

You can also make use of Timer1 if you want. And the output pin can be changed to whatever pin you want.
►C Code Example

►Timer setup for PWM in C
CODE:
//Global variables and definition
#define PWMPIN P1_0

unsigned char pwm_width;
bit pwm_flag = 0;

void pwm_setup(){
        TMOD = 0;
        pwm_width = 160;
        EA = 1;
        ET0 = 1;
        TR0 = 1;
}
 


►Interrupt Service Routine
CODE:
void timer0() interrupt 1 {
        if(!pwm_flag) { //Start of High level
                pwm_flag = 1;   //Set flag
                PWMPIN = 1;     //Set PWM o/p pin
                TH0 = pwm_width;        //Load timer
                TF0 = 0;                //Clear interrupt flag
                return;         //Return
        }
        else {  //Start of Low level
                pwm_flag = 0;   //Clear flag
                PWMPIN = 0;     //Clear PWM o/p pin
                TH0 = 255 - pwm_width;  //Load timer
                TF0 = 0;        //Clear Interrupt flag
                return;         //return
        }
}
 


Now your normal 8051 is capable of PWM output.



◄ Introduction to PWM  |  8051 PWM Example Code  |  AVR PWM Example Code ►

Back to index


© 2010 Rickey's World
Render time: 0.0401 sec, 0.0056 of that for queries. DB queries: 18. Memory Usage: 2,127kB