CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

UART string compare

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
vtrx



Joined: 11 Oct 2017
Posts: 141

View user's profile Send private message

UART string compare
PostPosted: Mon Nov 01, 2021 2:58 pm     Reply with quote

I'm trying to implement a serial command read.

Code:

char Rs_buf[25] 
...
#int_rda
void rda_isr(void)
{
 //aux=1;
 Rs_buf[posi_rs] = getc();
 posi_rs++;
 if(posi_rs==RSTotal)      //25 largura
  {
   posi_rs = 0;
   if(strcmp(string,'desativando texto rolante'))
     {do something;}
  }
}


I don't know how to 'assemble' a string to compare it using a buffer.
How would it be?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Nov 02, 2021 1:25 am     Reply with quote

The first key thing to learn, is that in C, a 'string', is an array of characters
_with a NULL terminator at the end_. You cannot and must not use a
string comparison, without adding this terminator character. So if you
wanted to work with a 25 character 'string', the buffer would need to be
26 characters long, and you would need to ensure that this 26th character
is a NULL before you do the comparison.
Second thing is a big 'caveat'. Interrupt handlers should always be kept
'quick'. Performing a 25 character string comparison inside an interrupt
handler is very poor practice, and may well cause problems. Remember while the processor is inside the handler doing this, it cannot do anything
else, so there becomes the risk of other interrupt events being missed...
Sad
This gets worse if 'do something' takes any time...

Now, there is another problem. What happens if a character is missed, or
an extra character is received?. By searching based on a count only,
if this happens there can never be a match.

Does the input data stream have anything 'marking' the start of the packet
or the end of a packet?. Ideally the routine should look for this character
and use this as the point where it starts or finishes the buffer write.

Now with the receive code then looking for the marker in the data to know
'where' it is, and writing the characters to the array, what should ideally
happen is to have a two dimensional array with space for two of the
received packets. When it gets to the end of the first packet, it sets
a flag to say 'use second buffer', and a flag for the main code to do the
search. The main routine when it sees this flag sets does the comparison
on the other buffer (so if 'use second buffer' is set it checks the first,
etc.).
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Nov 02, 2021 5:15 am     Reply with quote

Along with everything Mr. T has written....
the actual ISR should only capture the byte, insert into a buffer,set flag when full. MAIN(), when it sees the flag set, does the actual comparison/take action

I'll add, make the string comparisons short.
using your code ...
Instead of 'desativando texto rolante' use 'dtr'. Only 3 characters to compare not 25.
Make all the 'commands' or 'keywords', 3 characters long. less typing = less mistakes, easier to read the code,faster to compare.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Tue Nov 02, 2021 10:38 am     Reply with quote

I always use a state machine inside the ISR to decode an incoming string and then set a flag for main() when I get the correct one. No need for buffers (except maybe for debugging purposes), no comparing of strings at the end. It is all done on the fly. The downside is that for many different strings to decode the code can get quite long.I do very much agree that the incoming string should be as short as possible to make the program more easily readable and to avoid typos, if nothing else.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Nov 02, 2021 11:15 am     Reply with quote

Totally agree. The state machine approach is a much better way of
working. However the matching is done though, unless it is short the
actual action should be outside the ISR,
Woody



Joined: 11 Sep 2003
Posts: 75
Location: Warmenhuizen - NL

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 4:40 am     Reply with quote

Quote:
Remember while the processor is inside the handler doing this, it cannot do anything
else, so there becomes the risk of other interrupt events being missed...
Sad

Although I am all for keeping code inside ISR's as short as possible, I was under the assumption that an interrupt that occurs while another one is being serviced, would be serviced right after the first was done.

If this is not the case I learned an important lesson today.

Paul
gaugeguy



Joined: 05 Apr 2011
Posts: 286

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 7:05 am     Reply with quote

While any pending interrupt will be serviced after the current routine has exited, if two of the same interrupt occur there will be one missed.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 7:29 am     Reply with quote

Exactly. With the UART, you have a maximum of two character times (one
buffer and one for the shift register), before things are missed.
If the 'do anything' code takes any significant time, then things will be missed,
Woody



Joined: 11 Sep 2003
Posts: 75
Location: Warmenhuizen - NL

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 7:59 am     Reply with quote

Ah, ok.

My misunderstanding then. I am glad things work as I initially thought; I use interrupts a lot and often, while I don't care about precise timing, I need to be sure that an interrupt IS handled, no matter what.

Paul
vtrx



Joined: 11 Oct 2017
Posts: 141

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 4:38 pm     Reply with quote

I'm back Smile

Actually I need to decode some separate characters and know when I get a string of characters(51).

Code:

#int_rda
void rda_isr(void)
{
 int16   m;
 char    rx;
//....................
rx = getc();
  if(rx==0x00)
   {
    ...do something short.
    return;
   }else
  if(rx==0x01)
    {
    ...do something short.
    return;
    }else
  if(rx==0x02)
     {
    ...do something short.
    return;
     }else
  if(rx==0x03) //+
    {
    ...do something short.
    return;
    }else
  if(rx==0x04) //-
    {
    ...do something short.
    return;
    }else
  if(rx==0x05) //>
    {
    ...do something short.
    return;
    }else
  if(rx==0x06) //<
    {
    ...do something short.
    return;
    }else
//......if it's not the key character, i get the string of 51 characters.......
      Rs_buf[posi_rs] = rx;
      posi_rs++;
 if(posi_rs==RSTotal)      //51 chars
  {
       disable_interrupts(INT_RDA);
    for(m=0;m<51;m++)
        {
         messagebuf[messagebufpos] = Rs_buf[m];
         messagebufpos++;                                                     
        }
        enable_interrupts(INT_RDA);
  }
//...............................
}


Do you guys think that if I always take the 51-character string and check if the first character is a key and if not, then using the entire string is more effective(will be more in sync?)?

Code:

#int_rda
void rda_isr(void)
{
      Rs_buf[posi_rs] = getc();
      posi_rs++;
 if(posi_rs==RSTotal)      //51 chars
  {
   posi_rs = 0;
   full = 1;        //Main must do something
  }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 4:46 pm     Reply with quote

Here are some links to command parsing code:

From Ttelmah:
http://www.ccsinfo.com/forum/viewtopic.php?t=31144&start=3
From srhoar:
http://www.ccsinfo.com/forum/viewtopic.php?t=28159&start=8
jeremiah



Joined: 20 Jul 2010
Posts: 1314

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 5:27 pm     Reply with quote

vtrx wrote:

Code:

#int_rda
void rda_isr(void)
{
      Rs_buf[posi_rs] = getc();
      posi_rs++;
 if(posi_rs==RSTotal)      //51 chars
  {
   posi_rs = 0;
   full = 1;        //Main must do something
  }

}


for this i would recommend handling the "full" scenario in the ISR. Right now you would override previously good data and maybe corrupt by the time you service the data. I would at a minimum not copy any new data to the buffer until the main serviced it (to avoid corrupt data):

Code:

#int_rda
void rda_isr(void)
{

   if (full) {
      getc();  //throw away value
   }else{
     
      Rs_buf[posi_rs] = getc();
      posi_rs++;
      if(posi_rs==RSTotal)      //51 chars
      {
         posi_rs = 0;
         full = 1;        //Main must do something
      }

   }

}


if you want to save that incoming data instead, you could use multiple buffers and swap between them as they fill (and just use a char * pointer to point to the message the main should look at next while the other buffers fill). You'd need some additional flags for that.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 5:28 pm     Reply with quote

What exactly do you want to parse? Can you post an example of at least two possible incoming strings that you are interested in? Are those strings equal in 50 characters, so you need to capture and parse them all? What do you mean by separate characters? You could look for that character and when it arrives, start filling a buffer and count to 51. Options are unlimited, but you asked a really general question without any details and that makes it hard to suggest a solution that would suit your needs.
vtrx



Joined: 11 Oct 2017
Posts: 141

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 5:37 pm     Reply with quote

PrinceNai wrote:
What exactly do you want to parse? Can you post an example of at least two possible incoming strings that you are interested in? Are those strings equal in 50 characters, so you need to capture and parse them all? What do you mean by separate characters? You could look for that character and when it arrives, start filling a buffer and count to 51. Options are unlimited, but you asked a really general question without any details and that makes it hard to suggest a solution that would suit your needs.


Imagine, the hardware controls a TV (fictional example).
'+' Increase brightness.
'-' decreases etc.
The TV can send a text(51 char, it's actually much more).
'+' and '-' control the image, the rest is received text with fixed size.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Nov 03, 2021 5:47 pm     Reply with quote

What you are looking for are distinct strings. Let's say "+ " sends aaaaaaaaaaaaaabbbaaaaaaaaaaaaa. "-" sends aaaaaaaaaaaccccaaaaaa. You need to filter out the distinct part of the message. In my example that would be three consecutive b's or c's. It doesn't matter how long the incoming message is.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group