2013-02-03 7 views
10

저는 두 가지 중 하나에 대해 GSM 모뎀을 사용하는 응용 프로그램을 작성했습니다. 서버에 GET 요청을 보내거나 UDP를 사용하여 서버에 데이터를 보내 내장 된 HTTP 스택을 사용하여 상태를 확인하십시오. 가능한 한 신뢰할 수있는 여러 가지 방법을 시도했으며 마침내 도움을 요청할 준비가되었습니다.GSM 모뎀 드라이버 작성 중?

내 응용 프로그램은 SIMCOM908 모듈과 PIC18 플랫폼 용으로 작성되었습니다 (개발을 위해 PIC18 Explorer를 사용하고 있습니다).

그래서 문제는 때로는 모뎀이 뭔가를하는 중입니다. 명령을 놓친 경우입니다. 인간으로서 나는 그것을보고 그냥 명령을 다시 보냅니다. MCU에 시간 초과 및 재전송 기능을 추가하는 것은 문제가되지 않습니다.

문제는 모뎀이 다른 이벤트 후에 요청하지 않은 응답을 보내는 문제입니다. 모뎀이 등록 상태 (셀 타워 포함)를 변경하면 +CGREG: 1, ...으로 응답하거나 GPS가 준비되었을 때 GPS Ready으로 응답합니다. 이러한 응답은 명령의 중간 (IP 연결 작성과 같은)을 포함하여 언제든지 발생할 수 있습니다.

이 문제를 해결할 방법을 생각하지 않았기 때문에 이것은 문제입니다. 내 응용 프로그램이 명령을 보내야합니다 (예 : AT+CIPSTART="UDP","example.com",5000과 같은 서버에 연결).이 명령은 'OK'로 응답 한 다음 명령이 'CONNECT OK'를 완료하면 응답합니다. 그러나 나는 다른 많은 가능한 반응에 반응 할 수 있어야하고, 나는 이것을하는 방법을 알아 내지 못했다. 내 코드로 무엇을해야합니까? 모뎀으로부터의 응답을 기다리고, 응답을 확인하고, 그 응답을 기반으로 동작을 수행합니까?

저는 코드가 제한되어 있으며 (8 비트 마이크로 컨트롤러입니다!) 반복 반복을 최소로하고 싶습니다. GSM 모듈 (요청 또는 지금)로부터 응답을 받고 내 프로그램의 나머지 부분에서 무슨 일이 일어나는지 응답 함수를 작성하려면 어떻게해야합니까?

이상적으로 나는 이러한 응답으로 무엇인가하고 싶습니다. 마찬가지로 내가 GPS Ready을들을 때, 나는 등 GPS 전원을 공급할 수 알고 (내부 상태를 유지

어쩌면 나는 생각한다, 또는 어쩌면 이미이 문제를 해결 오픈 소스 프로젝트 거기에 몇 가지가있다?

.

는 여기에 지금까지이 작업은 다음과 같습니다.

/* Command responses */ 
enum { 
    // Common 
    OK = 0, 
    ERROR, 
    TIMEOUT, 
    OTHER, 
    // CGREG 
    NOT_REGISTERED, 
    // CGATT 
    NOT_ATTACHED, 
    // Network Status 
    NO_NETWORK, 
    // GPRS status 
    NO_ADDRESS, 
    // HTTP ACTION 
    NETWORK_ERROR, 
    // IP Stack State 
    IP_INITIAL, 
    IP_STATUS, 
    IP_CONFIG, 
    UDP_CLOSING, 
    UDP_CLOSED, 
    UDP_CONNECTING 
} gsmResponse; 

int gsm_sendCommand(const char * cmd) { 
    unsigned long timeout = timer_getCurrentTime() + 5000; 

    uart_clearb(GSM_UART); // Clear the input buffer 
    uart_puts(GSM_UART, cmd); // Send the command to the module 
    while (strstr(bf2, "\r") == NULL) { // Keep waiting for a response from the module 
     if (timeout < timer_getCurrentTime()) { // Check we haven't timed out yet 
      printf("Command timed out: %s\r\n", cmd); 
      return TIMEOUT; 
     } 
    } 
    timer_delay(100); // Let the rest of the response be received. 

    return OK; 
} 

int gsm_simpleCommand(const char * cmd) { 
    if (gsm_sendCommand(cmd) == TIMEOUT) 
     return TIMEOUT; 

    // Getting an ERROR response is quick, so if there is a response, this will be there 
    if (strstr(bf2, "ERROR") != NULL) 
     return ERROR; 

    // Sometimes the OK (meaning the command ran) can take a while 
    // As long as there wasn't an error, we can wait for the OK 
    while (strstr(bf2, "OK") == NULL); 
    return OK; 
} 

간단한 명령은 AT 같은 구체적으로 응답 OK 또는 ERROR을 찾고 명령 AT 어떤 무언가 그러나 나는 또한 AT+CPIN? 같은 고급 명령을 위해 사용하기 때문에 그것 전체 응답을 캡처 한 후 +CPIN: READY을 더 검색 할 수 있습니다. 그러나이 중 어느 것도 원치 않는 응답에 실제로 응답하지 않습니다. 사실 원하지 않는 응답이 수신되면 gsm_sendCommand() 함수는 일찍 반환됩니다.

복잡하고 때로는 원치 않는 상태 메시지를 관리하는 좋은 방법은 무엇입니까? 이 응용 프로그램은 C로 작성되었으며 8 비트 마이크로 컨트롤러에서 실행됩니다. 당신이 들어오는 스트림을 역 다중화 필요하고 적절한 처리기에 결과를 파견하기 때문에 동일한 데이터 스트림의 요청에 모두 원치 않는 메시지뿐만 아니라 응답을 처리하는 데

+1

상태 기계 (FSM)를 구현해야합니다 :'newstate = oldstate [message]', 그리고 아마도 다른 쪽이 상태 기계라고 생각할 수도 있습니다. – wildplasser

+0

그 부분은 내가 생각하기에. 그러나이 경우 전체 FSM은 최상의 옵션처럼 보이지 않습니다. 단일 시스템의 여러 상태 라기보다는 서로 다른 두 가지 원치 않는 코드의 이진 상태를 추적해야합니다. 나는 추적 할 두 개의 글로벌 부울 유형을 간단히 갖게 될 것이다. – dantheman

답변

2

어렵다. 인터럽트 핸들러와 약간 비슷합니다. 당신이하고있는 것을 버리고 반드시 기대하지 않았던 다른 정보를 처리해야합니다.

일부 모듈에는 메시지 용으로도 사용할 수있는 보조 직렬 포트가 있습니다. 이것이 가능하다면 주 포트가 AT 명령에 대한 것일 때 원치 않는 메시지가 하나의 직렬 포트에만 나타날 수 있습니다. 이것은 가능하지 않을 수 있으며 일부 GSM 모듈은 보조 포트에 설정된 전체 명령을 지원하지 않습니다.

아마도 더 나은 방법은 원치 않는 메시지를 사용하지 않도록 설정하는 것입니다. 대부분은 모든 주를 요청하도록 명령합니다. 예를 들어, 등록을 기다리는 동안 원하지 않는 등록 메시지가 나타날 때까지 기다리는 대신 모듈에 현재 등록 상태를 폴링하기 만하면됩니다. 이렇게하면 항상 제어 할 수 있으며 방금 보낸 명령에 대한 응답 만 처리하면됩니다. 여러 이벤트를 기다리는 중이라면 차례대로 각 항목의 루프를 폴링 할 수 있습니다. 이렇게하면 일반적으로 한 번에 하나의 응답 만 처리하면되므로 코드가 더 간단 해집니다. 단점은 응답 시간이 투표 율에 의해 제한된다는 것입니다.

요청하지 않은 메시지 방식을 계속 사용하도록 설정했다면 원치 않는 메시지에 대해 작은 대기열을 구현하는 것이 좋습니다. 명령에 대한 응답을 기다리는 동안 응답이 명령과 일치하지 않으면 큐에서 응답을 푸시하십시오. 그런 다음 AT 명령에 대한 응답을 받거나 시간 초과가되면 이후에 원치 않는 메시지 큐를 처리 할 수 ​​있습니다.

+0

정말 좋은 방법 같아 보입니다. 나는이 모듈을 통해 보조 직렬 포트가 명령을 보내는 데 좋지 않다는 것을 알고있다. 지금까지'GPS Ready'와'CGREG : 1' 메시지를 보았습니다. CGREG를 비활성화 할 수 있다는 것을 알고 있습니다. 내 오래된 코드는 설문 조사에 사용되었는데, 이는 요청되지 않은 응답을 놓친 경우에도 내 코드가 여전히이를 기다리지 않기 때문에 좋았습니다. – dantheman

+1

그렇기 때문에 대기열을 구현하는 아이디어 (상당히 메모리가 제한된 응용 프로그램 임)에 열중하지는 않지만 원하지 않는 응답을 사용하지 않도록 설정하는 것은 완전히 불가능합니다. 커맨드 펑션 전체에 인터럽트 가능성을 설명하기 위해 처리 능력을 추가하는 아이디어는 싫다. 그래서 큐가 훨씬 더 의미가있다. 답변 주셔서 감사합니다! – dantheman

+1

@ dantheman 대기열이 작을 수 있기를 바랍니다. 'gsm_sendCommand'가'char * buf'와'size_t bufLen'을위한 몇 개의 매개 변수를 취함으로써 원하는 경우 스택에 대기열을 배치 할 수 있습니다. 'gsm_sendCommand'를 호출하는 함수는 스택에 임시 버퍼를 할당 할 수 있으며,'gsm_sendCommand'가 반환 된 후에 큐를 처리합니다. 이것을하는 많은 방법. –