hound 0 24 марта, 2015 Опубликовано 24 марта, 2015 (изменено) · Жалоба Откопал же тему)) надеюсь тут еще кто-то есть и увидит мое сообщение) Ковыряю модем - 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; } } } Пока без подключений к серверу, отправки данных и т.п главное пока разобраться с правильностью разбора команды и сообщений от модема. Изменено 24 марта, 2015 пользователем hound Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться