|
|
View previous topic :: View next topic |
Author |
Message |
davt
Joined: 07 Oct 2003 Posts: 66 Location: England
|
Setting up for PWM |
Posted: Fri Feb 06, 2004 11:12 am |
|
|
Hi all
I am trying to use the PWM module in a 16F876 with a crystal frequency of of 20mhz.
What I want is a frequency of 50khz with 8 bit resolution.
I have got the PWM working but can only get 7 bits resolution at ~37khz.
I have set up the registers as follows:
t2con=0x04; // timer2 on, postscale=1
ccp1con=0x3c; // PWM on and lsb's set
pr2=0x82; // sets period
ccpr1l=0x10; // sets duty cycle
To give me a variable duty cycle I read a pot connected to A0 and after dividing by 8 pass the value to ccp1L to give me a variable pulse width - that bit works OK.
Could someone please help?
Thanks in advance.
Dave |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 06, 2004 11:36 am |
|
|
You're not using the CCS functions and you're setting the registers
directly.
If you look at this chart, and if you can believe it, it says
that what you want should be possible:
http://www.piclist.com/techref/microchip/pwmrescalc.htm
The CCS manual says the set_pwm1_duty() function can take
a 10-bit value.
Quote: | Writes the 10-bit value to the PWM to set the duty. An
8-bit value may be used if the least significant bits are
not required. |
In your code that writes directly to the registers, you've set the
bottom two bits as constants. So you're only going to get 8-bits
max, anyway.
You should use the CCS functions, and give them a 10-bit parameter. |
|
|
davt
Joined: 07 Oct 2003 Posts: 66 Location: England
|
PWM |
Posted: Fri Feb 06, 2004 3:44 pm |
|
|
Thanks for your reply PCM programmer.
8 bits resolution is all I require.
What I trying to achieve is to have a variable pulse width from almost zero to say 99%.
If I want a frequency of 50khz that is a period of 20us - if I divide by 255
I get 78ns per bit is this possible to achieve?
Many thanks for your time.
Dave |
|
|
Ttelmah Guest
|
Re: PWM |
Posted: Fri Feb 06, 2004 4:22 pm |
|
|
davt wrote: | Thanks for your reply PCM programmer.
8 bits resolution is all I require.
What I trying to achieve is to have a variable pulse width from almost zero to say 99%.
If I want a frequency of 50khz that is a period of 20us - if I divide by 255
I get 78ns per bit is this possible to achieve?
Many thanks for your time.
Dave |
Your problem is that you are not changing the least significant bits of the PWM duty. The CCPR1L register, holds eight bits of the duty cycle, but the two LSB's, are held in bits 4 and 5 of CCP1CON. You need to rotate your duty cycle value right by two bits, and put this into CCPR1L (as you are doing), and then mask the two low bits, and put these into CCP1CON. Without this, the CCP, runs in 'low resolution mode', which only gives just over 6 bits of resolution at the frequency you require.
At the end of the day, the 'set_ccp1_duty' function _does this_, and you are not going to make the code any smaller or neater, by going DIY...
Best Wishes |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: PWM |
Posted: Fri Feb 06, 2004 4:31 pm |
|
|
davt wrote: | Thanks for your reply PCM programmer.
8 bits resolution is all I require.
What I trying to achieve is to have a variable pulse width from almost zero to say 99%.
If I want a frequency of 50khz that is a period of 20us - if I divide by 255
I get 78ns per bit is this possible to achieve?
Many thanks for your time.
Dave |
Asume the timer increments once every 78ns with a prescaler of 1 you need a crystle speed of 1/.000000078 x 4 or 51.2 Mhz
That means you cant divide by 255 and get 50 Khz
This is doable.
Your timer actualy increments every 0.2 uS
If you simply setup the timer to overflow at 99 it will put a 50Khz wave out that has 1% control. Then simple set the puls width in % increments. Thats you best 50 Khz output. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 06, 2004 6:13 pm |
|
|
The following test program will give you a 50 KHz pwm frequency,
with 400 steps available. This gives you better than 8-bit resolution.
The key is to use a 16-bit variable as the parameter in the
set_pwm1_duty() function. Notice that I'm using a variable, below.
If you use a constant, be sure to declare it as a "long" by putting
a "L" on the end. Example:
set_pwm1_duty(200L);
When you specify it as a 16-bit value, this tells the compiler
to use 10-bit resolution mode when it compiles the code.
Code: | #include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
main()
{
int16 pwm_duty;
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_1, 99, 1);
pwm_duty = 200; // Set for 50% duty cycle
set_pwm1_duty(pwm_duty);
while(1);
} |
|
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Fri Feb 06, 2004 9:19 pm |
|
|
PCM programmer wrote: | The following test program will give you a 50 KHz pwm frequency,
with 400 steps available. This gives you better than 8-bit resolution.
The key is to use a 16-bit variable as the parameter in the
set_pwm1_duty() function. Notice that I'm using a variable, below.
If you use a constant, be sure to declare it as a "long" by putting
a "L" on the end. Example:
set_pwm1_duty(200L);
When you specify it as a 16-bit value, this tells the compiler
to use 10-bit resolution mode when it compiles the code.
Code: | #include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
main()
{
int16 pwm_duty;
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_1, 99, 1);
pwm_duty = 200; // Set for 50% duty cycle
set_pwm1_duty(pwm_duty);
while(1);
} |
|
Is that going to toggle the output on quarter cycles of the instruction clock? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 06, 2004 9:56 pm |
|
|
Quote: | Is that going to toggle the output on quarter cycles of the instruction clock? |
Yes. Microchip doesn't come right out and say it as plainly as they
should, but yes, it will.
In AN594, Using the CCP Module, on page 2, Microchip says:
"This gives a maximum accuracy of Tosc (50 ns when the device
is operated at 20 MHz)".
In the 16F877 data sheet they say that in 10-bit mode, the two
LSB's come from the pre-scaler for Timer2. That pre-scaler
is clocked at Fosc, so that means that 2-bit counter will count
at a 50 ns rate. They have this small note at the bottom of
the PWM block diagram:
"Note 1: The 8-bit timer is concatenated with 2-bit internal Q
clock, or 2 bits of the prescaler, to create 10-bit time-base". |
|
|
davt
Joined: 07 Oct 2003 Posts: 66 Location: England
|
setting up for PWM |
Posted: Sat Feb 07, 2004 1:48 pm |
|
|
Many thanks for your help.
Have a good weekend!
Dave |
|
|
|
|
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
|