Can’t write to GSM module through Serial connection from ARM board

armgsmserial

In our Graduation project, we're supposed to connect a GSM module (ADH8066) to our ARM board (OK-6410) which is running Embedded Linux (Qtopia) and communicate with it.

When we first operate on the module, it sends a "Ready" message, then we can communicate with it through AT commands. We've communicated with it successfully using Hyper-Terminal and managed to send a simple SMS.

The problem happens when we try to communicate with it from the ARM board.

We manage to receive the "Ready" message, but then we don't have any response.

Here is the code we've developed till now:

int main(void){

    int fd;
    char *dev ="/dev/ttySAC3";
    struct termios options;

    char buffer[20];
    char buffer2[20];
    char *bufptr;
    char *bufptr2;
    bufptr = buffer;
    bufptr2 = buffer2;
    int nbytes,nbytes2=0;

    fd = open (dev, O_RDWR | O_NOCTTY);

    tcflush(fd, TCIOFLUSH);

    tcgetattr(fd, &options);

    cfsetispeed(&options, B115200); //Set Baud-rate to 115200
    cfsetospeed(&options, B115200);

    options.c_cflag |= CLOCAL | CREAD; //Enable the receiver and set local mode
    options.c_cflag &= ~PARENB; //No parity (8N1)
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CRTSCTS; //Disable hardware flow control

    options.c_lflag |= (ICANON | ECHO | ECHOE); //enable input-canonical mode

    options.c_iflag = IGNPAR; //Ignore parity errors
    options.c_iflag &= ~(IXON | IXOFF | IXANY); //Disable software flow control

    options.c_oflag &= ~OPOST; //disable output-processing mode

    tcsetattr(fd, TCSANOW, &options);

    printf("Hello GSM\n");

    tcflush(fd, TCIOFLUSH);

    //capture the "Ready" message
    while(1){
        nbytes = read(fd, bufptr, 1);
        if (0!=strstr(buffer,"Ready")){
            printf("\nReady Found!\n");
            break;
        }
        bufptr += nbytes;
    }

    tcflush(fd, TCIOFLUSH);

    // send simple "AT" AT command
    int y = write(fd,"AT\r\n",4);
    if (y==4)
        printf("Written\n");

    //trying to capture the "OK" response for the above AT command
    while(1){
        nbytes2 = read(fd, bufptr2, 1);
        printf("%c\n",*bufptr2);
    }

    return 1;
}

we got this response:

Hello GSM


--- Ready Found! ---
Written: 3

and then it blocks and stays idle.

If we manage to capture the "Ready" message, doesn't that mean that "read" is working fine?
and If "written" is printed above, doesn't that mean that "write" is working fine?

So, why can't we communicate with the module?

Thanks.

Best Answer

Some things to check:

  • I always get bit when using UART/RS232 with the newline character & carriage return characters. It looks like you're using \r\n for that which may or may not be what the module wants. A cursory check of the module's datasheet didn't turn up anything specifying what it wants. Make sure that's what your sending out in Hyper-Terminal by checking what characters (if any) it appends for you. Go to File>Properties>Settings>ASCII Setup... for your working HyperTerminal session and see what the settings are. It may not be appending any line feeds at all (but I doubt that).

HyperTerm Settings

Sometimes peripherals only want one or the other (either \r or \n). Also, make sure you have coded them correctly for your compiler as some compilers treat string literals & escape characters differently. If you really want to know what's going on, I'd recommend a COM port sniffer (don't worry, this one's actually free). That way you can get down to the nitty gritty of what's being sent to coax the module into working.

  • I'm not sure what the line of code tcflush(fd, TCIOFLUSH); does, but you might try putting one between the read and write in case your UART buffer is getting ruined somehow.

  • Make sure you're on the right UART, there are two UARTs on the part, and one is for sending AT commands, the other is reserved.

  • Slow your baud rate down. Right now you're running at 115200 baud. Try running at 9600 baud. This might help things if there is an issue with noise on the line, which could be a real possibility depending on how you wired it up. The cable from the PC to the modem is pretty well shielded. If your setup is just bread-boarded with different length wire all over the place you could introduce/pick-up noise. Operating at a lower frequency will help reduce those effects.

  • Check for other things like number of stop bits/parity. There are several settings on a UART that a computer may have decided on for you, that your embedded driver may not have. Some common UART settings (besides baud rate) are the number of stop bits & whether or not you use parity bits. If you just used the default settings for creating your HyperTerminal Session, your likely to have the settings shown below. Check the documentation for your HW driver and make sure your processor is doing the same. HyperTerm Control Settings

  • Correct connection of UART signals. You may have been using a cross-over cable (very common), which did the matching of RX/TX pairs for you. Check if your signals are connected as shown below:

ARM UART TX -> GSM Module UART RXD0

ARM UART RX -> GSM Module UART TXD0

EDIT

If you're getting a similar output as the referenced question them more than likely the baud rate is your problem. Every time that I see an issue where I'm getting repeated characters in that make no sense, it's always a baud rate issue. You get a UART that is trying to sample bits that are coming too fast/too slow for it, which is usually evidenced as repetitive receipt of several of the same character. Sometimes the break in between characters looks like a bit at your baud rate and then the UART begins clocking in the rest of the bits, sampling all highs/lows and out comes repeated funny characters.

I would look at your RX buffer and make sure you're actually getting in the word "Ready". Don't just do a comparison using strstr because that gives you the offset of the position at which the comparison word is found, which in your case, should be 0. If you can, set a breakpoint and view each of the characters to make sure you really got the word "Ready".

Zerioze each of your buffers ( buffer[20] and buffer2[20]) with a known value (for example 0x00) before you start any reads/writes using a for loop and writing that value to each of array elements. That will help you see if the characters in your array are actually changing and you're not just printing what's left in memory when your program starts.

I would try changing the baud rate of the UART RX/TX separately. It looks like you have that ability from your code

cfsetispeed(&options, B115200); //Set Baud-rate to 115200
cfsetospeed(&options, B115200);

If you're really convinced you're receiving the "Ready" but transmitting gibberish, then only change the speed of the TX UART. Vary that until your results change. I can't imagine that this part would use different speeds for TX/RX, but I've seen crazier. Overall, check the actual buffer contents using breakpoints, don't just rely on the string comparison functions and you might learn something from that.