# Oshonsoft programs with INTERRUPTS and PARSE

#### camerart

Joined Feb 25, 2013
2,050
Hi,
I have a program with an INTERRUPT. This is triggered by $sentences sent from 3x different sources, and they are random, but a few times/second between them. They give DATA into the RX PIN that the MAIN program LOOP processes. As they are INTERRUPTs I assume that each time a$ arrives the LOOP is jumped out of while the INTERRUPT works. I'm guessing that this is not giving the LOOP enough time.

Is there a proceedure to time INTERRUPTs to give a better balance netween them and the MAIN LOOP?

EDIT: Am I correct that an INTERRUPT jumps out of the program LOOP does it's job, then jumps back in at the same point?
Cheers, Camerart.

Last edited:

#### ericgibbs

Joined Jan 29, 2010
10,200
hi C,
If it is the 18Fxxxx series, are you using the High and Low priority interrupt option.?
Keep the Code short as possible in the ISR's , use Flags for the 3 Asynchronous interrupting sources.
Read the Flags in the 'Main' loop and execute Subroutines according to the priority.

E

#### camerart

Joined Feb 25, 2013
2,050
hi C,
If it is the 18Fxxxx series, are you using the High and Low priority interrupt option.?
Keep the Code short as possible in the ISR's , use Flags for the 3 Asynchronous interrupting sources.
Read the Flags in the 'Main' loop and execute Subroutines according to the priority.

E
Hi E,
INTERRUPT below:
This has grown, so I'm not sure if it's too long or not.

Can you describe a FLAG and how to place them please?

Does an INTERRUPT jump out of a LOOP, then back in where it left off?
C
-------------------------------------------------------------------------------
On High Interrupt
Save System

'Await GPS RXD -----------------GPS GNRMC ----------------------
''''''PASTE: $GNRMC,123519,A,4807.038,N,01131.000,W,022.4,084.4,230394,003.1,W*6A? '''OR PASTE:$REMOTE,1100,1200,1300,1400,1500,1600W,? (Nonsense, just for testing)
'''Or paste: $QEIDEG,123,? If RCSTA.OERR = 1 Then 'BIT1..if over run error then flush RXD buffer RCSTA.CREN = 0 RCSTA.CREN = 1 'ENABLES RECEIVER char = RCREG '1 char = RCREG '2 PIR1.RCIF = 0 '0 = The EUSART receive buffer is empty Hserout "RX Err!", CrLf Goto skip1 Endif If PIR1.RCIF = 1 Then nxt_rxin: 'Add timed wait and DATASWITCH here, needs thought!!!!!!!!!!!!!! If PIR1.RCIF = 0 Then Goto nxt_rxin Hserin char If char = "?" Or char = 0x0a Then Goto msg_eol If char = "$" Then
str1(0) = "$" 'CHAR =$
rxi = 0
Endif
If str1(0) = "$" Then str1(rxi) = char rxi = rxi + 1 Goto nxt_rxin If rxi > 79 Then Hserout " OVER STR1 LIMIT", CrLf 'Over STR1() limit rxi = 0 Endif Endif Goto nxt_rxin Endif Goto skip1 ''Hserout CrLf msg_eol: 'strtp = "" 'strpr = "" strtx1 = "" strtx2 = "" strtx3 = "" strtx4 = "" strtx5 = "" 'str1(0) = 0 '???????????????????? strtim = "" strlat = "" strlong = "" msg1 = "" For x = 0 To rxi 'REMOVE Hserout str1(x) Next x Hserout CrLf, CrLf csv = 0 If BAUDCON.RCIDL = 1 Then 'SET DATASWITCH: 'S0=1 S1=0 =TX4431, S0=0 S1=H =HC-12, S0=0 S1=0 =GPS For txi = 1 To rxi char = str1(txi) strchr = Chr(char) If strchr <> "," Then msg1 = msg1 + strchr Else csv = csv + 1 If str1(5) = "C" Then '1 in DATASWITCH sequence Gosub get_valg 'GPS datasw = 2 'Set to next in DATASWITCH sequence Endif If str1(1) = "R" Then '2 in sequence Gosub get_valr 'REMOTE datasw = 3 'Set to next in sequence Endif If str1(1) = "Q" Then '3 in DATASWITCH sequence Gosub get_valq 'QEIDEG datasw = 1 'Set to next in sequence Endif Endif Next txi Endif skip1: Resume -------------------------------------------------------------------------- #### ericgibbs Joined Jan 29, 2010 10,200 hi C, Oh my, that ISR is much too long, have you used Oshonsoft IDE Timer Option to measure the Real time that the PIC is running that ISR.? E Thread Starter #### camerart Joined Feb 25, 2013 2,050 hi C, Oh my, that ISR is much too long, have you used Oshonsoft IDE Timer Option to measure the Real time that the PIC is running that ISR.? E View attachment 204852 Hi E, I had a go, and if I'm correct it takes app 17ms. I used HIGH INTERRUPT EDIT: Yes, I'm using 18LF4620 C. Last edited: #### jjw Joined Dec 24, 2013 540 Hi E, I had a go, and if I'm correct it takes app 17ms. I used HIGH INTERRUPT EDIT: Yes, I'm using 18LF4620 C. If I understand correctly your interrupt routine, it is sometimes looping to read the whole message and then it takes about 100ms at 9600Bd ? Thread Starter #### camerart Joined Feb 25, 2013 2,050 If I understand correctly your interrupt routine, it is sometimes looping to read the whole message and then it takes about 100ms at 9600Bd ? Hi J, It always READs the whole of each of the messages in turn, of varying lengths shown here: The DATA for processing is marked in red. C. ------------------------------------------------------------$GNRMC,123519,A,4807.038,N,01131.000,W,022.4,084.4,230394,003.1,W*6A?
$REMOTE,1100,1200,1300,1400,1500,1600W,? (Nonsense, just for testing)$QEIDEG,123,?
----------------------------------------------------------------------

#### jpanhalt

Joined Jan 18, 2008
9,740
Hi,
I have a program with an INTERRUPT. This is triggered by $sentences sent from 3x different sources, and they are random, but a few times/second between them. They give DATA into the RX PIN that the MAIN program LOOP processes. As they are INTERRUPTs I assume that each time a$ arrives the LOOP is jumped out of while the INTERRUPT works. I'm guessing that this is not giving the LOOP enough time.
After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)? You need to write loops or whatever so they are interrupt tolerant, not allow interrupts during parts that aren't tolerant, or return from an interrupt to a different place. The latter involves messing with the stack.

Is there a procedure to time INTERRUPTs to give a better balance netween them and the MAIN LOOP?
Yes, most definitely. You can use timers as interrupt controllers, or as stated about, if you have a loop that is not interrupt tolerant, turn off interrupts during that loop or return to the beginning, etc.

#### camerart

Joined Feb 25, 2013
2,050
Hi,
Thanks all.
Am I correct that to switch the INTERRUPT OFF/ON I can add DISABLE INTERRUPT, ENABLE INTERRUPT in the MAIN LOOP to suit?
C

#### jpanhalt

Joined Jan 18, 2008
9,740
The interrupt structure for 18F chips is somewhat different from the mid-range chips. On the latter, you do not have priorities to deal with. As for your question about that code to write, I can't help, but I am sure the answer is in the appropriate documentation. Do you want to disable ALL interrupts or just low priority ones. etc.?

#### MrChips

Joined Oct 2, 2009
21,337
Ideally, you want to spend the minimum amount of time in the ISR (interrupt service routine).
This means that there should be no loops and no polling of any flag.

For an ISR that services UART RX (received character) here is the structure of an interrupt service.

Enter ISR
Clear RX HW IRQ flag
If char is end_of_message (e.g. CR) send EOM semaphore
else store char in next location of message buffer
If message buffer is full, set buffer_full semaphore
Exit ISR

#### camerart

Joined Feb 25, 2013
2,050
The interrupt structure for 18F chips is somewhat different from the mid-range chips. On the latter, you do not have priorities to deal with. As for your question about that code to write, I can't help, but I am sure the answer is in the appropriate documentation. Do you want to disable ALL interrupts or just low priority ones. etc.?
Hi J,
There is only 1x HIGH priorityINTERRUPT started by a $. This then READs the$Sentence that is at the RX. After it has been READ, it switched a DATASWITCH to the next $input, and waits for the next$Sentence, and so on in a loop.
C.

#### camerart

Joined Feb 25, 2013
2,050
Ideally, you want to spend the minimum amount of time in the ISR (interrupt service routine).
This means that there should be no loops and no polling of any flag.

For an ISR that services UART RX (received character) here is the structure of an interrupt service.

Enter ISR
Clear RX HW IRQ flag
If char is end_of_message (e.g. CR) send EOM semaphore
else store char in next location of message buffer
If message buffer is full, set buffer_full semaphore
Exit ISR
Hi MrC,
This is going to take a bit of time to understand, not to mention re-write.

Am I correct that the LOOPs in the INTERRUPT I posted, must be moved to the MAIN LOOP?
C.

#### MrChips

Joined Oct 2, 2009
21,337
Hi MrC,
This is going to take a bit of time to understand, not to mention re-write.

Am I correct that the LOOPs in the INTERRUPT I posted, must be moved to the MAIN LOOP?
C.
No. There is no need for a loop while waiting for a complete message to arrive.
You capture every character coming in using interrupts and save it in a buffer.

The main program only acts on the complete message once it has received notice that the message is complete.
In the meantime the main program can continue doing what it needs to do.

#### camerart

Joined Feb 25, 2013
2,050
No. There is no need for a loop while waiting for a complete message to arrive.
You capture every character coming in using interrupts and save it in a buffer.

The main program only acts on the complete message once it has received notice that the message is complete.
In the meantime the main program can continue doing what it needs to do.
Hi MrC,
The clever sections of the program were written by member of this and other forums over years, as I'm not capable of more than basic programming, I'm afraid. I can just about understand how it has been done so far, by the help of the Oshonsoft simulator. Each \$message gets stored in a VARIABLE.
C

#### camerart

Joined Feb 25, 2013
2,050
After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)? You need to write loops or whatever so they are interrupt tolerant, not allow interrupts during parts that aren't tolerant, or return from an interrupt to a different place. The latter involves messing with the stack.

Yes, most definitely. You can use timers as interrupt controllers, or as stated about, if you have a loop that is not interrupt tolerant, turn off interrupts during that loop or return to the beginning, etc.
Hi J2,
Q/ After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)?
A/ I ran the program in the simulator, and it has answered both our questions, that the INTERUPT does jump out of the MAIN LOOP, and RESUME to whence it left off.
C.

#### camerart

Joined Feb 25, 2013
2,050
After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)? You need to write loops or whatever so they are interrupt tolerant, not allow interrupts during parts that aren't tolerant, or return from an interrupt to a different place. The latter involves messing with the stack.

Yes, most definitely. You can use timers as interrupt controllers, or as stated about, if you have a loop that is not interrupt tolerant, turn off interrupts during that loop or return to the beginning, etc.
Hi J2,
Q/ After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)?
A/ I ran the program in the simulator, and it has answered both our questions, that the INTERUPT does jump out of the MAIN LOOP, and RESUME to whence it left off.
C.

#### jpanhalt

Joined Jan 18, 2008
9,740
Hi J2,
Q/ After the interrupt, doesn't the program return from whence it came and continue (as you suggest in your edit)?
A/ I ran the program in the simulator, and it has answered both our questions, that the INTERUPT does jump out of the MAIN LOOP, and RESUME to whence it left off.
C.
Yes, interrupts always return to the place in code from which they came, unless you write code to make them do otherwise. Since you have access to the stack, with a little care you can return to any other place in the program you want. That is mentioned only as an option for the sake of completeness, not as a recommendation.

#### camerart

Joined Feb 25, 2013
2,050
Yes, interrupts always return to the place in code from which they came, unless you write code to make them do otherwise. Since you have access to the stack, with a little care you can return to any other place in the program you want. That is mentioned only as an option for the sake of completeness, not as a recommendation.
Hi J2,
I don't understand #14 INTERRUPTs and BUFFERS, but maybe I can find out.
I suppose that if 'ENABLE INTERRUPT and DISABLE INTERRUPT' start and stop the HSERIN, then perhaps I can DISABLE till the end of the LOOP, then ENABLE so it 'gets' the DATA, then DISABLE and go through the LOOP again. I'll have to think about it, or be advised.
C