View previous topic :: View next topic |
Author |
Message |
jojos
Joined: 30 Apr 2007 Posts: 64
|
Pwm Frequency output problem |
Posted: Sun Jan 17, 2010 12:57 pm |
|
|
Hello. I am working on a project with a PIC 18F2520 chip. I am using its PWM. I have an external crystal of 3276800 Hz. I am having trouble to achieve the desired PWM freq. If I choose PR2 with 255 value, prescaler 16, I am getting a 200 Hz on the PWM pin as it should. But when I try to get a 1 KHz output with settings PR2 204 value and prescaler 4, I am getting a dc signal on the PWM output, PWM Freq =0. Same happens if I want to get a 2500 Kz output. What seems to be the problem? It only works with low Freq like the 200 Hz. Is there any limitation of Frequncy output ? Thank you. |
|
|
Ttelmah Guest
|
|
Posted: Sun Jan 17, 2010 1:25 pm |
|
|
What duty cycle value are you loading?.
Remember that with PR2 = 255 the maximum duty cycle value is 255(short) or 1023(long), but with PR2 = 204, the maximum becomes 204(short) or 819(long). Load a value above this, and the output will just sit high....
Best Wishes |
|
|
jojos
Joined: 30 Apr 2007 Posts: 64
|
|
Posted: Mon Jan 18, 2010 2:19 am |
|
|
OK. I want to have 1 KHz Pwm frequency and to be able to change the duty cycle, by loading the appropriate value to the CCPR1L:CCP1CON<5:4 registers, from 20% to 100% . So with the 3276800 Hz crystal what settings do I have to choose? Thank you. |
|
|
Ttelmah Guest
|
|
Posted: Mon Jan 18, 2010 2:56 am |
|
|
Use the compiler.....
The whole key difference between a compiler, and assembler, is to let it do the work for you. Don't fiddle around accessing the registers directly.
Just use:
Code: |
#define DIVIDER (204)
#define DUTY_MAX (DIVIDER*4+3)
int16 duty;
setup_timer_2(T2_DIV_BY_4,DIVIDER,15); //Change the last value
//If you want to interrupt at a shorter interval
setup_ccp1(CCP_PWM);
//Then 'duty' can go from 0, to DUTY_MAX
duty=DUTY/MAX/2;
set_pwm1_duty(duty); //For 50% duty cycle
|
Best Wishes |
|
|
jojos
Joined: 30 Apr 2007 Posts: 64
|
|
Posted: Mon Jan 18, 2010 3:44 am |
|
|
First of all thank you Ttelmah for your help.I tested it and i got a 50% duty cycle.So i will have to make a matrix that will contain the appropriate values so i can get the duty cycle range that i want.Because my purpose is to learn and not to get a ready solution from the forum users,i want to ask some things.I see from the T2CON configuration that you are using also the postscaler (15 value).From the datasheet of the PIC 18F2520 i can read that "The Timer2 postscaler (see Section 13.0 “Timer2 Module”) is not used in the determination of the PWM frequency".So can you explain to me how you achieve the desired duty cycle % percent (how postscaler interfere's in the calculation e.t.c.)?Thanks again. |
|
|
jojos
Joined: 30 Apr 2007 Posts: 64
|
|
Posted: Mon Jan 18, 2010 8:02 am |
|
|
Hello again.I found that i can adjust the pwm duty cycle from 40% to 80% If i choose 30% i get a dc level signal.If i set for 20% duty cycle i get 80%.What seems to be the problem.Do i have an overflow somewhere that i cant get the desired duty cycle? |
|
|
Ttelmah Guest
|
|
Posted: Mon Jan 18, 2010 9:35 am |
|
|
The maximum duty value, is worked out like this:
Take the 'DIVIDER' value. Shift it left two bits, and fill the two bits with 1's.
So, with DIVIDER=204
0b11001100
Shift left two bits
0b11001100xx
Put in the two 1's
0b1100110011
This would be the maximum value that can go into the 10bit PWM duty.
The low two bits of the duty value, go into DCXB1, and B0 of the CCPXCON register, then the next 8 bits go into CCPRXL
So, for CCP1, read the CCP1CON register, AND it with 15, save this, take the duty value, and it with 3, shift this value left 4 times, then OR this with saved value, and write this back to CCP1CON. Shift the duty value right twice, and write this to CCPR1L.
This is what 'set_pwm1_duty()' does for you....
Best Wishes |
|
|
|