How to stop a program HSERIN blocking

Thread Starter

camerart

Joined Feb 25, 2013
3,730
I'm thinking this code may be more "correct":
nxt_rxin:
If PIR1.RCIF = 0 Then 'char = nothing
str1(0) = 0
rxi = 0
Goto skip1
Else
nxt_rxchk:
If PIR1.RCIF = 1 Then 'CHAR = $ or other 'No need for this line, check at end instead
You already know PIR1.RCIF =1 because the test above for =0 is false

Hserin char
If char = "?" Or char = 0x0a Then Goto msg_eol
If char = "$" Then
str1(0) = "$" 'CHAR = $
rxi = 1
If str1(0) = "$" Then
For x = 1 To rxi
Goto nxt_rxin
str1(rxi) = char
rxi = rxi + 1
if rxi > "limit" then goto someerror
'If char <> "$" Then'????????????????????
Next x
'Endif'?????????????????????
Endif
Endif
Endif
If PIR1.RCIF = 1 Then goto nxt_rxchk
Endif
Hi S,
"Wrong wrong" Apology not necessary, I encourage free speech, and it reminds me that it can be frustrating, for contributors.

Here is your modified CODE, plus 4x frames from the SIM which I hope help to illustrate what's happening.

Note;
RCREG and PIR1.RCIF in Special function registers.
SEND STRING BOX and RXBUFFER 1 and 2.

Even though there is a $sentence in the SEND STRING BOX, a '0' appears, which when READ by [ If PIR1.RCIF = 0 Then ] appear that there is no CHAR and goes to SKIP1
C
 

Attachments

Last edited:

sagor

Joined Mar 10, 2019
912
A possible issue, is it possible that you are receiving characters while doing your HSEROUT routine(s)? If so, then you may be missing characters and OERR gets set???
Since HSEROUT can take some time to process, you may have to check PIR1.RCIF more often, even while outputting a string, to see if there is a reason to stop HSEROUT and go back to reading the UART.

That is why a lot of responses here have stated to use interrupts for the RX routine, to receive a character and put it in a buffer (and check for completed string and flag it) then return to the main program. The main program checks the status of the RX buffer, to see if it is full or not. This type of coding enable simultaneous RX(HSERIN) and HSEROUT without each interfering with each other.

Remember in the Oshonsoft SIM (I' assuming you are using that?), that it takes several clock cycles to fill the UART buffer, and you may have to run code several statements before the UART gets flagged. That is, when you input a string in the SIM, the program does not immediately see the first character until some time later when the UART clocks it into the RCREG. AT 9600 baud and a 4Mhz CPU, it would take 1mS for a character to arrive in the UART, which is 1000 CPU cycles of 1uS each. You have to run the SIM through a lot of code lines before the first character arrives into the UART. It does not just happen when you enter the string into the SIM UART simulator.
In the Hardware UART Simulation panel, you will see under the "Status" area of both TX and RX, two lines that show TX or RX "in progress". If anything is still in progress, it will not be in the buffer yet, nor will PIR1.RCIF be set.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
A possible issue, is it possible that you are receiving characters while doing your HSEROUT routine(s)? If so, then you may be missing characters and OERR gets set???
Since HSEROUT can take some time to process, you may have to check PIR1.RCIF more often, even while outputting a string, to see if there is a reason to stop HSEROUT and go back to reading the UART.

That is why a lot of responses here have stated to use interrupts for the RX routine, to receive a character and put it in a buffer (and check for completed string and flag it) then return to the main program. The main program checks the status of the RX buffer, to see if it is full or not. This type of coding enable simultaneous RX(HSERIN) and HSEROUT without each interfering with each other.

Hi S,


Remember in the Oshonsoft SIM (I' assuming you are using that?), that it takes several clock cycles to fill the UART buffer, and you may have to run code several statements before the UART gets flagged. That is, when you input a string in the SIM, the program does not immediately see the first character until some time later when the UART clocks it into the RCREG. AT 9600 baud and a 4Mhz CPU, it would take 1mS for a character to arrive in the UART, which is 1000 CPU cycles of 1uS each. You have to run the SIM through a lot of code lines before the first character arrives into the UART. It does not just happen when you enter the string into the SIM UART simulator.
In the Hardware UART Simulation panel, you will see under the "Status" area of both TX and RX, two lines that show TX or RX "in progress". If anything is still in progress, it will not be in the buffer yet, nor will PIR1.RCIF be set.
Hi S,
I've found a few issues with my CODE section, apart from your noted 'Time needed for characters to be processed'
I'll re-try.
Thanks.

EDIT: Ive been reading the D/S and getting more confused, but was this and wondered if it could be useful for this 'USART missing characters' situation?
__________________________________________________________
The second method uses the auto-wake-up feature described in Section 18.2.4 “Auto-Wake-up on SyncBreak Character”. By enabling this feature, the EUSART will sample the next two transitions on RX/DT,cause an RCIF interrupt and receive the next data byte followed by another interrupt.
_________________________________________________________-

C.
 
Last edited:

sagor

Joined Mar 10, 2019
912
Auto-wake is only relevant when you put the PIC to "SLEEP" mode. Unless you do that, you can ignore all of section 18.2.4 (if you run the PIC steady ON, with no sleep mode, ignore that section).
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Auto-wake is only relevant when you put the PIC to "SLEEP" mode. Unless you do that, you can ignore all of section 18.2.4 (if you run the PIC steady ON, with no sleep mode, ignore that section).
Hi S,
Ok, thanks.
Am I correct that READ RCREG is only for resetting the register? I notice RCREG and PIR1.RCIF are not in sync when watching, the SIM (Oshonsoft).
C
 

sagor

Joined Mar 10, 2019
912
Reading RCREG is to actually read the character in the buffer. There is only a character in RCREG when PIR1.RCIF = 1. No exceptions to that rule.
As long as PIR1.RCIF = 1, there is a character to read in the UART buffer. That is the "golden rule". Period....

PIR1.RCIF is cleared automatically by the UART when the last character is read from RCREG, you cannot clear it via a programing command....

RCREG will fill up once all bits are received by the UART, then transferred to RCREG buffer. Once that happens, PIR1.RCIF will be set, a few clock cycles later. There is a bit of delay (a few clock cycles) between the UART received data register full and transferring the character to RCREG

According to Figure 18-7 in the D/S, RCIF is set about 1/2 way through the stop bit of the character received. At 9600 baud, that is about 50uS into the stop bit. That is 50 CPU instructions (approx.) with a 4Mhz PIC crystal.... You can do a lot of code in that 50uS....
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Reading RCREG is to actually read the character in the buffer. There is only a character in RCREG when PIR1.RCIF = 1. No exceptions to that rule.
As long as PIR1.RCIF = 1, there is a character to read in the UART buffer. That is the "golden rule". Period....

PIR1.RCIF is cleared automatically by the UART when the last character is read from RCREG, you cannot clear it via a programing command....

RCREG will fill up once all bits are received by the UART, then transferred to RCREG buffer. Once that happens, PIR1.RCIF will be set, a few clock cycles later. There is a bit of delay (a few clock cycles) between the UART received data register full and transferring the character to RCREG

According to Figure 18-7 in the D/S, RCIF is set about 1/2 way through the stop bit of the character received. At 9600 baud, that is about 50uS into the stop bit. That is 50 CPU instructions (approx.) with a 4Mhz PIC crystal.... You can do a lot of code in that 50uS....
Hi S,
I almost follow your explanation, and think I may understand FIG 18-7 (???)

I'm better at visual clues, and why I use the Simulator so much. While I trying different bits of 'spaghetti' in the program, I stepped through, watching the PIR1.RCIF BIT. Here is an image at the point where it changes from [ 1 ] to [ 0 ]. after being checked for [ If PIR1.RCIF = 1 Then ] Which is, as I think you suggest, during the READ of USART

From my limited view, it seems that (as already suggested) a TMR INTERRUPT must be used. Do you agree? Which one?

I'm sure I've been here before, but I'm not sure if it was for this purpose?
C.
 

Attachments

sagor

Joined Mar 10, 2019
912
Yes, that is correct, PIR1.RCIF will clear when you read the LAST character from RCREG (or do a Hserin or Hserget). However, if there is a second character in the RCREG buffer, PIR1.RCIF will not be cleared, it will remain =1 because there still is a character in the RCREG buffer.
In normal circumstances, there will be one character only in RCREG, and any normal read (Hserin, Hserget or read RCREG) will clear the PIR1.RCIF flag.
You have to remember that PIR1.RCIF is just that, a flag that there is a character in the RCREG buffer ready to be read. If PIR1.RCIF = 0, that means there is no "complete" character ready yet, though there may be one coming into the UART, but it has not reached the stop bit yet. There are no flags that a character is coming in, until it is completed and moved to RCREG and RCIF is set =1

TMR interrupt may have little to do with all this. If using an interrupt, you would use PIR1.RCIF as an interrupt flag (with appropriate interrupt ENABLE set), and process the character READ within that interrupt. In that case, you would not even need Hserin, just check flags and read from RCREG directly and store character in a buffer with some pointers (buffer length) and flags (last character read is end of line, read buffer has a full sentence now "flag").

Any TMR routine would be used to main program, wherever it is, to check certain things. It could be used for the software UART to set the "kill" bit to stop the software read. That is where is was suggested before I think. If you are comfortable understanding the PIR1.RCIF flag and RCREG, then you can stick with the HSERIN, HSERGET routines. If trying interrupts, do it for the hardware UART by enabling interrupts for PIR1.RCIF.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Yes, that is correct, PIR1.RCIF will clear when you read the LAST character from RCREG (or do a Hserin or Hserget). However, if there is a second character in the RCREG buffer, PIR1.RCIF will not be cleared, it will remain =1 because there still is a character in the RCREG buffer.
In normal circumstances, there will be one character only in RCREG, and any normal read (Hserin, Hserget or read RCREG) will clear the PIR1.RCIF flag.
You have to remember that PIR1.RCIF is just that, a flag that there is a character in the RCREG buffer ready to be read. If PIR1.RCIF = 0, that means there is no "complete" character ready yet, though there may be one coming into the UART, but it has not reached the stop bit yet. There are no flags that a character is coming in, until it is completed and moved to RCREG and RCIF is set =1

TMR interrupt may have little to do with all this. If using an interrupt, you would use PIR1.RCIF as an interrupt flag (with appropriate interrupt ENABLE set), and process the character READ within that interrupt. In that case, you would not even need Hserin, just check flags and read from RCREG directly and store character in a buffer with some pointers (buffer length) and flags (last character read is end of line, read buffer has a full sentence now "flag").

Any TMR routine would be used to main program, wherever it is, to check certain things. It could be used for the software UART to set the "kill" bit to stop the software read. That is where is was suggested before I think. If you are comfortable understanding the PIR1.RCIF flag and RCREG, then you can stick with the HSERIN, HSERGET routines. If trying interrupts, do it for the hardware UART by enabling interrupts for PIR1.RCIF.
Hi S,
I feel I am going to take a long time to actually program this, at this rate, while you are writing long explanations.
Is it possible to narrow down the options, so I have less choice please?

As far as I understand I will be using these: HSERIN, HARDWARE UART, PIR1.RCIF
The PIR1.RCIF appears to have TMR1 as it's interrupt
Is this ok.
C
 

Attachments

sagor

Joined Mar 10, 2019
912
PIR1 has many flags in it, including TMR1, RCIF, ADIF and others. You are just concerned about PIR1.RCIF flag. Any flag in that register can be set/cleared by other functions in the PIC, independant of what you are doing with the UART..
Notice on that page you posted (TX section), all the other PIR1 flags are with grey background, meaning they are not relevant to this section. On your page, only the TXIF flag is in white, meaning that is the only bit that applies to that section of the document, the transmit section.
If you look at the receive UART section, Table 18-6, you will see that only the RCIF flag is in white for the PIR1 register, as that section is discussing Async Receiving with the UART. All other bits are greyed out in that register because they do not apply to that section.

So, to make sure you do not get any blocking in your code, always check RCIF, then do the Hserin. Always check RCIF right after, just in case there is a second character. If so, go read it as well. Once RCIF=0, you are done reading, for now, and carry on with your code. The trick is that you MUST check RCIF often enough to prevent any received data overflow. If you happen to be sending a long string out, but data is coming in on the RX pin, you will miss data and get an overflow. This applies if there is a chance you can receive data at random intervals.If the received data can come at any time (random), you should be checking RCIF after every character you send during transmit, and if something comes in, you must read it immediately. An interrupt for RX can do that.

Summary:
If you can control the received data flow (when it comes in), via a prompt or some other signal, then just looping on RCIF and doing your Hserin will work just fine. It all boils down to if you can control the received data flow or not. If you control it, simple loops will work using PIR1.RCIF and HSERIN. If you cannot predict when data comes in, you should be using interrupts or very short loops (less than 1mS between checks of RCIF flag).
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
PIR1 has many flags in it, including TMR1, RCIF, ADIF and others. You are just concerned about PIR1.RCIF flag. Any flag in that register can be set/cleared by other functions in the PIC, independant of what you are doing with the UART..
Notice on that page you posted (TX section), all the other PIR1 flags are with grey background, meaning they are not relevant to this section. On your page, only the TXIF flag is in white, meaning that is the only bit that applies to that section of the document, the transmit section.
If you look at the receive UART section, Table 18-6, you will see that only the RCIF flag is in white for the PIR1 register, as that section is discussing Async Receiving with the UART. All other bits are greyed out in that register because they do not apply to that section.
So, to make sure you do not get any blocking in your code, always check RCIF, then do the Hserin. Always check RCIF right after, just in case there is a second character. If so, go read it as well. Once RCIF=0, you are done reading, for now, and carry on with your code. The trick is that you MUST check RCIF often enough to prevent any received data overflow. If you happen to be sending a long string out, but data is coming in on the RX pin, you will miss data and get an overflow. This applies if there is a chance you can receive data at random intervals.If the received data can come at any time (random), you should be checking RCIF after every character you send during transmit, and if something comes in, you must read it immediately. An interrupt for RX can do that.

Summary:
If you can control the received data flow (when it comes in), via a prompt or some other signal, then just looping on RCIF and doing your Hserin will work just fine. It all boils down to if you can control the received data flow or not. If you control it, simple loops will work using PIR1.RCIF and HSERIN. If you cannot predict when data comes in, you should be using interrupts or very short loops (less than 1mS between checks of RCIF flag).
Hi S,
I had forgotten about the greying.

After this section from the GET_DATA sequence:
________________________________________________________________
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
______________________________________________________________
I presume there is now nothing in the RX buffer.
Does it need to be run again during the rest of the GET_DATA LOOP or could it clear out usable digits?

You can see at the left of the image #51 the VARIABLES. STR1() is where the digits are placed as they arrive. Once in the STRING I can filter some problems out.

I've tried many [ If PIR1.RCIF = 1 or 0 Then ] ideas around [ HSERIN CHAR ] trying to get the glean digits, but so far, I've failed, but from what you say, I should be able to succeed if I keep trying. Is this true?
C.
 

sagor

Joined Mar 10, 2019
912
I would do:
If RCSTA.OERR = 1 Then 'BIT1..if over run error then flush RXD buffer
RCSTA.CREN = 0
char = RCREG '1 - Move these reads before enabling receiver
char = RCREG '2 as a character may be arriving after you enable it.
Not sure, if resetting CREN clears the buffers anyway, or not???


RCSTA.CREN = 1 'ENABLES RECEIVER
PIR1.RCIF = 0 '0 = The EUSART receive buffer is empty -Redundant, RCIF is cleared when you read RCREG twice. It should be zero when you reset the UART

Hserout "RX Err!", CrLf
Note that during your "RX Err" message, the receive is enabled, hopefully there is nothing else coming in at that time. Maybe check OERR again before skipping out. Once you have an overflow, data may still be coming in and could be several characters long. Thus, you need to flush the receive data somehow. Keep checking OERR until it is clear after each Hserout in this loop.
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
I would do:
If RCSTA.OERR = 1 Then 'BIT1..if over run error then flush RXD buffer
RCSTA.CREN = 0
char = RCREG '1 - Move these reads before enabling receiver
char = RCREG '2 as a character may be arriving after you enable it.
Not sure, if resetting CREN clears the buffers anyway, or not???


RCSTA.CREN = 1 'ENABLES RECEIVER
PIR1.RCIF = 0 '0 = The EUSART receive buffer is empty -Redundant, RCIF is cleared when you read RCREG twice. It should be zero when you reset the UART

Hserout "RX Err!", CrLf
Note that during your "RX Err" message, the receive is enabled, hopefully there is nothing else coming in at that time. Maybe check OERR again before skipping out. Once you have an overflow, data may still be coming in and could be several characters long. Thus, you need to flush the receive data somehow. Keep checking OERR until it is clear after each Hserout in this loop.
Hi S,
Please see #14 regarding double RCREG READ.. Do you mean place them after this line [ RCSTA.CREN = 1 'ENABLES RECEIVER ] ?

I've just tried this and now instead of HSERIN blocking, now PIR1.RCIF is blocked due to [ 0 ]

NOTE: STR1() is full, and giving correct results.

I'll re-read your message a couple of times, before more tests.
C.
 

Attachments

sagor

Joined Mar 10, 2019
912
Ok, if it worked before, just leave it the way it was then.

All I'm saying is that if you had an overflow, you have to keep checking the RCIF and OERR if there is still data coming into the UART. How do you know the string being received is finished coming in??
Once you get that OERR error, you want to flush any data coming in since it will not be a complete string.

For example, say you are receiving 30 characters. Somewhere after 5 or 10 characters you detect an OERR and reset the UART. That means there will still be about 20 more characters still being send to the UART from the remote device. You have to read them and discard them, or disable the UART for a long enough period to allow those characters to "disappear". Not easy to do that if you do not know the received length.
Other option is to read each character in your regular "read" code and detect no "start" character, and flush the characters one at a time. I think you are doing that with testing for the start "$" character - that may be enough, hard to say how the overall code works. There is a fine line between resetting the UART and getting back to read the next character. You may not have enough time to print a 7 character "RX Err!" error message if there are characters still coming into the UART.

Maybe print the error message before enabling the RX portion of the UART??
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Ok, if it worked before, just leave it the way it was then.
Hi S,
Quick answer:
It worked before, but blocked. I didn't know what was happening, but now I have a better idea, although it is still blocking.
I think possibly, the TMR suggestion was to clear blocking, but I've searched , and can't find an answer, I understand.
C.
 

sagor

Joined Mar 10, 2019
912
You cannot clear HSERIN blocking with any timer, not at all. HSERIN blocks while it waits for PIR1.RCIF to get set, nothing else will hold up the hardware HSERIN . HSERIN is designed to WAIT until there is a character, which is flagged by PIR1.RCIF=1. That is why you check for PIR1.RCIF=1 (to be set) before you do any HSERIN read. If PIR1.RCIF =0 then there is nothing to read, skip it, don't post a read if nothing is there. If you post a read when PIR1.RCIF = 0, then HSERIN will block....

TMR suggestion was only for the software UART, not the hardware UART. Software UART code waits for a start bit, forever. Hence the "kill bit" in the software UART definitions.

Forget TMR stuff, it has nothing to do with hardware UART.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
You cannot clear HSERIN blocking with any timer, not at all. HSERIN blocks while it waits for PIR1.RCIF to get set, nothing else will hold up the hardware HSERIN . HSERIN is designed to WAIT until there is a character, which is flagged by PIR1.RCIF=1. That is why you check for PIR1.RCIF=1 (to be set) before you do any HSERIN read. If PIR1.RCIF =0 then there is nothing to read, skip it, don't post a read if nothing is there. If you post a read when PIR1.RCIF = 0, then HSERIN will block....

TMR suggestion was only for the software UART, not the hardware UART. Software UART code waits for a start bit, forever. Hence the "kill bit" in the software UART definitions.
Forget TMR stuff, it has nothing to do with hardware UART.
Hi S,
Just had an idea (Simple!!) and it appears to be working. I'll re-test and tidy the program and post it later tomorrow.
A long day for both of us, thanks :)
C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Hi,
Here's the latest GET_DATA LOOP:
Also a simulator image showing the simulation of the TEXT on the left, ALL copied and pasted into the SEND STRING box, and giving good results, and not 'blocking' (So far)

LIVE tests, are not the same!
When I first tried, it looked promising, and as each $sentence arrived, it switched over (DATASWITCH and LED INDICATOR) A couple of times, the correct results appeared, but not regularly.

I can see some of the problems and will work through them.

Any comments?
C
 

Attachments

sagor

Joined Mar 10, 2019
912
Code:
If PIR1.RCIF = 1 Then
    nxt_rxin:
    WaitMs 10  '???????????????????????????????????????????????
    If PIR1.RCIF = 0 Then Goto nxt_rxin
Makes no sense at all. If RCIF=1, then it can never be cleared until something reads RCREG, so it will never be =0.
Also, waiting 10mS means you will miss 10 characters at 9600 baud, and get an overflow error right away. Never use a "wait" in a UART receive loop, just check the RCIF flag. You do not have time to waste with "WaitMS" commands, characters will be coming in every 1mS at 9600 baud.

I would write it something like:
Code:
If PIR1.RCIF = 1 Then 'Means there is a character ready to be read
    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   'No, not correct, you should not go back unless RCIF=1. Remove this line
                If rxi > 79 Then
                    Hserout " OVER STR1 LIMIT", CrLf  'Over STR1() limit
                    rxi = 0
                Endif
        Endif
    If PIR1.RCIF = 1 Then Goto nxt_rxin  'Change to =1 !!! to see if there is any more characters
'If not, you fall through and exit IF loop, as there are no more characters to read
Endif
This will read one (possibly two) characters and then exit the loop. It will not read the entire string in one shot, because RCIF =0 for most of the time when the program is running. You may have to loop back to the first IF forever, and only exit this loop when you get the EOL. However, this may "block" if you get an OERR, since you do not check it within this read loop. Hence, you may have to loop back to the OERR if statement at the top and loop forever until you get your EOL.

What happens when you get a "?", and branch to msg_eol, you may need to still check RCIF flag to make sure the receive buffer (RCREG) is emptied, though this may not be too critical at this point if yoiu assume you have an entire message. Any further characters will trigger an overflow most likely, and you will pick that up at the start where you check OERR
 
Last edited:

djsfantasi

Joined Apr 11, 2010
9,163
Code:
If PIR1.RCIF = 1 Then
    nxt_rxin:
    WaitMs 10  '???????????????????????????????????????????????
    If PIR1.RCIF = 0 Then Goto nxt_rxin
Makes no sense at all. If RCIF=1, then it can never be cleared until something reads RCREG, so it will never be =0.
Also, waiting 10mS means you will miss 10 characters at 9600 baud, and get an overflow error right away. Never use a "wait" in a UART receive loop, just check the RCIF flag. You do not have time to waste with "WaitMS" commands, characters will be coming in every 1mS at 9600 baud.

I would write it something like:
Code:
If PIR1.RCIF = 1 Then 'Means there is a character ready to be read
    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   'No, not correct, you should not go back unless RCIF=1. Remove this line
                If rxi > 79 Then
                    Hserout " OVER STR1 LIMIT", CrLf  'Over STR1() limit
                    rxi = 0
                Endif
        Endif
    If PIR1.RCIF = 1 Then Goto nxt_rxin  'Change to =1 !!! to see if there is any more characters
'If not, you fall through and exit IF loop, as there are no more characters to read
Endif
What happens when you get a "?", and branch to msg_eol, you may need to still check RCIF flag to make sure the receive buffer (RCREG) is emptied, though this may not be too critical at this point if yoiu assume you have an entire message. Any further characters will trigger an overflow most likely, and you will pick that up at the start where you check OERR
Not sure what language this in, but the “goto nxt_rxin” enters an if block. What happens when the endif statement is reached and there is no if active?

I’d code it differently if a while statement is available. This isn’t real code; it’s just to illustrate a better method.

Code:
WHILE (PIR1.RCIF = 1) 'Means there is a character ready to be read
    ‘ nxt_rxin: ‘not needed
        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
            '...
                If rxi > 79 Then
                    Hserout " OVER STR1 LIMIT", CrLf  'Over STR1() limit
                    rxi = 0
                Endif
        Endif
‘ end WHILE
‘   If PIR1.RCIF = 1 Then ... ‘ not needed
' when the while exits  you fall through
 
Top