реклама на сайте
подробности

 
 
> GSM модем + TNKernel
hound
сообщение Mar 23 2015, 18:39
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 15-02-15
Пользователь №: 85 179



Добрый день. Есть GSM модем, управление, которого производится AT командами.
Общий вид "общения" с модемом:
1. Отправляется команда
2. Ответ модема на команду (может отсутствовать)
3. Строка "OK", что мол команда выполнена.

Соответственно есть команды, которые возвращают значение состояния модема, например:
AT+CREG?

+CREG: 0, 1
OK

А есть, которые просто выдают строчку ОК, что команда принята и все, например:
AT

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


А в самом прерывании, если от модема пришла строка содержащее слово ОК, то выставляется флаг MODEM_SAY_OK:
Код
  if (strncmp(modem_buffer, "OK", 2) == 0) {
    tn_event_iset(&modem_event, MODEM_SAY_OK);
    return;
  }


С простыми командами так проходит, но сложность возникает с теми командами, в которых нужно разбирать ответ модема.
Например команда: AT+CREG?
После отправки модему она возвращает строку с определенными параметрами и после уже слово ОК, что команда выполнена.
Поэтому простой проверкой на слово ОК не обойтись, нужно разбирать, то что ответил модем.
Сделал таким образом: все строчки, которые пришли от модема складываются в очередь, которую уже должна обработать функция, которая отправляла данную команду модему, опять же пример:
Код
uint8_t modem_creg(void) {
  uint32_t rc, flag, number_queue;
  
  uart3_ex_send_string("AT+CREG?\r\n");
  
  rc = tn_queue_receive(&queue_modem_buffer, (void**)&number_queue, 300);
  if (rc != TERR_NO_ERR) {
    dbg_send("CREG fail!\r\n");
    return ACTION_FAIL;
  }
  
  dbg_send("Answer CREG - ");
  dbg_send(modem_queue_buffer[number_queue]);
  dbg_send_rn();
}

Да момент такой еще, есть один линейный буфер, в который пишутся приходящие символы в прерывании, в том случае когда эту строчку нужно отправить через очередь, содержимое этого линейного буфера копируется в другой буфер, который представляем из себя "массив буферов" и собственно позицию в этом массиве и передается через очередь.

Но в таком случае в очередь может отправится ЭХО модема и вместо ответа "+CREG: 0,2" в функции увидим "AT+CREG?", как вариант прогонять очередь до тех пор пока не попадется нужный нам ответ:
Код
  do {
    rc = tn_queue_receive_polling(&queue_modem_buffer, (void**)&number_queue);

    if (strncmp(modem_queue_buffer[number_queue], "+CREG", 5) == 0) {
      return number_queue;
    }
  } while (rc == TERR_NO_ERR);


Но это кажется сильно натянутым решением...
Эхо от модема отключать не желательно,хотя это отчасти и решило бы проблему, но опять же не полностью.
И кроме однострочных команд, модем может выдать много строчные команды.

В общем, у кого-нибудь был опыт работы с АТ командами, кто как реализовал? Заранее благодарен за любой совет/пинок в нужную/правильную сторону.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
controller_m30
сообщение Mar 24 2015, 17:53
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 356
Регистрация: 24-02-09
Пользователь №: 45 309



А, вот какой обработчик. Это совсем другое дело! biggrin.gif
А то я так понял, что обработчик будет ждать только один ответ (заданный из основной программы), и пропускать все остальные.

Могу в качестве посильной помощи выложить скрин с логического анализатора, как выдаётся из модема ответ "+CREG: 0,1","OK". То, что отмечено как "\r" и "\n" - это непечатные символы <cr> (0x0d) и <lf>(0x0a) соответственно.

Как видно, это сплошной поток данных. Сможет ли Ваш обработчик разделить строку на "+CREG: 0,1" и "OK"? Как обработчик отделяет сообщения друг от друга? По тайм-ауту, или по <cr>, <lf> вначале и конце сообщения?
Go to the top of the page
 
+Quote Post
hound
сообщение Mar 24 2015, 18:08
Сообщение #3





Группа: Участник
Сообщений: 12
Регистрация: 15-02-15
Пользователь №: 85 179



Цитата(controller_m30 @ Mar 24 2015, 20:53) *
А, вот какой обработчик. Это совсем другое дело! biggrin.gif
А то я так понял, что обработчик будет ждать только один ответ (заданный из основной программы), и пропускать все остальные.

Могу в качестве посильной помощи выложить скрин с логического анализатора, как выдаётся из модема ответ "+CREG: 0,1","OK". То, что отмечено как "\r" и "\n" - это непечатные символы <cr> (0x0d) и <lf>(0x0a) соответственно.

Как видно, это сплошной поток данных. Сможет ли Ваш обработчик разделить строку на "+CREG: 0,1" и "OK"? Как обработчик отделяет сообщения друг от друга? По тайм-ауту, или по <cr>, <lf> вначале и конце сообщения?


По концу строки <0xOD><0xOA>
В прерывании:
Код
  if (ch == 0x0D) return;
  if (ch == 0x0A) {
    modem_line_buffer.data[modem_line_buffer.pos] = 0x00;
    modem_line_buffer.pos = 0;
    modem_process_buffer();
    return;
  }


Дальше уже в функции modem_process_buffer() идет обработка сообщения
Код
void modem_process_buffer(void) {
  if (strlen(modem_line_buffer.data) < 1) return;
  
  if (strncmp(modem_line_buffer.data, "OK", 2) == 0) {
    tn_event_iset(&modem_event, MODEM_SAY_OK);
    return;
  }  
  
  if (strncmp(modem_line_buffer.data, "SEND OK", 7) == 0) {
    tn_event_iset(&modem_event, MODEM_SEND_OK);
    return;
  }  
  
  if (strncmp(modem_line_buffer.data, "+RECEIVE", 7) == 0) {
    uint16_t length;
    length = get_modem_token_int(modem_line_buffer.data, 1);
    modem_status.read_flag = TRUE;
    modem_receive_buffer_reset(&modem_receive_buffer, length);
    return;
  }
  
  if (strncmp(modem_line_buffer.data, wait_queue.data, wait_queue.length) == 0) {
    modem_send_queue();
  }
}


Где, wait_queue.data, wait_queue.lengt это строка и ее длина для анализа ответа от модема, т.е отправили мы команду AT+CREG?
и от нее нам нужно получить ответ вида +CREG: 2
Вот значение "+CREG" мы и записывает wait_queue.data.
И уже кроме этого ответа ничего в очередь не попадает, а если что-то пришло от сервера, то в прерывании мы схватим сообщение "+RECEIVE", которое в очередь не попадет уж точно.
Как-то так.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 20:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01423 секунд с 7
ELECTRONIX ©2004-2016