1 Attachment(s)
Instant Interrupts - Revisited
This is a series of include files that simplify the process of creating interrupt driven programs for PicBasic Pro. MPASM required.
Once you try this, you may never use ON INTERRUPT again.
Features:Assembly language Interrupts
Basic language Interrupts
Both ASM and Basic interrupts in the same program
Service Multiple Interrupt sources
Prioritized execution order
Very easy to use
No ON INTERRUPT "Code Bloat"
No ON INTERRUPT " I'll service your interrupt whenever I feel like it." mentality.
.
One of the best things about this system, is that you don't have to remember where all the Enable bits and Interrupt flags are located.
Each interrupt "source" is given a unique name that is used to reference it.
The system "Looks Up" the correct bit locations for that name. Reducing those RTFM sessions to a minimum.
The following table lists the Named Interrupts.
Note: More interrupts have been added .. please visit http://darreltaylor.com/DT_INTS-14/intro.html
Available Interrupt Sources 14-bit
Code:
INT_INT -- INT External Interrupt
RBC_INT -- RB Port Change Interrupt
TMR0_INT -- TMR0 Overflow Interrupt 16F
TMR1_INT -- TMR1 Overflow Interrupt
TMR2_INT -- TMR2 to PR2 Match Interrupt
TX_INT -- USART Transmit Interrupt
RX_INT -- USART Receive Interrupt
CMP_INT -- Comparator Interrupt
EE_INT -- EEPROM/FLASH Write Operation Interrupt
BUS_INT -- Bus Collision Interrupt
PSP_INT -- Parallel Slave Port Read/Write Interrupt
AD_INT -- A/D Converter Interrupt
SSP_INT -- Master Synchronous Serial Port Interrupt
CCP1_INT -- CCP1 Interrupt
CCP2_INT -- CCP2 Interrupt
Here's a simple example of toggling an LED using the external interrupt (INT). (Hello World)
Code:
LED1 VAR PORTB.1
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE INT_INT ; enable external (INT) interrupts
ENDASM
Main:
PAUSE 1
GOTO Main
'---[INT - interrupt handler]---------------------------------------------------
ToggleLED1:
TOGGLE LED1
@ INT_RETURN
Code Size = 234 words
This project, and it's associated files, have been moved.
Please download them from my website.
DT_INTS-14 (12F-16F)
http://darreltaylor.com/DT_INTS-14/intro.html
DT_INTS-18 (18F)
http://darreltaylor.com/DT_INTS-18/home.html
.
The Base Layer - ASM interrupts
<table cellpadding=6><tr><td valign=center>http://www.darreltaylor.com/files/INT_Layers_asm.gif</td><td>The Instant Interrupt System consists of several "Layers".
The Bottom Layer is "DT_INTS-14.bas". This file contains everything required to use Interrupts at the ASM level. It handles all of the "Context Saving/Restoring", detects which interrupt has been triggered, and calls the appropriate "User Routine".
The next layer up is created from the INT_LIST macro you define in the program. It defines the Interrupt sources to use and the corresponding subroutines that will be called. They can be either simple subroutines, or complete "Modules" in a separate Include file, like the Elapse Timer. Up to 14 separate INT_Handler's can be in the LIST.
And, the Top Layer is the normal PBP program that runs in the foreground.
If Basic Laguage interrupts are not being used, then DT_INTS-14.bas is the only file you need to include.</td></tr></table>Here's another example of a Blinky Light program using TMR1 with an Assembly Language Interrupt handler
Code:
LED1 VAR PORTD.0
LOW LED1 ; Set to Output Low
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, ToggleLED1, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
ENDASM
T1CON = $31 ; Prescaler=8, TMR1ON
Main:
PAUSE 1
GOTO Main
'---[TMR1_INT - interrupt handler]------------------------------------------
ASM
ToggleLED1
btfsc _LED1
goto $+3
bsf _LED1
goto $+2
bcf _LED1
INT_RETURN
ENDASM
<font size=-3>Code Size = 104 Words</font>
Notice that the INT_Handler's Type is ASM, and the Label does not have an underscore before it.<hr><table cellpadding=6><tr><td>http://www.darreltaylor.com/files/INT_Layers_pbp.gif</td><td valign=top>By using this type of Layering scheme. It allows us more flexability, depending on the type of interrupt we want to use. If we want to add Basic Language Handlers, all we need to do is Include "ReEnterPBP.bas", and it will insert another Layer in-between the Base and the Handlers.
With this layer included, you can have any combination of ASM and PBP interrupts in the same program</td></tr></table>
<br>
ReEnterPBP.bas - An adaptation of INT_CTRL.pbp
October 05, 2002 was a good day. Because that's the day that Tim Box released his "INT_CTRL.pbp" program. The original "Instant Interrupts"
Tim had discovered that the only reason you couldn't use Basic statements in a normal interrupt, was because the PBP system variables currently being used by the statement that got interrupted, would be overwritten by the Basic statements in the interrupt routine. And that, all you have to do is save the state of the system vars at the start of the interrupt, and restore them back to the way they were before exiting the interrupt and you can use any Basic statements you want.
I've probably said it too many times already but ... Thanks again Tim!
<hr>
ReEnterPBP.bas is an adaptation of the same concept, but it allows the Interrupt system to determine if it needs to save the variables or not.
For instance, if you have a program with both ASM and PBP interrupt handlers, and an interrupt triggers an ASM handler, there's no need to save the variables first, it would just be waisting valuable time. And if more than 1 Basic handler is triggered at the same time, it only saves the variables once, and processes all the Interrupts on the same pass, before restoring the system vars, again saving time.
However, it does still take a lot of time to save all those variables. Usually it takes around 70 instruction cycles to save the vars. Then another 70 cycles to restore them again. At 4mhz it's 140us total save and restore time, which limits the maximum interrupt frequency to just over 7khz. At 20mhz OSC, you can go up to almost 36khz. That's fast enough to receive RS232 at over 250Kbaud with the USART. But is still considerably slower than you can get with ASM interrupts.
<br>
DT_INTS-18 Interrupts for 18F's Now Available
<table><tr><td>http://www.darreltaylor.com/files/Fireworks_5.gif</td><td>
At long last.
The Instant Interrupt system for 18F PIC's is now available.
It's become increasingly harder to keep things up to date here on the forum, so I've moved everything over to my website.
I'm still working on some of the pages, but everything you need is already there. It seems to take longer to make the web pages, than it does to write the program. :)
http://darreltaylor.com/DT_INTS-18/home.html</td></tr></table>
<br>
Advanced Blinky Light (fader)
Chris,
The prescaler can be changed with T1CON.
$31 = 1:8
$21 = 1:4
$11 = 1:2
$01 = 1:1
And the Timer is reloaded by putting values in TMR1H:TMR1L.
So first, decide what frequency you need, I'll go with 100hz.
Then, go to this thread...
Testing Forms [TimerCalc] Working I think?
http://www.picbasic.co.uk/forum/showthread.php?t=2031
Enter the OSC value you are using, say 20mhz.
I'll also go with 1:1 prescaler, enter that. (ok, it's already there)
Then enter 100 in the Freq field at the bottom.
Now you can see that it will take a total of 50,000 counts (ticks) to achieve 100hz.
Decide what resolution you want for the Duty-Cycle. ummm, 8-bit (256).
Now you just calculate the ON count from that with...
50000*DutyCycle/256 which is the same thing as...
50000*/DutyCycle in PBP
and the OFF count is 50000 - ONcount
Ok, so let's put that into the Blinky Light example
Code:
; Initialize your hardware first.
INCLUDE "DT_INTS-18.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts
LED1 VAR PORTB.1
DutyCycle VAR BYTE
TotalCount CON 50000
ONcount VAR WORD
OFFcount VAR WORD
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
T1CON = $00 ; Prescaler=1:1, TMR OFF
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
Main:
FOR DutyCycle = 0 TO 255 ; Ramp up
GOSUB SetDutyCycle
PAUSE 5
NEXT DutyCycle
FOR DutyCycle = 254 TO 1 STEP -1 ; Ramp down
GOSUB SetDutyCycle
PAUSE 5
NEXT DutyCycle
GOTO Main
SetDutyCycle:
ONcount = TotalCount*/DutyCycle
OFFcount = TotalCount - ONcount
IF DutyCycle = 0 THEN
T1CON.0 = 0 ; turn off timer
LOW LED1 ; idle LOW
ELSE
T1CON.0 = 1 ; timer on if DutyCycle > 0
ENDIF
RETURN
DISABLE DEBUG
'---[TMR1 - interrupt handler]------------------------------------------------
@Timer1=TMR1L ; map timer registers to a word variable
Timer1 VAR WORD EXT
ToggleLED1:
IF LED1 THEN
LOW LED1
T1CON.0 = 0 ; stop the timer
Timer1 = OFFcount ; Load OFF count
T1CON.0 = 1 ; start timer
ELSE
HIGH LED1
T1CON.0 = 0 ; stop the timer
Timer1 = ONcount ; Load ON count
T1CON.0 = 1 ; start timer
ENDIF
@ INT_RETURN
ENABLE DEBUG