Search code examples
clinuxembeddedserial-portlpc

Serial communication with LPC1786


I what to send some commands to a LPC 1786 microcontroller over a serial port. To accomplish this task I open the serial port using this code.

struct termios tio;
int tty_fd;

memset(&tio,0,sizeof(tio));
tio.c_iflag = 0;
tio.c_oflag = 0;
tio.c_cflag = CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
tio.c_lflag = 0;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 5;

tty_fd = open(device, O_RDWR | O_NONBLOCK);
cfsetospeed(&tio, B9600);            // 115200 baud
cfsetispeed(&tio, B9600);            // 115200 baud
tcflush(tty_fd, TCIFLUSH);

This is for an embedded linux system using (iMX53). When I compile the code on my PC and run it. I get this:

sent:    ?
recieve: Sinchronized<CR><LF>
sent:    Sinchronized<CR><LF>
recieve: Synchronized<CR>OK<CR><LF>
sent:    16000<CR><LF>
recieve: 16000<CR>OK<CR><LF>

witch is fine. When I cross compile it and upload it to the system I get this.

Sent:  ?
HEX:   0x53 0x79 0x6E 0x63 0x68 0x72 0x6F 0x6E 0x69 0x7A 0x65 0x64 0xA 0xA 0x53 0x79 0x6E 0x63 0x68 0x72 0x6F 0x6E 0x69 0x7A 0x65 0xA
ASCII: SynchronizedSynchronizedOKOKnchronized1K024K024chronized1

Sent:  ?
HEX:   0xA 0xA 0xA 0xA 0xA 0xA 0xA 0x30 0xA 0xA 0x31 0xA 0xA 0xA 0xA 0xA 0xA 0x34 0xA 0xA 0x31 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0A
ASCII: 014141hronized1111111ronized1

witch kind of ruins my day. For writing and reading I'm using write & read functions. I bet this is to do with the way I am opening the serial port. But what wrong. I have tried different settings but with little success. In the best case as a response I get "?????1???". And most of the time there is nothing to be read.


Solution

  • The fundamental problem is that your code indicates that you have not (properly) initialized the tty port. Essentially the initialization does not call tcsetattr() to install the updated configuration that you tried to specify.

    The proper way to initialize the tty port is to open the port, obtain the current attributes, save the current attributes for restoration on program exit, modify the attributes, and install the attributes. And always test the return codes from system calls.

        tty_fd = open(device, O_RDWR | O_NONBLOCK);
        if (tty_fd< 0) {
            syslog(LOG_DEBUG, "failed to open: %d, %s", tty_fd, strerror(errno));
            exit (-1);
        }
        rc = tcgetattr(tty_fd, &tio);
        if (rc < 0) {
            syslog(LOG_DEBUG, "failed to get attr: %d, %s", rc, strerror(errno));
            exit (-2);
        }
        savetio = tio;    /* preserve original settings for restoration */
    
        spd = B9600;
        cfsetospeed(&tio, (speed_t)spd);
        cfsetispeed(&tio, (speed_t)spd);
    
        cfmakeraw(&tio);
    
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 5;
    
        tio.c_cflag &= ~CSTOPB;
        tio.c_cflag &= ~CRTSCTS;    /* no HW flow control? */
        tio.c_cflag |= CLOCAL | CREAD;
        rc = tcsetattr(tty_fd, TCSANOW, &tio);
        if (rc < 0) {
            syslog(LOG_DEBUG, "failed to set attr: %d, %s", rc, strerror(errno));
            exit (-3);
        }
    

    Of course there may also be cabling and hardware issues still to be resolved, but since the tty port has not been initialized to the operational state that you want or need, nothing is likely to function as you expect.

    Here's a guide for programming the serial port.