View previous topic :: View next topic |
Author |
Message |
pebbert9
Joined: 31 Dec 2010 Posts: 39
|
#USE TIMER and the ISR |
Posted: Sat May 01, 2021 12:50 pm |
|
|
The chip I am using has only 1 timer and the Modbus library takes it over with a
#USE TIMER(TIMER=1,TICK=.1ms,BITS=16, ISR) command.
I need a second timer and I'd like to add my own counter inside the timer1 ISR because the modbus library is constantly resetting the ticks.
Is it possible to add a second counter inside the ISR when using #USE TIMER? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 01, 2021 11:41 pm |
|
|
Why don't you tell us what your PIC is ?
Also tell us the frequency of the PIC's oscillator. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sun May 02, 2021 6:58 am |
|
|
There isn't any PIC made that 'only has one timer'. Even the 16F18313, which
has one 16bit timer, has two more 8bit timers. With a suitably selected
prescaler one of these can generate a high speed tick, or give something
close to the tick required by the MODBUS driver.
So as PCM says, 'tell us what your PIC is'. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun May 02, 2021 7:16 am |
|
|
Is it possible, yes, of course....
Say the ISR is triggered every 1 ms.
You simply have an increment/test inside the ISR for another 'flag'.
Say you need a 10ms flag...
There's a SW RTC program in the code library, that shows one way to do it....
Though using a 2nd timer has benefits.....
LOTS of choices. |
|
|
pebbert9
Joined: 31 Dec 2010 Posts: 39
|
|
Posted: Sun May 02, 2021 10:28 am |
|
|
I'm using the dsPIC33CK32MP502 which has only 1 timer.
Is there an ISR available to put code in if using the #USE TIMER(TIMER=1,TICK=.1ms,BITS=16, ISR directive?
I tried adding
Code: |
#INT_TIMER1
void timer1_int(void) {
cntr++;
} |
But it doesn't seem to work unless I setup the timer manually like
Code: |
setup_timer1(TMR_INTERNAL|TMR_DIV_BY_64, TIME_1_MS);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1); |
Which won't work with the library unless I re-write that part of it. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun May 02, 2021 10:39 am |
|
|
Are you locked into using this MCU? Having only one timer feels very restrictive. |
|
|
pebbert9
Joined: 31 Dec 2010 Posts: 39
|
|
Posted: Sun May 02, 2021 10:48 am |
|
|
I am for it's CAN controller
I just realized it has a CCP module which I've never used before that can act as a timer.
I need to research on how to set it up.... |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun May 02, 2021 10:54 am |
|
|
Sadly, there aren't many PICs with a built in CAN controller...
I use the MCP2515 with the CCS driver for it when I need it though. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sun May 02, 2021 12:07 pm |
|
|
Your chip as well as the single pure 'timer', has eight SCCP modules and
one MCCP module, each of which can be programmed as timers.
Use one of these.
You actually have a total of ten timers available. |
|
|
pebbert9
Joined: 31 Dec 2010 Posts: 39
|
|
Posted: Sun May 02, 2021 3:20 pm |
|
|
The manual is very vague on using the CCP module as a general purpose timer and there isn't much on the forum.
It looks like I would do something like this if I have an 8MHz external crystal (clock=160MHz). It would have an interrupt every 0.1 second, correct?
Code: | setup_ccp1(CCP_TIMER | CCP_DIV_BY_64 | CCP_FOSC | CCP_COMPARE_SET_ON_MATCH | CCP_TIMER_32_BIT);
set_timer_period_ccp1(12500); |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Mon May 03, 2021 12:57 am |
|
|
The key thing to read here is the Microchip application note on these
modules. 300003035b.pdf
Refer to section 5.
Now to use it as a 32bit timer, key thing to note is that you must load
both the 16bit period values. This means the number you give the
set_timer_period function, needs to either be two 16bit values, or needs
to be explicitly a 32bit value (so would need an 'L' after the value).
Currently you are only feeding it a 16bit value.
You don't want 'set_on_match'. That makes the CCP output set.
So (very basic demo):
Code: |
#include <33CK32MP502.h>
#device ICSP=1
#use delay(clock=160000000,crystal=8000000)
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
int count=0;
#INT_TIMERCCP1
void tick(void)
{
count++;
}
void main()
{
setup_ccp1(CCP_TIMER | CCP_DIV_BY_16 | CCP_FOSC | CCP_TIMER_32_BIT);
set_timer_period_ccp1(99999); //one less than the count you want
//since > 65535, forces to be an int32, so both registers are loaded.
enable_interrupts(INT_TIMERCCP1);
enable_interrupts(GLOBAL);
while(TRUE)
{
if (count==10)
{
count=0;
output_toggle(PIN_A0);
}
}
}
|
Since the period here is >65535, this forces it to be a 32bit value, and
thereby load both registers.
You should find this will merrily interrupt at 16*100000 counts of the
FOSC. By using the /16 divisor, ir allows the 32bit timer value to be used.
However you don't need to do this. So:
Code: |
void main()
{
setup_ccp1(CCP_TIMER | CCP_DIV_BY_64 | CCP_FOSC);
//get rid of the 32bit setting & instead /64
set_timer_period_ccp1(24999); //one less than the count you want
//only loading a 16bit value
enable_interrupts(INT_TIMERCCP1);
enable_interrupts(GLOBAL);
while(TRUE)
{
if (count==10)
{
count=0;
output_toggle(PIN_A0);
}
}
}
|
So now the timer is used in 16bit mode with the /64 prescaler.
I think I've got the counts right. Have a play and see...
|
|
|
pebbert9
Joined: 31 Dec 2010 Posts: 39
|
|
Posted: Mon May 03, 2021 10:42 pm |
|
|
Thanks for the help, everything's working fine now. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Tue May 04, 2021 6:56 am |
|
|
Good. Glad you have it working. |
|
|
|