简体   繁体   English

Qt modbus串口流量控制处理

[英]Qt modbus serial port flow control handling

I'm writing a small program using QModbusDevice over the serial port (using the QModbusRtuSerialMaster class) and have some problems. 我正在通过串口(使用QModbusRtuSerialMaster类)使用QModbusDevice编写一个小程序,并遇到一些问题。

One of the problems seems to be that the flow control of the serial port is incorrect. 其中一个问题似乎是串口的流量控制不正确。 Checking in a serial port sniffer I see that a working client sets RTS on when it sends requests, and then RTS off to receive replies. 检查串口嗅探器我发现有效的客户端在发送请求时设置RTS,然后关闭RTS以接收回复。 When I use QModbusRtuSerialMaster to send messages that doesn't happen. 当我使用QModbusRtuSerialMaster发送不会发生的消息时。

The message is sent correctly (sometimes, subject for another question) compared to the working client. 与工作客户端相比,消息发送正确(有时,另一个问题)。 It's just the control flow that doesn't work and which causes the servers to be unable to reply. 只是控制流不起作用,导致服务器无法回复。

I have set the Windows port settings for the COM-port in question to hardware flow control but it doesn't matter, the sniffer still reports no flow control. 我已经将有问题的COM端口的Windows端口设置设置为硬件流控制,但没关系,嗅探器仍然没有报告流量控制。

Is there a way to get QModbusRtuSerialMaster to set the flow control as I would like? 有没有办法让QModbusRtuSerialMaster按照我的QModbusRtuSerialMaster设置流量控制? Or is there a way to manually handle the flow control (which is what the working client does)? 或者有没有办法手动处理流量控制(这是工作客户端做的)? Or is the only solution to skip the Qt modbus classes and make up my own using the serial port directly? 或者是跳过Qt modbus类并直接使用串口构建我自己的解决方案?


A short summary of what I'm doing... 我正在做的简短摘要......

First the initialization of the QModbusRtuSerialMaster object: 首先是QModbusRtuSerialMaster对象的初始化:

QModbusDevice* modbusDevice = new QModbusRtuSerialMaster(myMainWindow);

modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM3");
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud115200);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
modbusDevice->setTimeout(100);
modbusDevice->setNumberOfRetries(3);

modbusDevice->connectDevice();

Then how I send a request: 然后我如何发送请求:

auto response = modbusDevice->sendReadRequest(QModbusDataUnit(QModbusDataUnit::Coils, 0, 1), 1);

QtModbus does not implement an automatic toggling for the RTS line because it expects your hardware to do it on its own (with a dedicated line instead). QtModbus没有为RTS线实现自动切换,因为它希望您的硬件自己完成(使用专用线)。

This should be the case for most RS485 converters (even cheap ones). 对于大多数RS485转换器(即使是便宜的转换器)应该是这种情况。 You would only need the RTS line if you have a separate transceiver like this one with a DE/~RE input. 如果你有一个像一个独立的收发器,你只需要RTS行这一个带有DE / RE〜输入。

If you were on Linux and had some specific hardware you could try to use the RS485 mode to toggle the RTS line for you automatically. 如果你在Linux上并且有一些特定的硬件,你可以尝试使用RS485模式自动为你切换RTS线。 But you don't seem to be on Linux and the supported hardware is certainly very limited. 但是你似乎不在Linux上,支持的硬件肯定非常有限。

You can also toggle the line manually with port.setRequestToSend(true) , see here . 您也可以使用port.setRequestToSend(true)手动切换该行,请参见此处 But note that depending on the timing needs of the device you are talking too, this software solution might not be very reliable. 但请注意,根据您所说的设备的时序需求,此软件解决方案可能不太可靠。 This particular problem has been discussed at length here . 这个问题已经在这里详细讨论过 Take a look at the links on my answer too, I made some benchmarks with libmodbus that show good results. 看看我的答案上的链接,我用libmodbus做了一些基准测试,结果很好。

Enabling or disabling flow control on the driver won't have any effect on this issue because this is not actually a flow control problem but a direction control one. 启用或禁用驱动程序上的流控制不会对此问题产生任何影响,因为这实际上不是流控制问题,而是方向控制问题。 Modbus runs on two-wire half-duplex links very often, and that means you need a way to indicate which device is allowed to talk on the bus at all times. Modbus经常在双线半双工链路上运行,这意味着您需要一种方法来指示允许哪个设备始终在总线上通话。 The RTS (flow control) from an RS232 port can be used for this purpose as a software workaround. 来自RS232端口的RTS(流量控制)可用作软件变通方法。

In the end, it would be much less of a headache if you just replace your transceiver with one that supports hardware direction control. 最终,这将是更头疼的,如果你只是更换您的收发器一个支持硬件方向控制。 If you have a serial port with an FTDI engine you should be able to use the TXEN line for this purpose. 如果您有一个带有FTDI引擎的串行端口,您应该可以使用TXEN线来实现此目的。 Sometimes this hardware line is not directly routed and available on a pin but you can reroute it with MProg . 有时,此硬件线路不会直接路由并在引脚上可用,但您可以使用MProg重新路由它。

I would like to highlight that you did not mention if you are running your Modbus on RS485. 我想强调你没有提到你是否在RS485上运行Modbus。 I guess it's fair to assume you are, but if you have only a couple of devices next to each other you might use RS232 (even on TTL levels) and forget about direction control (you would be running full-duplex with three wires: TX, RX and GND). 我想假设你是公平的,但如果你只有几个设备彼此相邻,你可能会使用RS232(即使在TTL电平上)而忘记了方向控制(你将使用三条线运行全双工:TX ,RX和GND)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM