Problem: QSerialPort Terminal example scrambling incoming data
-
I'm working with Qt 4.8.5 and QSerialPort along with the Terminal example on OSX. On the hardware side, I'm using a Prolific USB-to-Serial device connected to a piece of equipment that operates with 9600, 7 data bits, Even parity, and 1 stop bit and no flow control. I know the hardware is working because a regular terminal program like ZTerm works fine.
I am able to connect to the device just fine but when I get data back from the device but it's really screwed up. A % character (ASCII 37) is coming out as the yen character (ASCII 165). A 1 character (ASCII 49) is coming out as a plus/minus (ASCII 177). But some characters are unscrambled e.g. a lower case r (ASCII 114), lower case o, the numbers 0 and 9.
My hardware device has a specific string of characters that when sent reset the device which then announces itself with a version string. Sending that reset string works because I get back the exact number of characters I'm supposed to get. They're just mostly scrambled.
-
I am also using QtSerialPort with Qt4.8.5 and it works like it shall works.. Take a look at the incoming bytes itelf as hex and not as char. Is that still the same you send? If yes, than it is only a converting problem.
Another mistake I cannot recognize.
-
I can look at the data in the QByteArray and it's definitely wrong. Please note that I'm testing with recently downloaded git repository for both the QSerialPort libraries as well as the terminal example.
-
This morning, I hooked up two laptops with a null modem in between and checked all of the various protocol choices: 7 or 8 data bits; even, odd, or no parity; 1 or 2 stop bits. All at 9600 baud.
Sending characters from the QSerialPort terminal example always works correctly. Receiving characters only works correctly with 8 data bits regardless of parity or stop settings. Using 7 data bits garbles the incoming data. The characters that get changed are consistent though.
-
Okay, further testing information. I need to use 7 data bits so the fact that things work with 8 is irrelevant. When I use 7 data bits, Even parity, and 1 stop bit, what happens is that characters with an even number of 1 bits come across fine. When I send a character with an odd number of 1 bits, the result has its most significant bit set.
E.g. I send an ASCII 8 character, that's 38h or 00111000. What I get in the QSerialPort terminal example is 10111000. However, if I send an ASCII 0 which is 30h or 00110000, that comes across correctly.
So it appears that there's something screwy going on with the parity. If I switch the sending terminal and the Qt terminal app to odd parity, then the opposite behavior occurs i.e. ASCII 8 is fine but ASCII 0 now has the high bit set. And if I use no parity, then the high bit is always set regardless of the character. Note, that this is only a problem with 7 data bits and it's only a problem with QSerialPort because two instances of ZTerm with 7-even-1 work just fine.
-
Okay, here's what I did to fix this. In qserialport_unix.cpp Line 568 Function QSerialPortPrivate::setDataBits I added a line:
@
case QSerialPort::Data7:
currentTermios.c_cflag |= CS7;
currentTermios.c_iflag |= ISTRIP; // NEW: strip high bit
break;
@ -
Hi,
Since you discovered a bug, did you open "bug report":http://bugreports.qt-project.org/issues/ ?
If not, that would be great since you also have found a solution
-
Hmmm... It is strange.. Why required a ISTRIP flag?
e.g. on POSIX guide this flag is not present (see "Setting the Character Size" chapter): http://ulisse.elettra.trieste.it/services/doc/serial/config.html
bq. Setting the Character Size
bq. Unlike the baud rate, there is no convienience function to set the bq. character size. Instead you must do a little bitmasking to set things bq. up. The character size is specified in bits:
bq. options.c_cflags &= ~CSIZE; /* Mask the character size bits */
bq. options.c_cflags |= CS8; /* Select 8 data bits */
Whether someone can give the reference to such strange behavior in MacOSX?
BTW: In Apple's sample:
for 7 bit, ISTRIP flag also is not present.
UPD: You are sure, that settings of terminals are identical?
-
Update: my current theory is that there is a bug in the Prolific USB-to-Serial device driver. I haven't tried the open-source version. My work around has been to shelve the device and go back to an ancient Keyspan adapter.