10101010 10101010 - 5 months ago 16
Linux Question

serial port: bytes from device all have their most significant bit = 0

guys tell me please what can be a problem - i send commands (sequence of bytes including bytes with most significant bit (MSB) = 1) to device through serial port, device successfully recognize the commands (so it seems all bytes are sent correct) and reply with almost correct answer. "Almost" here means than answer is correct except that all bytes have zero MSB (while some of them must have MSB = 1).

I use Ubuntu 16 on VirtualBox, Windows 7 as host OS, serial port as USB device on FTDI chip.

Here my serial port settings:

void com::open()
{
fd = ::open( "/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY );
if ( fd < 0 )
{
throw exceptionSystem( ERROR_UNK, "Error open COM port" );
}

int err;
err = fcntl(fd, F_SETFL, FNDELAY);
if ( err == -1 )
{
close();
throw exceptionSystem( ERROR_UNK, "Error fcntl" );
}

try{
set();
}catch(...){
close();
throw;
}
}

void com::set()
{
if ( fd == -1 )
return;

struct termios tty;
memset( &tty, 0, sizeof( tty ) );
if ( tcgetattr(fd, &tty) != 0 )
{
throw exceptionSystem( ERROR_UNK, "Error tcgetattr" );
}

int err;
err = cfsetospeed( &tty, B115200 );
if ( err != 0 )
{
throw exceptionSystem( ERROR_UNK, "Error fsetospeed" );
}
err = cfsetispeed( &tty, B115200 );
if ( err != 0 )
{
throw exceptionSystem( ERROR_UNK, "Error cfsetispeed" );
}

tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag |= PARENB;
tty.c_cflag &= ~PARODD;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag |= CLOCAL;
tty.c_cflag |= CREAD;
tty.c_cflag &= ~CRTSCTS;

tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

tty.c_iflag |= (INPCK | ISTRIP);
tty.c_iflag &= ~IGNPAR;
tty.c_iflag &= ~PARMRK;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);

tty.c_oflag &= ~OPOST;

tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;

if ( tcsetattr( fd, TCSANOW, &tty ) != 0 )
{
throw exceptionSystem( ERROR_UNK, "Error tcsetattr" );
}
}

Answer

EDIT I've just seen the problem. You've got the line

tty.c_iflag |= (INPCK | ISTRIP);

ISTRIP means "strip off the eighth bit". You need

tty.c_iflag |= INPCK;

to simply enable input parity.


You've enabled EVEN parity

tty.c_cflag |= PARENB;
tty.c_cflag &= ~PARODD;

as well as 8-bit bytes

tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;

So that's one start bit, 8 data bits, 1 parity bit, and 1 stop bit. I'm not sure that the FTDI chip can handle all that!

If you don't want parity, use

tty.c_cflag &= ~PARENB;

And if I've maligned the FTDI chip, I apologise - in which case are you sure the other end is configured the same way? 8E1 is not very common compared to 7E1 or 8N1