Oshonsoft programs with INTERRUPTS and PARSE

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
18,766
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
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
18,766
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
AAA 306 09.15.gif
 

jjw

Joined Dec 24, 2013
823
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
3,724
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
11,087
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.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
11,087
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
30,703
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
Read RX data
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
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
Read RX data
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
30,703
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.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
11,087
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.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
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
 
Top