CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PIC16F88 - PWM resolution problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 11:40 am     Reply with quote

CCS uses 10-bit mode if you specify the duty cycle parameter as 16-bit.
For a constant, put an 'L' on the end of it. For a variable, declare it as 'int16'.
Then you will get the 10-bit mode that you want.
sirius



Joined: 27 Jun 2009
Posts: 16
Location: Bulgaria

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 11:54 am     Reply with quote

Thank You for the fast reply! After adding "L", everything with the loading of pwm_duty_cycle is fine:

Code:

09A4:  BCF    06.0
09A5:  BCF    03.5
09A6:  BCF    06.0
09A7:  MOVLW  0C
09A8:  MOVWF  17
....................    set_pwm1_duty(102L);
09A9:  MOVLW  19
09AA:  MOVWF  15
09AB:  MOVF   17,W
09AC:  ANDLW  CF
09AD:  IORLW  20
09AE:  MOVWF  17


Nevertheless, 102L should be 10% duty_cycle(10-bit mode), but it's 39,8%. Just to remind,on 16F819 it's fine(10%). Is this a MCU-bug, I couldn't find any errata related topics? Thanks!

P.S. The actual resolution seems to be 8-bit, according to: 102L resulting in duty_cycle of 39.8%.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 12:54 pm     Reply with quote

I'm using the test program shown below with vs. 4.084. I also get about
40% duty cycle measured on the scope. But that's correct, because the
duty cycle is not determined by 102 being 10% of 1024. It's determined
by 102 being a percentage of the Timer2 value. That's the middle value
in the setup_timer_2() function.

In 10-bit mode, the duty cycle equation is:
Code:

16-bit Duty cycle Parameter         102L          102
---------------------------  =  ------------  = ------ = 39.8%
  (Middle value +1) * 4          (63 +1) * 4      256

Using the logic analyzer, I measure the high level pulse at 51.0 us,
and the total period at 128.1 us. This gives the following, which agrees
with the duty cycle equation:
Code:

51.0
-----  = .389
128.1


Test program:
Code:

#include <16F88.h>
#fuses INTRC_IO,NOWDT,BROWNOUT,PUT,NOLVP
#use delay(clock=8000000)

//=======================
void main()
{
setup_timer_2(T2_DIV_BY_4,63,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(102L);

while(1);
}
sirius



Joined: 27 Jun 2009
Posts: 16
Location: Bulgaria

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 1:26 pm     Reply with quote

Problem solved Very Happy. Seems to be a compiler issue, but don't want to investigate it profoundly. Manually configured PWM module, following PIC16F88 datasheet sequence:

Code:

...............................................
#byte CCP1CON = 0x17
#byte T2CON = 0x12
#byte PR2 = 0x92
................................................

PR2=255;
T2CON=4;               
CCP1CON=12;
set_pwm1_duty(102L);


Now 102L gives 9.98%, as should be. Tested also with 512L - exactly 50% duty_cycle. All 10-bit of resolution are available now.

Could be a wrong initialization sequence of PWM-module, but don't want to dig any further. Thanks anyway for the interest in my topic!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 1:30 pm     Reply with quote

Right, but you've changed the PR2 setting. That's the middle value.
I can do the same thing you just did, and I can do it in CCS. All I do is
set the middle value to 255 in the setup_ccp1() function, as shown below.
Then I read 10% duty cycle on the logic analyzer. This is with vs. 4.084.
Tested in hardware.
Quote:

#include <16F88.h>
#fuses INTRC_IO,NOWDT,BROWNOUT,PUT,NOLVP
#use delay(clock=8000000)

//=======================
void main()
{
setup_timer_2(T2_DIV_BY_4,255,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(102L);

while(1);
}
sirius



Joined: 27 Jun 2009
Posts: 16
Location: Bulgaria

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 1:42 pm     Reply with quote

setup_timer_2(T2_DIV_BY_4,63,1); - Defined by CCS Project Wizard.

setup_timer_2(T2_DIV_BY_4,255,1); - just tested it in hardware. You are right - duty_cycle=10%, but frequency is now 1,95KHz Exclamation , not as supposed to be 7,8Khz.




P.S. Adjusting Timer2 Prescaler to 1 and now is fine:
Code:

setup_timer_2(T2_DIV_BY_1,255,1);
-7,8Khz, full 10-bit resolution

A Project Wizard issue?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 2:33 pm     Reply with quote

I don't know. I never use the Wizard. I don't have that compiler version.
Changing the PR2 value will also affect the PWM frequency. So certainly
if the PR2 value is increased and nothing else is changed, the PWM
frequency will go down. You compensated for that by reducing the
prescaler. This post has the PWM frequency formula:
http://www.ccsinfo.com/forum/viewtopic.php?t=17993&start=1

If it's all working now, I'm happy.
sirius



Joined: 27 Jun 2009
Posts: 16
Location: Bulgaria

View user's profile Send private message

PostPosted: Wed Apr 28, 2010 7:47 am     Reply with quote

Yes, everything is fine now . Thanks PCM Wink
slammer



Joined: 02 May 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun May 02, 2010 7:35 am     Reply with quote

hi, I also have problem with PWM, I'm using Proteus 7.6 sp4 and PCWHD Compiler 4.106, the problem is pwm is not working, I don't know why, my code is like this

Code:
#include <16F877a.h>
#use delay(clock=20MHZ)
#fuses XT, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP

main()
{
enable_interrupts(GLOBAL);
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16,100L,1);
set_pwm1_duty(30L);
while(1);
}


but if I cancel the line
Code:
set_pwm1_duty(30L);

it is working then how can I control the duty cycle ?
my aim is to build a controller for Dc-Dc converter, my pic will take some data from ADC which is connected to output of the converter and referring to this data it will change the duty cycle of my 100kHz pwm,
please help me Smile what is the problem with this code ? is it because of proteus or version of CCS, If I try in real pic, will it work ?
thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Sun May 02, 2010 7:44 am     Reply with quote

It could be a proteus problem.
However there are two 'glaring' things that should be fixed:
1) Never _ever_ enable anything to do with interrupts without an interrupt handler present. If an interrupt does get enabled, this is a 'sure' way to crash code.
2) Set your fuses correctly for your clock. XT, does not support operation at 20MHz....

Best Wishes
slammer



Joined: 02 May 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun May 02, 2010 8:27 am     Reply with quote

the new code is like this, but still it's not working
I don't have the pic and the setup now so I have to simulate it :D that's why I used proteus, and if it's a proteus problem then how can I simulate it, I don't know CCS too much last year I was using pic with assembly however it's been 1 year and I don't remember...

Code:
#include <16F877a.h>
#use delay(clock=4MHZ)
#fuses XT, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP

main()
{
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16,100L,1);
set_pwm1_duty(30L);
while(1);
}
slammer



Joined: 02 May 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun May 02, 2010 8:45 am     Reply with quote

I have also tried PIC Simulator IDE - Evaluation Copy v6.65 and still not working :S
slammer



Joined: 02 May 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun May 02, 2010 9:18 am     Reply with quote

I've found a patch for proteus and now it's working, thanks for help Smile
luismramirez



Joined: 17 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Wed Apr 06, 2011 9:20 am     Reply with quote

Hi,

I have an 8Mhz, with T2 BY 16, 250;

I know what duty % I need, so, using the equation:

16bit value = % * (250 + 1) * 4

Then, for 100% and 50%:

100% = 10400
50% = 50200

Is that right?
I read some were that this 16bit value can't be bigger than the middle value from the timer_2 setup.

Thank you.
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Wed Apr 06, 2011 9:32 am     Reply with quote

Value can't be bigger than the ((middle value+1) *4)-1.
So for a middle value of 255, maximum value is 256*4 = 1024 -1 = 1023. The '10 bit' maximum for the chip.
Your formula is basically right, except for needing a division by 100.

value = (%/100) *(250+1) *4 -1

100% = 1003
50% = 501

You've lost a '0' in your 100% calculation.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group