Pregunta

I am programming a driver for an AT command based modem. Here is the datasheet

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

The modem is connected serially via a USB to TTL converter to my PC.

There are two modes of response messages for the modem: one is terse or short form which returns a numerical value and a long form which returns a string.

I would like to use the short form, but I have come across some problems. The short form for the response message "OK" is 0. I have a buffer which reads in the response message. The buffer is cleared BEFORE each response message is read to ensure there is no overlap from previous responses. Because of this clearing before is read of the response, the initial value of the buffer is 0, or NULL, regardless if the response message is "OK" or not. This causes my program to enter an infinite loop of checking the value.

Is there any way that I can check this response message correctly using the short form? I have tested the code using the long form and it works fine. The short form would just be easier to work with down the line when the response messages get 30 or so characters long.

NOTE: This is not a syntax question, but more of an algorithm question.

Here is the main chunk of code

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: I solved the first edit problem so just disregard it (in fact I will delete it altogether). I have isolated the problem. The terse code does a carriage return after each result code. This is being over-written in the actual result code's spot, ie when a result code of 0 is returned, it is returned, but a carriage return or value 13 immediately overwrites it. This is true for all result codes.

¿Fue útil?

Solución

Is there any way that I can check this response message correctly using the short form?

Yes.
You have to write code that pays attention to the number of bytes read.
It should be a trivial matter to determine that no bytes are valid in the buffer versus one (or more) bytes are valid data for parsing.

the initial value of the buffer is 0, or NULL

Your program should not be checking the contents of the buffer unless data has been put there by the read operation.
The read operation should return the number of bytes placed into the buffer, as well as the data. If your program always checks that more than zero bytes have been "read", then the original contents of the buffer should not matter.

Initializing or clearing a buffer prior to a read operation (if not for debugging) is often a crutch for bad/poor code.

You might also be trying to use string techniques (e.g. null termination) with binary data.
Don't do that. All functional binary protocols have a byte count associated with each variable-length block or datagram of data. Only when dealing with fixed-length transfers or blocks can the length be hard coded.

ADDENDUM

You didn't mention it, but the manual indicates that each terse code is followed by a CR character.
In other words this response is a hybrid of a binary byte value combined with an ASCII line-termination character.
But for proper and reliable input, the read operation should be non-canonical (aka raw), because the ASCII codes for backspace, linefeed and carriage return are also valid terse codes sent by this modem.

Otros consejos

I would recommend setting the value in your buffer to a known, unused, value - rather than clearing it with 0. Then you can check to see if the response was actually 0. For example, assuming that 0xff is not a valid return value:

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

Or something along those lines...

Without seeing any of your code, my best guess would be to suggest 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;
}  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top