Anjanu
Anjanu

Reputation: 623

Linux Serial RS-232, 8th bit always clear (set to 0)

Below are Serial Communication Port Settings
1. BaudRate: 19200
2. Parity: Even
3. StopBits: 1

The transmitter sends few bytes of data: 0x5A 0xA5 0xAA
Receiver is written in C on Linux using termios serial API
I am able to receive the first byte 0x5A correctly but the byte 0xA5 is received as 0x25 and 0xAA is received as 0x2A i.e. the 8th bit of each byte is set to 0...why ?

Below is the C (OS: Linux) code extract for setting the serial port settings on receiver application:

void *threadRecv(void *arg)
{
    char *portName = (char *)arg;
    char ch;
    struct termios portSettings;

    //fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);
    fd = open(portName, O_RDONLY | O_NOCTTY);
    close(fd);
    fd = open(portName, O_RDONLY | O_NOCTTY);
    if(fd == -1)
    {
        printf("Error opening port: %s", portName);
        pthread_exit("Exiting thread");
    }

    cfsetispeed(&portSettings, B19200);

    //Parity
    portSettings.c_cflag &= ~PARENB;
    portSettings.c_cflag |= PARENB;
    portSettings.c_cflag &= ~PARODD;

    //Stop Bit
    portSettings.c_cflag &= ~CSTOPB;

    //Data Size: 8bits
    portSettings.c_cflag &= ~CSIZE;
    portSettings.c_cflag |= CS8;

    portSettings.c_cflag |= CREAD;
    portSettings.c_cflag |= CLOCAL;

    portSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    portSettings.c_iflag |= (INPCK);

    portSettings.c_oflag &= ~OPOST; //For RAW I/P

    portSettings.c_cc[VMIN] = 77;
    portSettings.c_cc[VTIME] = 0;

    if(tcsetattr(fd, TCSANOW, &portSettings) == -1)
    {
        printf("Error setting port: %s", portName);
        pthread_exit("Exiting thread");
    }
    while(1)
    {
        //Recv Logic
    }
}

Upvotes: 0

Views: 484

Answers (1)

sawdust
sawdust

Reputation: 17047

While your code follows the preferred practice of bit-wise modifying the terms of the termios structure, your program is missing the salient initialization of the structure by calling tcgetattr(fd, &portSettings).
If the garbage values in the uninitialized termios stucture has the iflag.ISTRIP enabled, then that could explain the results you see.
Since your code only does minimal modification of the iflag bits, it should have a statement similar to what the cfmakeraw() does:

portSettings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP 
                             | INLCR | IGNCR | ICRNL | IXON); 

See Serial Programming Guide for POSIX Operating Systems.


portSettings.c_cc[VMIN] = 77;
portSettings.c_cc[VTIME] = 0;

This is a problematic configuration if message frame synchronization is ever lost. Specifying a nonzero VTIME would be a safety measure that would permit recovery as long as you have proper hunt logic for re-achieving message synchronization.


BTW raw (aka non-canonical) I/O is typically 8 bits with no parity. Eight bits with parity is an unusual configuration. Are you trying to emulate receiving 9-bit character frames (i.e. 9N1)?

Upvotes: 1

Related Questions