Откопал же тему)) надеюсь тут еще кто-то есть и увидит мое сообщение)
Ковыряю модем - Quectel m66, но особой роли не играет, главное те же самые АТ команды.
Использую операционку TNKernel, но тоже особой роли не играет, разве что в этой системе в очереди передается указатель на данные, а не сами данные как, например, во FreeRTOS. К этому чуть позже вернемся)
1. Сделал отдельный таск под работу с модемом.
2. Линейный буфер, куда складываются все приходящие данные с модема, которые потом из прерывания передаются в функцию обработчик (modem_process_buffer).
В функции обработчике (modem_process_buffer) проверяется строка от модема со следующими условиями:
если пришел ответ OK, то выставляется определенный флаг, который в последствии мы будем ждать в функции отправке команды.
Если пришел что-то другое, то копируем эти данные в массив буферов и номер в этом массиве отправляем уже очередью.
Пример команды AT:
Код
uint8_t modem_check_at(void) {
uint32_t flag, rc;
uart3_ex_send_string("AT\r\n");
rc = tn_event_wait(&modem_event, MODEM_SAY_OK, TN_EVENT_WCOND_OR, &flag, 300);
if (rc != TERR_NO_ERR) {
dbg_send("AT fail\r\n");
return ACTION_FAIL;
}
dbg_send("AT ok\r\n");
tn_event_clear(&modem_event, ~(MODEM_SAY_OK));
return ACTION_OK;
}
Тут все просто, нужно только дождаться чтобы флаг ОК был выставлен. Сложности начинаются с командами в которых нужно парсить ответ от модема.
Например, команда AT+CREG?
На нее модем отвечает следующим образом:
Код
+CREG: 0, 1
OK
Нужно дождаться именно этого ответа. Сделал следующим образом:
Перед отправкой команды помещаю в некоторые переменные условия по которым мы должны отправлять очередь:
Код
uint8_t modem_creg(void) {
uint32_t rc, flag, number_queue;
// Используется в прерывании для определения условия отправки очереди
strcpy(wait_data, "+CREG");
wait_length = 5;
uart3_ex_send_string("AT+CREG?\r\n");
// Ждем ответ ОК от модема, если ОК пришло значит команда успешно выполнена
rc = tn_event_wait(&modem_event, MODEM_SAY_OK, TN_EVENT_WCOND_OR, &flag, 300);
if (rc != TERR_NO_ERR) {
dbg_send("CREG fail\r\n");
return ACTION_FAIL;
}
tn_event_clear(&modem_event, ~(MODEM_SAY_OK));
// В очереди получаем порядковый номер в массиве для нашего сообщения
tn_queue_receive_polling(&queue_modem_buffer, (void**)&number_queue);
dbg_send("Answer CREG - ");
dbg_send(modem_queue_buffer[number_queue]);
dbg_send_rn();
return ACTION_OK;
}
И в свою очередь в функции modem_process_buffer (в прерывании):
Код
if (strncmp(modem_line_buffer, wait_data, wait_length) == 0) {
modem_send_queue();
}
Либо отправлять в очередь все что пришло и потом уже в функции отправки команды перебирать очереди пока не нашли нужный нам ответ, но так кажется более затратно...
И стоит ли в подобных командах CREG, где нужно разбирать ответ от модема дожидаться именно приходящего ОК сообщения? Или можно просто дождаться уже ответа от модема +CREG и его разбирать, а после флаг ОК просто сбросить...
Ах да, и вот сам таск для модема:
Код
void modem_queue_func(void *par) {
dbg_send("Task modem start\r\n");
while (1) {
modem_reset();
if (modem_check_at() == ACTION_FAIL) continue;
if (modem_qimux() == ACTION_FAIL) continue;
while (1) {
if (modem_check_at() == ACTION_FAIL) break;
if (modem_qistate() == ACTION_FAIL) break;
if (modem_cgatt() == ACTION_FAIL) break;
if (modem_creg() == ACTION_FAIL) break;
}
}
}
Пока без подключений к серверу, отправки данных и т.п главное пока разобраться с правильностью разбора команды и сообщений от модема.
Сообщение отредактировал hound - Mar 24 2015, 09:22