Creating PWM With PIC

Status
Not open for further replies.

EN0

Member
Hey Everybody,

If you want to create PWM using a PIC, then this thread is for you. I contrived a PWM function that can drive motors, LEDs, and other hardware from 15.26 Hz to 1 MHz. I also put in a Comet lighting effect for 10 LEDs (RA0-RA3, RB0-RB5) on the PIC18F1320 just for a quick example program. Please note that the compiler is C18 and I am using the PIC18F1320. The code will not work with a different compiler or PIC. To understand how the code works, you need to grasp the concept of duty cycle and PWM itself. With PWM, you are turning on your hardware for a limited amount of time, and turning it off for a limited amount of time. That time differs with respect to your driving frequency, in which you subtract your frequency from the duty cycle to get the OFF delay. Therefore, the following equations apply:

[LATEX]D = \frac{t}{T}[/LATEX]

Where:

D = Duty Cycle

t = ON Duration

T = Period of Frequency

[LATEX]V_O = D V_{IN}[/LATEX]

Where:

Vo = Output voltage from pin.

Vin = Standard voltage input, presumably 5V (What you are doing is switching that 5V on and off rapidly so you get a new output voltage).

So in the code, you see I have my on and off variables, which determine the on and off delay. The reason you see 65536 subtracting from the variables is due to Timer0, which uses the following equation to find frequency:

[LATEX]f = \frac{1}{(65536 - Delay)}[/LATEX]

The showPat function simply combines LATA and LATB together, otherwise my LED combination wouldn't be consecutive.


**broken link removed** is the code:

Code:
//
//	Comet Tails.C
//
	#include <p18f1320.h>
	#include <delays.h>
	#include <stdlib.h>
	#pragma config OSC=INTIO2, WDT=OFF, LVP=OFF, DEBUG=ON
	#define PAUSE Delay1KTCYx(10);
	#define FREQ 500
	#define TIME 100

   void showPat(unsigned int myPat)
	{
		unsigned int patstopBits;
		patstopBits = myPat>>4;
		LATA = myPat;
		LATB = patstopBits;
	}
	
	void showPatN(unsigned int patN)
	{
		unsigned int patstopN;
		patstopN = patN>>4;
		LATA = ~patN;
		LATB = ~patstopN;
	}

	void pwm(unsigned int pins, unsigned int duty, unsigned int freq, unsigned int timer)   // PWM Function
    {    
			unsigned int times, on, off, pat;
			TRISA = ~(pins & 0xFF);
			TRISB = ~(pins>>4 & 0xFF);
			pat = pins;
			on = (65536 - duty);
			off = (65536 - freq) - on;
            INTCONbits.TMR0IF = 0;   // Clear OVF Flag
            showPat(pat);   // Initialize LATA          		
            T0CON|=0x80;	// Set Timer0 Bits
        
            for(times=timer;times>0;times--)   // Duration of playing
            {
				if(freq<=duty)	// If duty cycle is greater than or equal to the frequency
				{
					showPat(pat);
				}
				else
				{
	     	        TMR0H = (on >> 8) & 0xFF;   //Load TMR0H byte first
	                TMR0L = on & 0xFF;   // Load TMR0L byte next
	                while(!INTCONbits.TMR0IF);   // Wait for timer
					INTCONbits.TMR0IF = 0;   // Clear OVF Flag
					showPatN(pat);   // Invert output
					TMR0H = (off >> 8) & 0xFF;
					TMR0L = off & 0xFF;
					while(!INTCONbits.TMR0IF);
					showPat(pat);
				}  
            }
    }

	void main()
	{
		int a,b,c,d,e,f;
		OSCCONbits.IRCF0=1; 
		OSCCONbits.IRCF1=1;
		OSCCONbits.IRCF2=1;
		T0CONbits.TMR0ON = 0;   // Don't turn timer on yet
		T0CONbits.T08BIT = 0; 	// Timer0 is configured as 16-bit timer
		T0CONbits.T0CS = 0;	  // Use internal clock
		T0CONbits.PSA = 1;   // Prescaler is not assigned
		T0CONbits.T0PS2 = 0;
		T0CONbits.T0PS1 = 0;
		T0CONbits.T0PS0 = 0;
		OSCCONbits.IRCF0=1; 
		OSCCONbits.IRCF1=1;
		OSCCONbits.IRCF2=1;
		while(!OSCCONbits.IOFS);

		while(1)
		{
			a = 0x01;
			b = 0x02;
			c = 0x04;
			d = 0x08;
			f = 0x10;
			while(a<500)
			{
				pwm(a, 1, FREQ, TIME);
				PAUSE;
				a=a<<1;
				pwm(b, 25, FREQ, TIME);
				PAUSE;
				b=b<<1;
				pwm(c, 50, FREQ, TIME);
				PAUSE;
				c=c<<1;
				pwm(d, 150, FREQ, TIME);
				PAUSE;
				d=d<<1;
				pwm(e, 350, FREQ, TIME);
				PAUSE;
				e=e<<1;
				pwm(f, 500, FREQ, TIME);
				PAUSE;
				f=f<<1;
			}
		}
	}

If anyone has questions, I would encourage you to ask them! Comments and suggestions are also welcomed.

Enjoy!

EDIT: Don't be afraid to ask questions! Remember the following saying:

If you ask questions you may look stupid, but if you don't ask questions you'll stay stupid.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…