1

I bought a GSM module and I am trying to control it through a USB to serial interface (FT232 to name the component).

I wrote a little program to test the FT232 (by linking TX to RX) before the GSM module and I am facing to a problem.

I can send data (typically "AT\r") and I can receive the same data (hopefully) but I receive data again and again (often '0x0A' and sometimes the original data : "AT\r") ...

Can you help me to solve this ?


Code of main.c

#include    <fcntl.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <sys/ioctl.h>
#include    <sys/select.h>
#include    <sys/time.h>
#include    <sys/types.h>
#include    <termios.h>
#include    <unistd.h>

int open_serial();

int close_serial(int serial_fd);

int read_serial (int fd);

int main ()
{
    int serial_fd = open_serial();

    if (serial_fd == EXIT_FAILURE)
        return EXIT_FAILURE;

    struct termios old_termios;
    struct termios serial_termios;

    //  Port configuration backup
    tcgetattr(serial_fd, &old_termios);
    serial_termios = old_termios;
    //  Port setup
    serial_termios.c_cflag |= (B9600 | CS8 | CLOCAL | CREAD);
    serial_termios.c_lflag |= (ICANON);
    //  Port configuration update
    tcsetattr(serial_fd, TCSANOW, &serial_termios);

    int num_char;
    char* str2send = "AT\r";

    num_char = write(serial_fd, str2send, strlen(str2send));
    if (num_char < 0)
    {
        fputs("FAIL !\n", stderr);
    }
    else
    {
        printf("%d char sended\n", num_char);
    }

    fd_set  serial_in;
    int count=0;    

    while ((read_serial(serial_fd) > 0) & (count < 25))
        count++;

    //  Port configuration restore
    tcsetattr(serial_fd, TCSANOW, &old_termios);

    return close_serial(serial_fd);
}

int open_serial()
{
    int serial_fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

    printf("Serial port opening...\n");
    if (serial_fd == -1)
    {
        printf("FAIL !\n");
        perror("open()");
        return EXIT_FAILURE;
    }
    printf("SUCCESS ! [FD] : [%02d]\n", serial_fd);

    return serial_fd;
}

int close_serial(int serial_fd)
{
    printf("Serial port closing...\n[FD] : [%02d]\n", serial_fd);
    if (close(serial_fd) == -1)
    {
        printf("FAIL !\n");
        perror("close()");
        return EXIT_FAILURE;
    }
    printf("SUCCESS !\n");

    return EXIT_SUCCESS;
}
int read_serial (int fd)
{
    char rcv_serial [256];
    int max_fd = fd + 1;
    fd_set input;
    FD_ZERO(&input);
    FD_SET(fd, &input);
    int count;
    //  1sec timeout
    struct timeval timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    int nb_char, ret_read;
    int ret_sel = select(max_fd, &input, NULL, NULL, &timeout);
    if (ret_sel < 0)
    {
        perror("select() :");
    }
    else if (ret_sel == 0)
    {
        printf("TIMEOUT\n");
    }
    else
    {
        if (FD_ISSET(fd, &input))
        {
            nb_char = 10;
            ioctl(fd, FIONREAD, &nb_char);
            printf("%d chars availables\n", nb_char);
            ret_read = read(fd, &rcv_serial, nb_char);
            printf("[ RET READ : %d]\n", ret_read);
            rcv_serial[ret_read] ='\0';
            for (count = 0; count < ret_read; count++)
                printf("[%02X]", rcv_serial[count]);
            printf("\n");
            //printf("[%s]\n", rcv_serial);
        }
    }
    return ret_sel;
}

Result

Serial port opening...
SUCCESS ! [FD] : [03]
3 char sended
3 chars availables
[ RET READ : 3]
[41][54][0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
Serial port closing...
Teutates
  • 11
  • 4
  • 1
    If you continue to read the DR when there's no new data, it will continue to be the same. AT commands end in `"\r\n"` and `'\n` may `' == 0xA`, so it makes sense. – Fiddling Bits Feb 16 '17 at 15:47
  • Thank you for your answer. It makes sense with this command, but how do I know if there is a new message or an incoming call ? Should I continuously check the serial port ? – Teutates Feb 16 '17 at 15:52
  • @Fiddling-Bits, you say that the register of the chip doesn't change when no new data is received and so contains the last character received. Makes much sense. Any idea what is wrong with his call of `read_serial`? Should it block, or return zero while no new data received? – Paul Ogilvie Feb 16 '17 at 16:00
  • read_serial return the value of select. In my case, it always return a value > 0, as if there was new data – Teutates Feb 16 '17 at 16:18
  • I added the output, and as we can see, the output sometimes changes. I don't understand why – Teutates Feb 16 '17 at 16:25
  • You fail to disable input echo (ECHO, ECHOE) in the termios configuration. At least you used **tcgetattr()**, and it's close but not the proper way for [Setting Terminal Modes Properly](http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html#SEC237) See [this answer](http://stackoverflow.com/questions/41841772/linux-serial-read-blocks-minicom/41844154#41844154) for more hints on proper configuration of the serial terminal. @FiddlingBits ' comment does not apply; you have a application program with an OS, and no direct access to the hardware registers. – sawdust Feb 16 '17 at 17:51
  • @sawdust Thank you very much, it works by disabling input echo ! – Teutates Feb 16 '17 at 18:23
  • Your one line fix only solves the immediate problem. You code has more issues that may or may not cause visible problems. – sawdust Feb 16 '17 at 19:32

1 Answers1

0

Thanks to @sawdust comment. I add this to solve my problem to disable input echo :

serial_termios.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN)
Teutates
  • 11
  • 4