|
|
View previous topic :: View next topic |
Author |
Message |
Alel8
Joined: 20 Jan 2017 Posts: 2
|
PIC18F CCP (PWM) and Timers1/3 interrupts problem |
Posted: Fri Jan 20, 2017 12:06 pm |
|
|
Hello everyone,
PCM programmer and Ttelmah, THANKS because you have solved many problems I had, and by searching on the forum you already solved the problem. But I need your help now, please!
I have a PIC18F2685, and I'm using the CCP1 to produce a PWM signal. I'm also using timer_0 as a millisecond event counter.
Code: | setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,249,10); //freq PWM
setup_timer_3(T3_DISABLED);
setup_ccp1(CCP_PWM); //CCP pin PWM
set_pwm1_duty(1000); //Dc 100% = 1000 |
I setup the timer2 with the desired frequency and everything worked fine, until now that I added timer3 to generate an event after a certain amount of time after another event.
Code: | //some event()
{
set_timer3(43036); //45 ms //2^16 - ms/(4/Fosc*DIV) , Fosc 16 MHz , DIV 8 | 53036 - 25 ms | 50536 - 30 ms | 43036 - 45 ms // 50 ms max timeout
setup_timer_3(T3_INTERNAL|T3_DIV_BY_8);
} |
I tried it with "timer_1" instead of "timer_3" and makes no difference.
This caused the PWM signal to disappear, no longer PWM output on CCP1 pin (RC2).
I tried changing timer3 with timer1 and the problem still exists.
The problem, as I have seen so far, is with the Interrupts:
Code: | #int_TIMER1
void TIMER1_isr(void)
{
//do things
setup_timer_1(T1_DISABLED);
} |
or
Code: | #int_TIMER3
void TIMER3_isr(void)
{
//do things
setup_timer_3(T3_DISABLED);
} |
If I disable this part of code, the PWM works fine.
Why are timer1/3 affecting the CCP module? In PWM mode is not only timer2?
What can I do to fix this, please?!
Thanks in advance!!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 20, 2017 12:29 pm |
|
|
Can you post a complete test program that shows the problem ?
In other words, if the problem is that enabling Timer3 shuts down CCP1,
then post a program that demonstrates this. Post the #include for the
PIC, #fuses, #use delay(), main(), etc. It should be compilable.
Leave out any code that isn't related to the problem.
Also post your compiler version. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sat Jan 21, 2017 2:01 am |
|
|
It certainly shouldn't affect the CCP.
The classic thing is to simplify. Just generate a minimum program generating the PWM, and running Timer3. Does it work?. If not, then this becomes something you can post so that we can look at the problem.
The obvious thing that changes, is whatever is in '//Do Things', so this would be the first place to look. If you remark out this code, what happens?. Obvious things to look for here:
Anything changing TRIS on the PWM port.
Anything touching the timers.
Anything accessing arrays of using pointers (which might 'overflow' and therefore affect other registers.
Where are you setting up the PWM?. Before or after you setup Timer3?.
The other things that may be happening, is that the code is simply never reaching the PWM setup. If you are executing too many interrupts, and they contain code that takes significant time, it's possible that effectively the main code is never actually getting executed. You mention a 1mSec counter, and show this using the RTC as an /256 counter. This implies potentially an interrupt every 256 instructions. If this is executing a handler, even if this does nothing at all, immediately 25% of your processor's time will be being used handling this. If you then add another interrupt at 45mSec, and this takes perhaps 35mSec to execute it's code, suddenly there is no time let to do anything.
It takes quite a bit of time to get into and out of an interrupt handler. Typically something like 60 instructions. This is why it is better to keep the number of interrupts low if possible. If you want a timer, then consider if you could do this by just reading the timer registers, rather than having an interrupt. If you have a 1mSec timer, and want a 45mSec one, then just add a counter in the 1mSec interrupt (uses less time provided it is a simple int8, than calling another interrupt). However many interrupts you have though repeat the mantra fifty times _spend as little time as possible inside the handler_.
As one further comment to this, if 256 instructions is about 1mSec, this implies the chip is only being clocked at 1MHz. Honestly if you want to have an interrupt at 1mSec, you need to be clocking the chip faster than this. However your comment on Timer3 setup, says you are using 16MHz, which would imply timer1 interrupting every 64uSec... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jan 21, 2017 4:13 pm |
|
|
He said in a PM to me that upon trying to make a test progarm, it all
started working fine. |
|
|
Alel8
Joined: 20 Jan 2017 Posts: 2
|
|
Posted: Sat Jan 21, 2017 4:48 pm |
|
|
Ttelmah wrote: | As one further comment to this, if 256 instructions is about 1mSec, this implies the chip is only being clocked at 1MHz. Honestly if you want to have an interrupt at 1mSec, you need to be clocking the chip faster than this. However your comment on Timer3 setup, says you are using 16MHz, which would imply timer1 interrupting every 64uSec... |
I'm clocking with a 4MHz crystal and the x4 PLL enabled, and the timer0 is 16bit mode and I precharge a value of around 61600 so it generates an interrupt on overflow every 1000us.
PCM programmer wrote: | He said in a PM to me that upon trying to make a test progarm, it all
started working fine. |
In the test program it works fine, but in the "bigger" one it doesn't. I had to add another setup_ccp(PWM); just before entering the while(1) loop inside the main routine and that seems to work. I will keep trying to find the problem. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Jan 22, 2017 5:34 am |
|
|
Your timer0 code is never going to be very accurate. You are attempting to tweak the loaded value to adjust for the instructions it takes to go into the interrupt (fair enough)_, but if another interrupt occurs, the tweak will be wrong.
Why do this?. You already have Timer2 ticking at exactly 1000HZ. Pointless to setup another timer and try to 'fiddle' it's timings. Just put the timer2 postscaler down to 1, and have a timer2 interrupt like:
Code: |
#INT_TIMER2
{
static int8 hundredth_tick=9;
//assuming you do want to handle something every ten times
if (hundredth_tick==0)
{
hundredth_tick=9;
//Your existing int_timer2 code
}
else
--hundredth_tick;
//Now your 1mSec code
}
|
The test & decrement will take no more instructions than you currently have loading the 16bit timer value , and implies one less interrupt to worry about... |
|
|
|
|
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
|