0

我想收到有关如何从 UART 缓冲区读取数据的想法。更准确地说,我需要一种在缓冲区中找到一些字符串模式的方法。问题是,如果我等待搜索这个字符串,缓冲区会被再次写入,计数器会发生变化,数据可以有也可以没有模式。好吧,我认为这个解释有点难以理解,所以请随时问其他问题。

void f(char * buffer) {

char * p;
p = strstr(buffer, "abc");

printf(p);
}

我认为就我而言,UART 是按块写入的,而不是按字符写入的,并且无法说数据已完成,因为它是连续的流。为了更好地说明,它是一个读取 NMEA 协议中的 GPS 数据并尝试从这些数据中获取信息的代码。

此致

4

3 回答 3

0

你的问题不清楚,但我看到很多人误解了缓冲区的工作原理,所以我想我可以提供帮助。

根据您的说法,您希望将数据读入缓冲区,并担心它会部分匹配您的搜索字符串。然后,当您阅读其余部分时,您会覆盖第一批数据。

因此,这取决于您如何处理数据。您不需要每次都读入内存的同一部分。缓冲区的全部意义在于它为您提供了可以填充的空间,必要时随机播放然后丢弃。

有很多方法可以有效地使用缓冲区。我会给你一个最容易理解的,虽然它可能不是最有效的:

当您读入缓冲区时,您会维护一个索引(我们称之为它tail),以便您知道最后一个字节在哪里。您最多可以读取缓冲区大小的N字节。N在处理数据时,您最多可以检查tail.

要跟踪您已经处理的内容,请维护一个head索引。一旦确定需要读取更多数据,就将 和 之间的所有内容head移到tail缓冲区的开头(使用memmoveNOT memcpy)。您设置head = 0tail = tail-head。现在您可以读取N - tail更多字节。tail自然地,您从索引之后开始读入缓冲区中的一个位置。

如果您希望能够将整个匹配字符串作为连续字节进行测试,这是最简单的缓冲方法。

如果你想更进一步,不需要太多的想象力就能意识到你根本不需要移动数据。你可以到处head追逐。tail这称为环形(或循环)缓冲区。这样做的困难是你不能使用普通的字符串匹配,但你自己的滚动并不需要太多。

希望这会有所帮助。

于 2013-04-02T02:03:52.417 回答
0

您可以接收每个字符并将它们累积(复制)在常规缓冲区中以供以后比较。或者,更好的方法是接收每个字符并保留一个状态变量来告诉您您在比赛中的距离:

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;
}

如果您期待重复的字符序列(“abcabd”),它会变得更加棘手。在这种情况下,如果你失败了,d你可能需要寻找c. 被警告。

于 2013-04-02T01:46:52.933 回答
0

你能接收所有数据然后处理字符串吗?我认为代码是这样的:

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)));
}
于 2013-04-02T01:44:01.813 回答