Continue to Site

Welcome to

Welcome to our site! is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

pic pwm duty is inaccurate

Not open for further replies.


Member level 1
May 1, 2013
Reaction score
Trophy points
Activity points
i am using a code which takes frequency and dutycycle and give the pulse.frequency works fine (accurate) but duty doesnt always give correct output. i.e if a enter 50 as duty cycle then it will give accurate duty cycle and when i choose 80,it will give 80% duty but when i want 10,20 or 25 then it gives wrong duty but accurate frequency.pwm is the part which i cant figure so far.i know the equations but when i write them it gives errors.i am attaching the code,kindly have a look at it.i will be very thankful.the trouble lies in PWM_Set_Duty function which i am unable to figure out.or kindly give me a pwm function for fixed 25khz frequency and variable duty cycle.i will be very thankful

#include <pic.h>
#include <htc.h>
#define _XTAL_FREQ 20000000 
void PWM_Init(float frequency,unsigned char timer_prescalar);
void PWM_Set_Duty(unsigned char duty_cycle,unsigned char timer_presclar);
void PWM_Stop();

unsigned char i=0;
unsigned char flag = 0;
unsigned int value;
void main()
unsigned short duty1=20;
unsigned char TimerPrescalar=4;

void PWM_Init(float frequency,unsigned char timer_prescalar)

float temp;
TRISC2 = 0;

temp = _XTAL_FREQ/frequency;
temp = temp/4;
temp = temp/timer_prescalar;
PR2 = (unsigned char)(temp);
PR2 = PR2-1;
CCPR1L = 0x00;
CCP1CON = 0x0C; //Set Zero Percent Duty Cycle Initially
TRISC2 = 0; 
if(timer_prescalar == 1)
T2CON = 0b00000100; 
else if(timer_prescalar == 4)
T2CON = 0b00000101; 
else if(timer_prescalar == 16)
T2CON = 0b00000111; 
void PWM_Set_Duty(unsigned char duty_cycle,unsigned char timer_prescalar)
unsigned int register_value;
float frequency;

frequency = (_XTAL_FREQ/4);
frequency = (frequency/timer_prescalar);
frequency = (frequency/(PR2+1)); //Frequency of PWM Signal

frequency = (frequency*100)/(duty_cycle);

register_value = (_XTAL_FREQ)/(unsigned int)frequency;
register_value = (register_value/timer_prescalar);

CCPR1L = (register_value>>2);
register_value = register_value & 0x03;
CCP1CON = CCP1CON | (register_value<<4);

You neither mentioned the PIC type nor the compiler version which makes it hard to give specific help.

i am using mplab 8 and pic 16f877a pic microcontroller.soory i forgot to in hurry.

The problem is that frequency is greater than unsigned int range in this line
register_value = (_XTAL_FREQ)/(unsigned int)frequency;

- - - Updated - - -

Your code is rather long winded, the problem can be solved much more easily.

void PWM_Set_Duty(unsigned char duty_cycle)
unsigned int register_value;
register_value = (long)(PR2+1)*duty_cycle/25; 
CCPR1L = (register_value>>2);
CCP1CON = CCP1CON & 0xf | (register_value & 3)<<4;

Thankyou so much sir,helped me alot :)
its working on proteus and will try on hardware.a big thank you.

it would be a great help if you can provide a general and much simpler code which takes frequency and duty cycle.i want 25khz frequency and 0-100% duty would help me avoiding mistakes which was in my code.

Try the attached project. Use a Frequency counter to check the PWM frequency. It should be near or equal to 25 KHz. ADC value varies from 0 to 1023 and PWM duty depends upon adc value. PWM duty can be 0 to 100 %. adcValue is scaled and mapped to pwm duty.

broken link removed


  • PWM.rar
    94.9 KB · Views: 70
  • pwm.png
    39 KB · Views: 97
Last edited by a moderator:

The attached project doesn't answer the question because it uses (I guess mikroC) built-in functions to operate the PWM unit instead of genuine C code.

Yes. I know but I can only help with mikroC code.

i am using mplab to code my project.anyways you people are a great help :)
thank you so much for your kind replies.appreciate it :)

Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to