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!
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
Đó 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