Проверить значение в буферном массиве 0 и не NULL в ответ на AT модем?


Я программирую драйвер для модема на основе команд AT. Вот таблица данных

Http://www.cermetek.com/Catalog/High-Speed-Modems/DataSheet/CH1794_607-0003.pdf

Модем подключен последовательно через конвертер USB to TTL к моему компьютеру.

Существует два режима ответных сообщений для модема: краткий или короткий, который возвращает числовое значение, и длинный, который возвращает строку.

Я хотел бы использовать краткую форму, но у меня есть столкнулся с некоторыми проблемами. Краткая форма для ответного сообщения " OK " равна 0. У меня есть буфер, который считывает ответное сообщение. Буфер очищается перед чтением каждого ответного сообщения, чтобы гарантировать отсутствие перекрытия предыдущих ответов. Из-за этой очистки перед считыванием ответа начальное значение буфера равно 0 или NULL, независимо от того, является ли ответное сообщение "ОК" или нет. Это заставляет мою программу входить в бесконечный цикл проверки значения.

Есть ли как я могу проверить это ответное сообщение правильно, используя короткую форму? Я протестировал код, используя длинную форму, и он отлично работает. С короткой формой будет просто легче работать, когда ответные сообщения будут иметь длину около 30 символов.

Примечание: это не синтаксический вопрос, а скорее вопрос алгоритма.

Вот основной кусок кода

void EM_Modem_Manager(void)
{
switch(m_nModemStateMachine)
{
    case MODEM_RESET:
            EM_Modem_sendTxCommand(ATZ_COMMAND);
            if(m_nModemReceiveBuffer[0] == 'O' && m_nModemReceiveBuffer[1] == 'K')
            {
                m_nModemStateMachine = MODEM_INIT;
                //EM_Modem_sendTxCommand(ATV0_COMMAND); //this is the command that sets the modem in short form
                EM_clearReceiveBuffer();
            }
        break;
    case MODEM_INIT:

        //does not work this way, ie short form, stuck in MODEM_INIT
        //EM_Modem_sendTxCommand(ATX1_COMMAND);
        //if(m_nModemReceiveBuffer[0] == 0)
        //{
        //    m_nModemStateMachine = MODEM_POLL_CONNECTION;
        //    EM_clearReceiveBuffer();
        //}

        //works this way, ie long form
        EM_Modem_sendTxCommand(ATX1_COMMAND);
        if(m_nModemReceiveBuffer[0] == 'O' && m_nModemReceiveBuffer[1] == 'K')
        {
            m_nModemStateMachine = MODEM_POLL_CONNECTION;
            EM_clearReceiveBuffer();
        }

        break;
    case MODEM_POLL_CONNECTION:
        //some code
        break;
    case MODEM_CONNECTED:
        //some code
        break;
}
}

EDIT2: я решил первую проблему редактирования, поэтому просто проигнорируйте ее (на самом деле я удалю ее в целом). Я изолировал проблему. Краткий код возвращает каретку после каждого кода результата. Это перезаписывается в месте фактического кода результата, т. е. когда возвращается код результата 0, он возвращается, но возврат каретки или значение 13 немедленно перезаписывает его. Это справедливо для всех кодов результатов.

3 2

3 ответа:

Есть ли какой-либо способ, которым я могу проверить это ответное сообщение правильно, используя короткую форму?

Да.
Вы должны написать код, который обращает внимание на количество прочитанных байтов.
Это должно быть тривиальным вопросом, чтобы определить, что ни один байт не является допустимым в буфере против одного (или более) байт являются допустимыми данными для синтаксического анализа.

Начальное значение буфера равно 0, или NULL

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

Инициализация или очистка буфера перед операцией чтения (если не для отладки) часто является костылем для плохого / плохого кода.

Возможно, вы также пытаетесь использовать строковые методы (например, null завершение) с бинарными данными.
Не делай этого. Все функциональные двоичные протоколы имеют количество байтов, связанное с каждым блоком переменной длины или датаграммой данных. Только при работе с переносами или блоками фиксированной длины длина может быть жестко закодирована.

Добавление

Вы не упомянули об этом, но в руководстве указано, что за каждым кратким кодом следует символ CR.
Другими словами этот ответ представляет собой гибрид двоичного байтового значения в сочетании с ASCII символ окончания строки.
Но для правильного и надежного ввода операция чтения должна быть неканонической (aka raw ), потому что ASCII-коды для backspace, linefeed и carriage return также являются допустимыми краткими кодами, отправляемыми этим модемом.

Я бы рекомендовал установить значение в вашем буфере на известное, неиспользуемое значение, а не очищать его с помощью 0. Затем вы можете проверить, был ли ответ на самом деле 0. Например, предположим, что 0xff не является допустимым возвращаемым значением:

#define UNUSED_VALUE        0xffU
#define NUM_BUFFER_BYTES    100U

static unsigned char my_buffer[NUM_BUFFER_BYTES];

void clear_my_buffer (void)
{
    memset(my_buffer, UNUSED_VALUE, NUM_BUFFER_BYTES);
}

Или что-то в этом роде...

Не видя ни одного из ваших кодов, я бы предложил fgets():

char *get_line (char *s, size_t n, FILE *f)
{
  char *p = fgets (s, n, f); //for f: pass (and use) whatever input stream you have defined for your modem

  if (p != NULL) /*do something here to process p  */;  
  return p;
}