1
votes

I am trying to use QSerialPort to implement one side of a simple serial communication protocol. The board on the receiving end of the protocol is not under my control, so I am trying to debug my side by using a null DE-9 cable to loop-back from one serial port to another on the same board, and running a simple "listener" app that relies on the same underlying transport-protocol code.

The transport protocol requires instantly sending an "acknowledgment" packet when a valid message packet is received, so ports are always opened in read/write mode, and after each message packet is sent the code waits and listens for an acknowledgment; the port is not closed again until after a timeout period has passed. EDIT 4: The port is, however, closed when the program is not trying to send a message or specifically listening for data.

I've discovered that the code behaves differently depending on whether or not the baud rate of the ports before the Qt programs are run matches the baud rate selected by the Qt program. That is, I'm using setBaudRate() (in both the sender and the listener) to determine the baud rate, and if I set it to whatever it was before running my programs, then the listener sees the correct byte sequences, but if I set it to something else, then the listener just sees garbage on the serial port.

(Even when the listener sees the correct byte sequences and sends acks, these acks are not seen by the other program, and I'm not sure why; I suspect this problem may be related, but for this question it's not my focus.)

It does not appear to matter what baud rate is actually used; I just need to set it using stty before running the Qt programs, even though the Qt programs set the baud rate explicitly. If I use stty to set the baud rate to something other than what the Qt programs use, the listener sees garbage.

I have printed the values of baudRate(Input), baudRate(Output), dataBits(), flowControl(), parity(), and stopBits() for each port after setting the baud rates in order to assess whether the baud rate isn't being set correctly or whether some other property of the serial port is incorrect, but the values printed are identical in every case.

I have experimented (though not extensively) with other properties of stty (for instance setting both ports to raw or to cooked before running my programs), and have observed that no settings except for the baud rate appear to have any affect.

Does anyone have any idea what might be going on here, how to debug it, and whether QSerialPort or QSerialPortInfo provide the proper tools to fix whatever inconsistency is manifesting?

EDIT: To clarify, I know that the Qt baud-rate-setting code is having some effect, because the remote end of the protocol (the one that's not under my control) uses 57600 baud, and I can send and receive some messages with that hardware after using Qt (not stty) to change my port's baud rate from the default 9600 to 57600. (If I do not change the baud rate, communication is not possible; I get characters that don't match what the hardware is actually sending.)

It should also be clear that the Qt code is having some effect from the fact that the loopback test would always work if there were no effect from setting the baud rate in my program.

EDIT 2: Before setting the baud rate, Qt apparently perceives the rate, as determined by baudRate(), to be 9600 (the default rate), regardless of how it has been set by stty.

Also, if I use stty to set the "sending" side to the "right" baud rate and the "listening" side to the "wrong" baud rate, I get the partially-correct behavior that I get when both ports are set to the "wrong" rate in advance (i.e. the listener sees messages, but the sender never sees acknowledgments).

EDIT 3: I previously had an edit noting that some of these tests were done with the loopback cable unplugged, but I have just realized that I was mistaken.

Qt version: 5.4.0

OS: Debian 7

1
Check with strace to see if the baud rate is being set by Qt?Hamish Moffatt
@HamishMoffatt During the program's execution, you mean? I know that at least the sender is correctly setting the baud rate in both directions, and the listener is using the same code.Kyle Strand
Seems like stty is actually setting the baud rate (because we can trust that it works), and the Qt programs are merely a rubber stamp or doing nothing. Comment out the setBaudRate() and see what happens; i.e. I predict no difference.sawdust
@sawdust I think you're misunderstanding the situation. First, both Qt programs use the same baud-rate-setting code, and I have been using stty to set both ports to the same baud rate before launching the programs, so if the issue were just that setBaudRate() were doing nothing, the loopback test would always work. Second, setting the baud rate with Qt affects whether I can exchange messages with the other hardware (the one that's out of my control).Kyle Strand
"I think you're misunderstanding the situation." -- Maybe, but no worse than you. A properly-written program using the serial port should fully configure the port to its requirements. Any previous settings should not interfere or affect the program's use of the port. That is not what you're reporting. You're collecting and reporting a lot of experimental data, instead of analyzing why the initialization code is incomplete.sawdust

1 Answers

1
votes

It turns out I was losing data due to the fact that I was opening and closing the ports. When a QSerialPort is closed, data is either not buffered (by the driver) in the first place, or it is discarded as soon as the port is re-opened.

Presumably, the reason that setting the baud rate using stty to match the baud rate used by Qt affected the program behavior is that, when the baud rate is already what Qt needs to set it to, the setBaudRate() call is a no-op, and no clean-up action is required upon close to restore the old baud rate; whereas when Qt does need to change the baud rate, it must also restore the old baud rate when closing the port, which takes up a significant amount of processing time.