View previous topic :: View next topic |
Author |
Message |
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
Handling Multiple Interrupts... |
Posted: Tue Sep 26, 2006 12:08 pm |
|
|
Hi,
I was reading somewhere about the "Fast" and "High" options for interrupts but I'm planning on implementing a system on a 16f648A that will use the hardware UART RX interrupt and TMR1.
1) I would *like* the TMR1 interrupt to override the RX interrupt, i.e. say the RX causes and interrupt and TMR1 overflows, it'll put the initial PC to the stack, on top the point in the RX isr and service TMR1, and pop 'em in order...any ideas on this?
Note: In th event I do *not* want this from happening how can I prevent it, i.e. force GIE=0 inside each interrupt?
2) How does one initialise the TMR1 interrupt? Will try and figure this out tomorrow.
3) I was reading this on the FAQ:
Quote: | Due to the limited hardware stack of the PIC a limitation of the CCS compiler is the disability to use recursion in functions. This drawback will affect customers if they try to call a function in an interrupt that is also called outside of an interrupt. When you see this warning message, the compiler is letting you know that you are calling a function inside an interrupt that is also called outside of the interrupt. To prevent accidental recursion the compiler will disable interrupts when you call that specific function outside of that interrupt. |
Seems that this will be directed by the compiler - just thought about it, and it does affect me so no worries. Worst case, I can duplicate the functions at the expense of ROM...if needed.
Cheers,
Mike |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 26, 2006 12:24 pm |
|
|
Quote: | I would *like* the TMR1 interrupt to override the RX interrupt, |
1. Use the #priority statement to give priority to the Timer1 interrupt.
2. Test for the timer interrupt while you're inside the #int_rda isr.
Check the TMR1IF bit. If it's set, then a Timer1 interrupt occurred after
the interrupt dispatcher had already vectored you to the #int_rda isr.
Then execute some (presumably short) code to handle the Timer1
interrupt and then clear the TMR1IF bit. Then handle serial port.
Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=906
Scroll down to the #int_ccp isr code. In that code, I check to see
if a Timer1 interrupt has occurred, and if so, I handle it right there. |
|
|
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Tue Sep 26, 2006 1:11 pm |
|
|
Thanks for that
I was just thinking of something else, rather than letting my TMR1 give me a 13ms delay [(1/(Fosc/4)) * 2^16 = (4/Fosc) * 2^16 = ~13msec] what if I set TMR1H:TMR1L = 2^16 - 5000, i.e. 5000*(4/Fosc) = 1msec.
Now this would mean I'd need to set TMR1H:TMR1L = 60536 or 0xEC78, so would writing like this work:
TMR1H = 0xEC;
TMR1L = 0x78;
This in in ref to the 16f648/877 and both datasheets state they these registers are readable and writeable, however, they advise to first STOP the timer before writing to it. This can be done at the init() and inside the ISR for the next iteration, as it would be stopped inside the ISR.
Cheers! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 26, 2006 4:11 pm |
|
|
Quote: | as it would be stopped inside the ISR. |
The timer is not automatically stopped inside the isr. You would have
to put in a line of code to do that.
Quote: | so would writing like this work:
TMR1H = 0xEC;
TMR1L = 0x78; |
CCS has a function to load timer1. It's called set_timer1().
Here's the code from the .LST file (compiled for a 16F877):
Code: |
...... set_timer1(60536);
0016: MOVLW EC
0017: MOVWF 0F // TMR1H
0018: MOVLW 78
0019: MOVWF 0E // TMR1L
|
|
|
|
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Tue Sep 26, 2006 4:53 pm |
|
|
Thanks a lot for your help, simply awesome
I'll just initialise the timer to 60536 as the ISR is exiting, but while in the ISR it can't cause another interrupt as GIE would be disabled.
I'm just used to the regular way of writing to the registers by hand rather than using the inbuilt libraries... |
|
|
|