2013-02-03 39 views
10

Tôi đã làm việc trên một ứng dụng sử dụng modem GSM cho một trong hai điều; kiểm tra trạng thái của nó bằng cách sử dụng ngăn xếp HTTP dựng sẵn bằng cách gửi yêu cầu GET đến máy chủ hoặc gửi dữ liệu đến máy chủ (sử dụng UDP). Tôi đã thử một số phương pháp khác nhau để giữ điều này là đáng tin cậy nhất có thể và cuối cùng tôi đã sẵn sàng yêu cầu trợ giúp.Viết trình điều khiển modem GSM?

Ứng dụng của tôi được viết cho mô-đun SIMCOM908 và nền tảng PIC18 (tôi đang sử dụng Trình khám phá PIC18 để phát triển).

Vì vậy, vấn đề đôi khi modem bận rộn làm điều gì đó và bỏ lỡ một lệnh. Là một con người, tôi sẽ thấy điều đó và chỉ gửi lại lệnh. Thêm một cơ sở cho MCU của tôi để thời gian chờ và gửi lại không phải là một vấn đề.

Sự cố là modem gửi phản hồi không mong muốn sau các sự kiện khác nhau. Khi modem thay đổi trạng thái đăng ký (với tháp di động), nó sẽ phản hồi với +CGREG: 1, ... hoặc khi GPS sẵn sàng GPS Ready. Những phản ứng này có thể xảy ra bất cứ lúc nào, kể cả ở giữa lệnh (như tạo kết nối IP).

Đây là một vấn đề, bởi vì tôi đã không nghĩ ra một cách để giải quyết vấn đề này. Ứng dụng của tôi cần gửi lệnh (để kết nối với máy chủ chẳng hạn, AT+CIPSTART="UDP","example.com",5000) Lệnh này sẽ phản hồi bằng 'OK', và sau đó khi lệnh kết thúc 'CONNECT OK'. Tuy nhiên, tôi cần phải có khả năng phản ứng với nhiều phản ứng có thể khác, và tôi đã không tìm ra cách để làm điều này. Tôi cần làm gì với mã của mình; chờ phản hồi từ modem, kiểm tra phản hồi, thực hiện hành động dựa trên phản hồi đó?

Tôi bị giới hạn mã (là vi điều khiển 8 bit!) Và muốn giữ lại sự lặp lại ở mức tối thiểu. Làm thế nào tôi có thể viết một chức năng đáp ứng mà sẽ có một phản ứng từ các mô-đun GSM (mời hoặc bây giờ) và sau đó cho phần còn lại của chương trình của tôi biết những gì đang xảy ra?

Lý tưởng nhất, tôi muốn làm điều gì đó với những phản hồi đó. Giống như giữ một trạng thái nội bộ (khi tôi nghe GPS Ready, tôi biết tôi có thể cung cấp năng lượng GPS, vv

Có lẽ có một số điều tôi nên suy nghĩ về, hoặc có thể có một dự án mã nguồn mở mà đã giải quyết vấn đề này?

Dưới đây là những gì tôi có cho đến nay:..

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

Một lệnh đơn giản là bất kỳ lệnh AT được đặc biệt tìm kiếm OK hoặc ERROR để đáp ứng cái gì đó giống như AT Tuy nhiên, tôi cũng sử dụng nó cho các lệnh cao cấp hơn như AT+CPIN? vì nó m eans Tôi sẽ nắm bắt được toàn bộ phản hồi và có thể tìm kiếm thêm +CPIN: READY. Tuy nhiên, không ai trong số này thực sự phản ứng với những phản ứng không được yêu cầu. Thực tế, hàm gsm_sendCommand() sẽ trả về sớm khi nhận được phản hồi không mong muốn.

Cách tốt nhất để quản lý các thông báo trạng thái phức tạp, thỉnh thoảng không được yêu cầu như thế này là gì? Xin lưu ý rằng ứng dụng này được viết bằng C và chạy trên vi điều khiển 8 bit!

+1

Bạn có thể phải triển khai máy trạng thái (FSM): 'newstate = oldstate [message]' và có thể coi đầu kia là máy trạng thái. – wildplasser

+0

Đó sẽ là một phần của nó tôi nghĩ. Tuy nhiên, FSM đầy đủ trong trường hợp này dường như không phải là lựa chọn tốt nhất. Tôi cần phải theo dõi trạng thái nhị phân của một vài mã không được yêu cầu khác nhau hơn là nhiều trạng thái của một hệ thống đơn lẻ. Tôi sẽ chỉ có một vài loại boolean toàn cầu để theo dõi. – dantheman

Trả lời

2

Phải xử lý cả thư không mong muốn cũng như phản hồi yêu cầu trong cùng luồng dữ liệu vì bạn sẽ cần phải phân tách luồng đến và gửi kết quả đến trình xử lý thích hợp. Nó giống như một trình xử lý ngắt trong đó bạn phải bỏ những gì bạn đang làm và xử lý một chút thông tin khác mà bạn không nhất thiết phải mong đợi.

Một số mô-đun có cổng nối tiếp thứ cấp cũng có thể được sử dụng cho tin nhắn. Nếu điều này là có thể bạn có thể có các tin nhắn không mong muốn chỉ xuất hiện trên một cổng nối tiếp duy nhất trong khi cổng chính là cho các lệnh AT của bạn. Điều này có thể không thực hiện được, và một số mô-đun GSM sẽ không hỗ trợ lệnh hoàn chỉnh được đặt trên cổng phụ.

Có lẽ cách tiếp cận tốt hơn là chỉ cần tắt tin nhắn không mong muốn. Hầu hết các lệnh đều được yêu cầu. ví dụ: Trong khi chờ đăng ký, thay vì chờ đợi một thông báo đăng ký không được yêu cầu xuất hiện, chỉ cần thăm dò ý kiến ​​mô-đun cho trạng thái đăng ký hiện tại. Điều này cho phép bạn luôn kiểm soát được và bạn chỉ phải xử lý các câu trả lời cho lệnh vừa gửi. Nếu bạn đang chờ đợi nhiều sự kiện, bạn có thể thăm dò ý kiến ​​trong vòng lặp cho từng mục. Điều này thường sẽ làm cho mã đơn giản hơn khi bạn chỉ phải xử lý một phản hồi duy nhất tại một thời điểm. Nhược điểm là thời gian phản hồi của bạn bị giới hạn bởi tỷ lệ bỏ phiếu của bạn.

Nếu bạn đang tiếp tục với cách tiếp cận thư không mong muốn, tôi khuyên bạn nên triển khai một hàng đợi nhỏ cho các thư không mong muốn. Trong khi chờ đợi câu trả lời cho một lệnh, nếu phản hồi không khớp với lệnh, chỉ cần đẩy phản hồi trên hàng đợi. Sau đó, khi bạn đã nhận được phản hồi cho lệnh AT của bạn hoặc hết thời gian, bạn có thể xử lý hàng đợi tin nhắn không mong muốn sau đó.

+0

Điều đó nghe có vẻ giống như một cách thực sự tuyệt vời để đi. Tôi biết với mô-đun này rằng cổng nối tiếp thứ cấp là không tốt cho việc gửi lệnh. Cho đến nay, tôi đã thực sự chỉ nhìn thấy tin nhắn 'GPS Ready' và' + CGREG: 1'. Tôi biết bạn có thể vô hiệu hóa một CGREG. Mã cũ của tôi được sử dụng để thăm dò ý kiến, và điều đó là tốt bởi vì nó có nghĩa là nếu tôi bỏ lỡ câu trả lời không mong muốn, mã của tôi sẽ không chờ đợi nó. – dantheman

+1

Vì vậy, trong khi tôi không quan tâm đến ý tưởng thực hiện một hàng đợi như vậy (là một ứng dụng hạn chế bộ nhớ khá) vô hiệu hóa các phản ứng không mong muốn là không hoàn toàn có thể. Tôi không thích ý tưởng thêm khả năng xử lý cho tất cả các chức năng lệnh để giải thích khả năng bị gián đoạn để hàng đợi có ý nghĩa hơn rất nhiều. Cảm ơn bạn vì câu trả lời! – dantheman

+1

@dantheman Hy vọng hàng đợi của bạn có thể nhỏ. Bạn có thể sắp xếp hàng đợi trên stack nếu bạn muốn có 'gsm_sendCommand' của bạn có thêm một vài tham số cho' char * buf' và 'size_t bufLen'. Các hàm gọi là 'gsm_sendCommand' có thể cấp phát bộ đệm tạm thời trên ngăn xếp và sau khi' gsm_sendCommand' đã trả về, xử lý hàng đợi. Nhiều cách để làm điều này. –

Các vấn đề liên quan