Reputation: 1170
I would like to receive ideas about how to read data from an UART buffer. Being more precisely, I need a way to find some string pattern in the buffer. The problem is that if I wait to search this string, the buffer is written again, the counter changes, and the data can have the pattern or not. Well, I think that this explanation is a little hard to understand, so feel free to ask anything else.
void f(char * buffer) {
char * p;
p = strstr(buffer, "abc");
printf(p);
}
I think the UART, in my case, is written by blocks and not char by char and there's no way to say that data finished because it's a continuous stream. To better illustrate, it is a code that reads GPS data in NMEA protocol and try to get information from these data.
Best regards
Upvotes: 0
Views: 4329
Reputation: 17487
Could you receive all the data then processing the string? I think the code likes this:
char *p_uart = read_from_uart();
void search_string(char *p_uart)
{
static char last_remain_char[20];
char new_data[1000] = {0};
char *p = NULL;
int n = 0;
n = snprintf(new_data, sizeof(new_data), "%s%s", last_remain_char, p_uart);
p = strstr(new_data, "abc");
strcpy(last_remain_char, new_data + (n - (strlen("abc") - 1)));
}
Upvotes: 0
Reputation: 63481
Your question is not clear, but I've seen a lot of people misunderstand how buffers work, so I think I can help.
By what you're saying, you are expecting to read data into a buffer, and are worried that it will partially match your search string. Then when you read the rest of it, you overwrite the first lot of data.
So, this comes down to how you process your data. You don't need to read into the same part of memory every time. The whole point of a buffer is it gives you space that you can fill up, shuffle around if necessary and then discard.
There are many ways to use buffers effectively. I'll give you the simplest one to understand, although it might not be the most efficient:
When you read into the buffer, you maintain an index (let's call it tail
) so you know where the last byte is. You can read up to N
bytes where N
is the size of your buffer. When it comes to processing the data, you can check bytes up to tail
.
To track what you have already processed, maintain a head
index. Once you have determined that you need to read more data, you take everything between head
and tail
and move it to the beginning of the buffer (use memmove
, NOT memcpy
). You set head = 0
, and tail = tail-head
. Now you can read up to N - tail
more bytes. Naturally, you read into a position in the buffer beginning after the tail
index.
If you want to be able to test the entire match string as consecutive bytes, this is the easiest buffering approach.
If you want to go a step further, it doesn't take much imagination to realise that you don't need to move the data at all. You can just have head
chase tail
around and around. This is called a ring (or circular) buffer. The difficulty with this is you can't use ordinary string matching, but it doesn't take much to roll your own.
Hope this is helpful.
Upvotes: 0
Reputation: 98118
You can receive each character and accumulate them (copy) in a regular buffer for comparing later. Or, a better way is to receive each character and keep a state variable to tell you how far you are in the match:
size_t state = 0;
while( c=get_char_uart() ) {
if (str_to_match[state] == c) {
state++;
if (state == strlen(str_to_match)) {
/* success */
}
}
else
state = 0;
}
if you are expecting a repeating sequence of characters ("abcabd") it gets trickier. In this case if you fail at d
you might need to look for c
. Be warned.
Upvotes: 0