|
|
View previous topic :: View next topic |
Author |
Message |
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
set_pwm1_duty(0); Is not outputing 0%! |
Posted: Thu Jul 05, 2012 5:32 pm |
|
|
Hello guys! I am currently working in a project with the PIC18F2550 and when I use the set_pwm1_duty(0); function call I still get a very small pulse of 1uS, but I was expecting to get a flat line i.e. 0% PWM right?
My configurations are:
Code: |
#include <18F2550.h>
#device adc=10
//#FUSES HS //No Watch Dog Timer
#FUSES PLL5 //Divide By 5(20MHz oscillator input)
#FUSES CPUDIV1
#FUSES HSPLL //High Speed Crystal/Resonator with PLL enabled
//#use delay(crystal=20000000, clock=10000000)
#use delay(clock=20000000)
setup_timer_2(T2_DIV_BY_16,125,1);
using an 20MHz crystal.
I have also tried to configure the registers myself using this:
#byte CCP1CON = getenv("SFR:CCP1CON")
#byte CCPR1L = getenv("SFR:CCPR1L")
#byte CCP2CON = getenv("SFR:CCP2CON")
#byte CCPR2L = getenv("SFR:CCPR2L")
bit_clear(CCP2CON,5);
bit_clear(CCP2CON,4)
|
but still it behaves the same way....
My test code is a very simple one...I mixed the test inside an old code, so that's why I am setting so many things
Code: |
void main(void)
{
delay_us(10);
output_a(0x04);
output_b(0x00);
output_c(0x00);
output_high(DISABLE);
set_tris_a(0b00000011);
set_tris_b(0b11010111);
set_tris_c(0b10000001);
output_high(DISABLE);
output_low(BHI);
output_low(AHI);
output_low(LED);
output_low(ALI);
output_low(BLI);
port_b_pullups(FALSE);
if (!input(CONFIG_EMR))
configuraLimitesRC();
carregaConfiguracoes();
//configurando o PWM
//setup_timer_2(T2_DIV_BY_4,249,1); //200 us overflow, 200 us interrupt
setup_timer_2(T2_DIV_BY_16,125,1); //200 us overflow, 200 us interrupt
set_pwm1_duty(0);
set_pwm2_duty(0);
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
set_pwm1_duty(0);
set_pwm2_duty(0);
delay_ms(10);
set_pwm1_duty(499);
set_pwm2_duty(499);
delay_ms(10000);
set_pwm1_duty(0);
set_pwm2_duty(0);
/*bit_clear(CCP2CON,5);
bit_clear(CCP2CON,4);
CCPR2L = 0;
bit_clear(CCP1CON,5);
bit_clear(CCP1CON,4);
CCPR1L = 0; */
delay_ms(20000);
//configurando o ADC
setup_adc_ports(AN0_TO_AN1);
setup_adc(ADC_CLOCK_INTERNAL );
//configurando os timers
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); //26.2 ms overflow 0.4us resolution, usado em Tempo inicial e final do RC e Fail Safe
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
//configurando as interrupcoes
enable_interrupts(INT_EXT2);
enable_interrupts(GLOBAL);
output_low(DISABLE);
while(TRUE)
{
}
}
|
As you can see I am setting the PWM to 100% and then bringing it to 0%....but I dont get 0%! I still get a 1us pulse! (I know this code makes more than that, but I am looking at the behavior of the begining, sice there are 30s to look at).
In another function call this behavior is intermintent...I call this function many time, and sometimes there is a flat line, sometimes there is the 1us pulse....does anyone has any ideas why is this happening?
Thank's a lot!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 05, 2012 6:16 pm |
|
|
Your test program is too complicated. Try this program instead and see
what you get:
Code: |
#include <18F2550.h>
#fuses INTRC_IO, NOWDT, PUT, BROWNOUT, NOLVP, CPUDIV1
#use delay(clock=4M)
//=================================
void main()
{
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 125, 1);
while(1)
{
// Run for 3 seconds.
set_pwm1_duty(63); // 50% duty cycle
delay_ms(3000);
// Stop for 3 seconds.
set_pwm1_duty(0); // PWM off
delay_ms(3000);
}
} |
|
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Thu Jul 05, 2012 6:33 pm |
|
|
I got
Error 111: Unknown keyword in #fuses INTRC_IO |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 05, 2012 6:40 pm |
|
|
What is your CCS compiler version ? Compile a test program so that
it doesn't give any errors (remove the INTRC_IO and put in HS).
Then go to your project directory and view the .LST file. At the top, it
will have a 4-digit number, like the ones in this list:
http://www.ccsinfo.com/devices.php?page=versioninfo
What is your version ? |
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Thu Jul 05, 2012 6:41 pm |
|
|
I modified your code to:
Code: |
#include <18F2550.h>
#fuses NOWDT, PUT, BROWNOUT, NOLVP, CPUDIV1
#use delay(clock=20M)
//=================================
void main()
{
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 125, 1);
while(1)
{
// Run for 3 seconds.
set_pwm1_duty(99); // 50% duty cycle
delay_ms(3000);
// Stop for 3 seconds.
set_pwm1_duty(0); // PWM off
delay_ms(3000);
} |
and it compiled and worked! 0 was 0 as expected ! I think my problem is my timer configurations in the FUSES.... I am using an 20MHz crystal and I want to bring the PIC to 48MHz with PLL and everything else....can you see any problems in my #FUSES?
Thanks! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 05, 2012 7:03 pm |
|
|
Nope. No version, no help. Different versions have different bugs.
I can't give a real answer without the version. I'm going home for
the day now. |
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Thu Jul 05, 2012 7:32 pm |
|
|
Version 4.120...no problem, this is not urgent, I can wait your reply!
CCS PCM C Compiler, Version 4.120, 5967 06-jul-12 04:43 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 06, 2012 12:49 pm |
|
|
Quote: | Version 4.120.
I am using an 20MHz crystal and I want to bring the PIC to 48MHz with PLL.
|
This program will run the PIC at 48 MHz. The PWM frequency will be
5.952 KHz:
Code: |
#include <18F4550.h>
#fuses HSPLL, NOWDT, PUT, BROWNOUT, NOLVP,PLL5, CPUDIV1
#use delay(clock=48M)
//=================================
void main()
{
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 125, 1);
while(1)
{
// Run for 3 seconds.
set_pwm1_duty(63); // 50% duty cycle
delay_ms(3000);
// Stop for 3 seconds.
set_pwm1_duty(0); // PWM off
delay_ms(3000);
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Jul 07, 2012 12:59 pm |
|
|
There is a key thing that will cause this problem.
It is the old difference between an int16, and an int8 behaviour.
If you use:
set_pwm1_duty(0);
This sets the top 8bits if the 10bit pwm to zero, _but does not update the low two bits_. So if the PWM has already been driven by a 10bit value which sets these to a non zero value, they will stay non zero, and you will get the tiny pulse.
set_pwm1_duty(0L);
will set all ten bits to zero.
Best Wishes |
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Sat Jul 07, 2012 9:20 pm |
|
|
Ttelmah thanks a lot for your answer! I would never thought about something like that....monday, when I will be back to the lab, I will test it and see if that fixes everything.
But I already had tried (as I posted before)
Code: |
#byte CCP1CON = getenv("SFR:CCP1CON")
#byte CCPR1L = getenv("SFR:CCPR1L")
#byte CCP2CON = getenv("SFR:CCP2CON")
#byte CCPR2L = getenv("SFR:CCPR2L")
bit_clear(CCP2CON,5);
bit_clear(CCP2CON,4);
CCPR2L = 0;
bit_clear(CCP1CON,5);
bit_clear(CCP1CON,4);
CCPR1L = 0;
|
and it didn't work also...but as far as I can see this code does the same thing that you proposed right? Setting all the bytes from the PWM to 0?
Best Regards! |
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Mon Jul 09, 2012 2:46 pm |
|
|
Ttelmah, thank you again! It worked! 0% PWM is 0 now :D
But I still dont understand why when I set the registers to 0 it didnt work?
Another quick question:
When I call:
set_pwm1_duty(PWM);
And PWM is an unsigned int 16 variable, it will get all the bytes all the time right? So I dont have to force it with a type cast, right?
Best Regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Jul 10, 2012 1:17 am |
|
|
Yes, if the variable being passed, is an int16, full 10bit update is done.
Just FYI, thought setting the bits would appear it should work, I have met this before.
You can do it 'manually', with:
Code: |
CCPR1L = 0;
CCP1CON=CCP1CON & 0xCF;
|
Though the data sheet implies the bits are latched on the next update of the PWM, and makes no mention of requiring them needing writing in a particular order, it only seems to work 'right', if you update the separate bits _after_ updating the register, and, change both in a single instruction. There is nothing in the data to say the other way won't work, but on some chips, it just doesn't.....
The CCS routine I knew 'worked', so easiest to use it.
Best Wishes |
|
|
mfeinstein
Joined: 05 Jul 2012 Posts: 35
|
|
Posted: Tue Jul 10, 2012 7:09 pm |
|
|
Oh, that's tricky!
Anyways, thank you very much for your help, everything seems to be working perfectly now! You are my hero ; )
Best Regards! |
|
|
|
|
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
|