help for 1MHz to 14MHz pwm using pic16f877a

PWM for MHz using pic does linearity being achived

  • Yes

    Votes: 0 0.0%
  • No

    Votes: 2 100.0%

  • Total voters
    2
  • Poll closed .

Thread Starter

pany2008

Joined Aug 17, 2008
11
Hi,

I am having problem for pwm using pic16f877a, I am not getting the pulse output from microcontroller. Please can you help me out for seeing my source code if their is any thing wrong or missing then please help me out.

Rich (BB code):
#include<pic.h>
#include<math.h>
#include "ioports1.h"
#include "delay.h"
#include "lcd.h"
 
__CONFIG (HS & DEBUGDIS & WDTDIS & BORDIS & PWRTEN & LVPDIS & PROTECT);
 
unsigned int dummy_sec;
 
void Sec(unsigned int);
 
void main()
{
    Sec(100);
    init_ports();
    Sec(50);
    lcd_init(); //LCD initialized
    Sec(25);
 
        lcd_line1(0); //LCD address specified AT LINE 1
        lcd_string("  PANKAJ  PATEL  "); //Displays message "LCD INTERFACING"
        lcd_line2(0); //LCD address specified AT LINE 2
        lcd_string(" PWM EXAMPLE    "); //Displays message "LCD INTERFACING"
 
    Sec(200);
    init();
 
    for(;;)
    {
        GIE = 1;
        lcd_line1(0); //LCD address specified AT LINE 1
        lcd_string("  PANKAJ  PATEL  "); //Displays message "LCD INTERFACING"
        lcd_line2(0); //LCD address specified AT LINE 2
        lcd_string(" PWM EXAMPLE    "); //Displays message "LCD INTERFACING"
     } 
}
 
init_ports()
{
       T_CPU_LED = 0;  // pin enable to output
       CPU_LED = 0;
} 
 
init()
{
       TMR1H = 0xfc;
    TMR1L = 0x17;
    TMR1CS = 0;
    T1CKPS0 = 0;
    T1CKPS1 = 0;
    T1CON = 0b00000001;
    TMR1ON = 1;     
    TMR1IF = 0;
    TMR1IE = 1;
    PR2 = 0b00000000;
    T2CON = 0b00000100;
    CCPR1L = 0b00000000;
    CCP1CON = 0b00011100; 
    TMR2ON = 1;     
    TMR2IF = 0;
    TMR2IE = 1;
    PEIE = 1;
    GIE = 1; 
}
 
void Sec(unsigned int itime)
{
    unsigned int i;
    unsigned char j;
        for(i=0;i<itime;i++)
            for(j=0;j<165;j++);
}
 
 
void interrupt ISR()
{
   if(TMR1IF)
    {
        PIE1 = 0;    
        TMR1IF = 0;
        TMR1ON = 0;
        CPU_LED = !CPU_LED;
        ++dummy_sec;
        if(dummy_sec > 1000)
            {
//                CPU_LED = !CPU_LED;
                dummy_sec = 0;
            }
 
        TMR1H = 0xfc;
        TMR1L = 0x17;
        TMR1ON = 1;
        PIE1 = 1;
    }
 
}
 
Last edited by a moderator:

Thread Starter

pany2008

Joined Aug 17, 2008
11
Hello,

On wich speed is the pic running?
I think the 1 to 14 Mhz is way to high for PWM at the pic.

Bertus
The pic is running on 20Mhz can please check the code i am not getting any pwm output from the code which i have post. if i can get even 10Mhz maximum the also it will be fine for me.
 

Markd77

Joined Sep 7, 2009
2,806
Yup, max 5MHz with 20MHz clock. Is the CCP pin definately set to output?
In MPLAB simulator you can't see PWM with a resolution greater than the instruction cycle so running PWM at max frequency you will not see anything. You can reduce the frequency for debugging and then assume it will work.
The PWM period is specified by writing to the PR2 register.
The PWM period can be calculated using the following
formula:
PWM period = [(PR2) + 1] • 4 • TOSC •
(TMR2 prescale value)
PWM frequency is defined as 1 / [PWM period].
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
Run it through the MPLAB simulator.

PS it'll top out at 5MHz @ 50% duty. Perhaps a 24H could muster 14MHz but would also be a 1 or 2 bit PWM.

What's it for?

PPS useless poll.
Thanks for the help, for me right now 5Mhz @50% duty cycle will be ok, Can please verify my code because in the current code no output pwm is coming i think their might be something wrong in the code please correct my mistake in code. I am using it for the Medical instrument (ultrasound).
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
Yup, max 5MHz with 20MHz clock. Is the CCP pin definately set to output?
In MPLAB simulator you can't see PWM with a resolution greater than the instruction cycle so running PWM at max frequency you will not see anything. You can reduce the frequency for debugging and then assume it will work.
Thanks for the help can please me out to verify my code, because i am not getting any output from above code, please correct my mistake in code.
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
Do you have a part number for the transducer.
Currently we have manufacture it here locally in India, we have done a copy of transducer from one imported machine and we have checked out it in details the machine works with 1 to 5MHz frequency output to the transducer, and their transducer is also manufactured by them. Our transducer which we have made work perfectly with their machine now we have to develop the machine so for that i need the help.
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
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:



Where:

D = Duty Cycle

t = ON Duration

T = Period of Frequency



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:



Please note that the (65536 - Delay) is in microseconds (μS). Here's a simple example of how it works:

Suppose hypothetically you wanted a frequency of 1 kHz. You simply put it in the PWM function and it does the rest. It begins in the code by subtracting 65536 from your intended frequency value:

Code Math:






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

Here is the code:

Rich (BB 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;
            }
        }
    }
Informative Links:

Duty cycle - Wikipedia, the free encyclopedia

Pulse-width modulation - Wikipedia, the free encyclopedia

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

Enjoy!
Can provide me code for pic16f877a for hitech compiler, i am really needing it.

PS you posted in a thread that is for explanation of the topic and not for the question.
 
Last edited by a moderator:
Thanks for the help can please me out to verify my code, because i am not getting any output from above code, please correct my mistake in code.
You have set up the PWM for software interrupt, but have enabled the hardware interrupts?
<EDIT with fresh cup of coffee, I see CCP1CON is set for PWM P1A-P1D high>

I have my doubts as to being able to output the max clock of 5Mhz for the 20Mhz osc. The implication is that would require a 100% duty cycle which would be DC, yes/no? The best setting I could get on an 18lf14k22 with the internal osc of 16Mhz, and 4X PLL, was 8Mhz (50% duty cycle).

Here is a snippet of GCBasic code, that followed the 18f manual. No luck with PR2 = 0 at all.

Rich (BB code):
CCP1CON = 0
TMR2 = 0
PR2 = 0x01        ;set TMR2 register for max speed
CCPR1L = 0x00    ;50% duty cycle
dir PortC out    ;P1A as pwm out
PIE1 = 0
PIR1 = 0 
Set TMR2ON ON
CCP1CON = b'00101100'    '50% duty with PR2 = 0x01, Single output pwm as controlled by pulse steering mode
Set STRA ON                'Steer pwm to P1A for ECCP module 

Main:

Goto Main
<EDIT not in software interrupt mode so deleted clearing TMR2IF code>
 
Last edited:

t06afre

Joined May 11, 2009
5,934
@Pankaj D. Patel
Then you cross post to other forums. It is often a good idea to post link(s) to the other forums http://forum.htsoft.com/all/showflat.php/Cat/0/Number/195092/an/0/page/0#Post195092
To solve your problem. I think it would be a good idea to take some time and read the datasheet. Then you have a better understanding on how your chip actually work. Sit down on your lab bench with a scope. And to some test so you can check if your ideas are correct. Then you can move on and expand your program. And if you are stuck. Post your problems with a good explanation of what you have done. And why and how you struggle.
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
@Pankaj D. Patel
Then you cross post to other forums. It is often a good idea to post link(s) to the other forums http://forum.htsoft.com/all/showflat.php/Cat/0/Number/195092/an/0/page/0#Post195092
To solve your problem. I think it would be a good idea to take some time and read the datasheet. Then you have a better understanding on how your chip actually work. Sit down on your lab bench with a scope. And to some test so you can check if your ideas are correct. Then you can move on and expand your program. And if you are stuck. Post your problems with a good explanation of what you have done. And why and how you struggle.
I am person who try maximum time and when i am not able to solve my problem then i ask someone to help me out, to the clear i am just new to pic till i have done only 3 project using pic, but if you ask for 89c52 then for that i have done almost 400 industrial project in that.
Why i am asking their also that now i am underwater totally so i am waiting for some to get me out off water and save my life.
I have studied a lot the datasheet and followed the instruction but not able get the result i was behind the pwm from last 15 days, then a last i came out all for solving my problem.
 

Markd77

Joined Sep 7, 2009
2,806
I've looked over you settings for PR2, T2CON, CCPR1L and CCP1CON and they look fine for a frequency of crystal/4 and a duty cycle of 25%.
You shouldn't set TMR2IE because it will generate interrupts faster than it is possible to deal with them - although at that point PWM should already be operating so this isn't the real problem.
I don't use C, but I can't see where the CCP1 pin is set as output.
I see T_CPU_LED = 0 and CPU_LED = 0 but I don't know if they are defined as the CCP1 pin.
How are you testing the code - a simulator or in hardware, and what are you using to measure the output?
 

Thread Starter

pany2008

Joined Aug 17, 2008
11
I've looked over you settings for PR2, T2CON, CCPR1L and CCP1CON and they look fine for a frequency of crystal/4 and a duty cycle of 25%.
You shouldn't set TMR2IE because it will generate interrupts faster than it is possible to deal with them - although at that point PWM should already be operating so this isn't the real problem.
I don't use C, but I can't see where the CCP1 pin is set as output.
I see T_CPU_LED = 0 and CPU_LED = 0 but I don't know if they are defined as the CCP1 pin.
How are you testing the code - a simulator or in hardware, and what are you using to measure the output?
Now i am getting the output from pwm but it is really getting very low, just only 25Khz at 50% duty cycle, i am using the hardware, measure the output on scope and frequency meter.
 

Markd77

Joined Sep 7, 2009
2,806
Very odd, what frequency do you measure on the OSC1/OSC2 pins (where the crystal is)? Also if this frequency is continuous with no gaps - which would indicate the PIC is resetting.
Best to check the PWM output stays the same at the same time because the oscillator is very sensitive to disturbance.
 
Last edited:
Top