2013-04-02 2 views
0

UART 버퍼에서 데이터를 읽는 방법에 대한 아이디어를 얻고 싶습니다. 좀 더 정확히 말하자면, 버퍼에서 문자열 패턴을 찾는 방법이 필요합니다. 문제는이 문자열을 검색하기 위해 대기하는 경우 버퍼가 다시 쓰여지고 카운터가 변경되고 데이터에 패턴이 있는지 여부입니다. 글쎄, 나는이 설명이 이해하기가 조금 어렵다고 생각한다. 그래서 다른 것을 물어 보자.버퍼에서 데이터를 읽는 최선의 방법

void f(char * buffer) { 

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

printf(p); 
} 

은 내가 UART, 내 경우에는 블록으로 기록되고 문자로 문자하지 생각하고 연속 스트림이기 때문에 데이터가 완성이라고 할 수있는 방법이 없습니다. 더 잘 설명하기 위해 NMEA 프로토콜에서 GPS 데이터를 읽고 이러한 데이터에서 정보를 얻으려고 시도하는 코드입니다.

감사합니다.

답변

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))); 
} 
+0

"모든 데이터"라고 말할 방법이 없습니다 ... 제 경우에는 매 1 초마다 데이터 블록을 보내는 GPS입니다. –

+0

@Leandro : 다른 스레드에 데이터를 전송 한 다음이 스레드에서 문자열을 검색하도록 할 수 있습니까? –

+0

Nops, 그 임베디드 코드, 더 많은 스레드를 가질 수 없습니다 ... –

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을 찾아야 할 수도 있습니다. 경고 받다.

+0

문제는 char로 char을받을 수 있는지 없는지입니다 ... –

0

당신의 질문은 명확하지 않지만, 많은 사람들이 버퍼 작동 방식을 오해하고있는 것을 보았습니다. 그래서 제가 도울 수 있다고 생각합니다.

당신이 말하는 바에 따르면, 데이터를 버퍼로 읽을 것으로 예상되며 부분적으로 검색 문자열과 일치 할까 우려됩니다. 그런 다음 나머지 부분을 읽으면 첫 번째 많은 데이터를 덮어 씁니다.

이렇게하면 데이터 처리 방법이 달라집니다. 매번 같은 부분의 메모리를 읽을 필요가 없습니다. 버퍼의 요점은 당신이 채울 수있는 공간을 제공하고 필요하다면 뒤섞어 버리고 버릴 수 있다는 것입니다.

버퍼를 효과적으로 사용하는 방법에는 여러 가지가 있습니다.

버퍼를 읽을 때 마지막 바이트의 위치를 ​​알 수 있도록 색인을 유지 관리합니다 (tail이라고 부름). 가장 효율적인 방법은 다음과 같습니다. N 바이트까지 읽을 수 있습니다. 여기서 N은 버퍼 크기입니다. 데이터 처리와 관련하여 바이트 수를 tail까지 확인할 수 있습니다.

이미 처리 한 항목을 추적하려면 head 색인을 유지하십시오. 더 많은 데이터를 읽어야한다고 결정한 후에는 headtail 사이의 모든 것을 가져 와서 버퍼의 처음으로 이동하십시오 (memmove, 이 아닌memcpy 사용). head = 0tail = tail-head을 설정합니다. 이제 최대 N - tail 바이트를 읽을 수 있습니다. 당연히 버퍼의 위치는 tail 색인 뒤에 시작됩니다.

전체 일치 문자열을 연속 바이트로 테스트 할 수있는 경우 가장 쉬운 버퍼링 방식입니다.

더 나아가려면 데이터를 전혀 옮길 필요가 없다는 것을 깨닫기 위해 많은 상상력을 필요로하지 않습니다. 당신은 head 체이스 tail 주위를 돌아 다닐 수 있습니다. 이것은 반지 (또는 원형) 버퍼라고합니다. 이것의 어려움은 일반적인 문자열 매칭을 사용할 수 없다는 것입니다. 그러나 자신의 롤링을 많이하지는 않습니다.

희망이 있으면 도움이됩니다.

+0

괜찮 으면'strstr'을 사용하고 싶습니다. 처리하기 전에 매번 버퍼를 NULL 종료해야합니다. 일치 문자열의 길이가'X'라고 가정 해 봅시다. 'strstr'가 어떤것과도 일치하지 않는다면 버퍼에'X-1' 문자를 넣고 (내가 제안한대로'tail '을 수정하여), 배열 인덱스'X- 1 '. 읽을 바이트 수는'N-X '입니다. 버퍼를 종료하려면 한 문자 만 남아 있어야합니다. – paddy

+0

그래서 내가 이해했는지 보자. 내가 읽고 읽은 것과 꼬리가 배열의 구걸을 가리키는 사이의 모든 데이터를 이동하고 그때 나는 꼬리 마이너스 머리로 0과 꼬리로 머리를 설정해야합니다 일부 char를 읽고 처리 할 때마다. 승인. 하지만, 내가 꼬리 포인터를 설정할 때 데이터를 움직일 때, isr은 버퍼에 다른 것을 씁니까? 나는 그 편지를 통제 할 수 없다 ... –

+0

오, 알았어. UART 버퍼에서 직접 작동한다는 것을 알지 못했습니다. 가능한 한 빨리 버퍼에서 데이터를 복사합니다. 이상적으로는이를 위해 스레드 또는 인터럽트 처리 루틴이 있어야합니다. 그게 옵션이 아닌 것 같은데. 귀하의 처리 *는 UART보다 훨씬 빠르지 만 빨리 폴링하거나 인터럽트를 처리하는 한 괜찮습니다. 블록을 덮어 썼는지 여부를 확인할 수 있습니다. 그렇지 않은 경우 첫 문자에 사용되지 않은 비트를 설정할 수 있습니다. – paddy

관련 문제