本文介绍了驱动程序CH341 USB适配器串行端口或QSerialPort在Linux中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码对我而言在Windows中正常工作,但Linux不起作用.我使用的是同一台PC,两个操作系统都是本地安装的.我不使用虚拟机.我需要在Linux上工作.我尝试了不同的Linux发行版,但在任何地方都无法使用.

The following code works for me correctly in Windows, but Linux does not work. I am using the same PC, both operating systems are installed native. I do not use virtual machine. I need to work on Linux. I have tried in different linux distributions and does not work anywhere.

// In the main class:
QSerialPortInfo info = XXXX; // Generally in Linux: /dev/ttyUSB0, in win: COM1
QSerialPort serial;
QObject::connect(&serial, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection);
QObject::connect(&serial, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)), Qt::DirectConnection);
QObject::connect(&serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)), Qt::DirectConnection);

// Slot
void MyClass::onReadyRead()
{
    qDebug()<<"Signal onReadyRead";
    buffer_mutex.lock();
    buffer += serial.readAll();
    qDebug()<<"Read: "<<qstr_to_hexstr(buffer);
    bufferNotEmpty.wakeAll();
    buffer_mutex.unlock();
}

void MyClass::onError(QSerialPort::SerialPortError error) {
    qCritical()<<"Serial Port Error: "<<(int)error;
}

void MyClass::onBytesWritten(qint64 size){
    qDebug()<<"onBytesWritten: "<<size;
}


// In another place I did:
serial.setPort(info);
if(!serial.open(QIODevice::ReadWrite))
    return false;

qDebug()<<"Init Setting!...";

if(!serial.setBaudRate(QSerialPort::Baud9600))
    qCritical()<<"Error in setBaudRate";
if(!serial.setDataBits(QSerialPort::Data8))
    qCritical()<<"Error in setDataBits";
if(!serial.setParity(QSerialPort::EvenParity))
    qCritical()<<"Error in setParity";
if(!serial.setStopBits(QSerialPort::OneStop))
    qCritical()<<"Error in setStopBits";
if(!serial.setFlowControl(QSerialPort::SoftwareControl))
    qCritical()<<"Error in setFlowControl";
if(!serial.setDataTerminalReady(true))
    qCritical()<<"Error in setDataTerminalReady";

qDebug()<<"Setting ready!...";

如果发送1个字节,则设备会响应并正确发送数据.

If sending 1 byte the device responds and sends the data correctly.

示例:

// In the main class:
const char enq[2] = {0x05, '\0'};
serial.write (enq);

// In onReadyRead:
serial.readAll(); // Works on Win / Linux

如果发送了一个多于1个字节的设备,则不会在linux中响应该请求.

If sent a more than 1 byte device does not respond the request in linux.

示例:

// In the main class:
const char command[6] = {0x02, 'S', '1', 0x03, 'a', '\0'};
serial.write(command);

// In onReadyRead
serial.readAll(); // Works only in Win

仅在Windows中触发此事件.在linux中,它永远无法工作,无法接收或格式错误,也永远无法识别远程设备.

This event is triggered only in windows. In linux it never works, not received or arrives in bad format and never recognized the remote device.

我在Windows中的日志:

My log in Windows:

{Debug}         Init Setting!...
{Debug}         Setting ready!...
{Debug}         Write:  " 0x05 "
{Debug}         onBytesWritten:  1
{Debug}         buffer wait!...
{Debug}         Signal onReadyRead
{Debug}         Read:  " 0x02 `@ 0x03 #"
{Debug}         buffer size:  5
{Critical}      Serial Port Error:  0
{Debug}         Write:  " 0x02 S1 0x03 a"
{Debug}         onBytesWritten:  5
{Debug}         buffer wait!...
{Debug}         Signal onReadyRead
{Debug}         Read:  " 0x02 S100 0x0A 00000000000000000 0x0A 00000479"
{Debug}         buffer size:  32
{Debug}         buffer wait!...
{Debug}         Signal onReadyRead
{Debug}         Read:  " 0x02 S100 0x0A 00000000000000000 0x0A 00000479 0x0A 00000 0x0A 00000330 0x0A 00000 0x0A 0061 0x0A 0000 0x0A "
{Debug}         buffer size:  64
{Debug}         Signal onReadyRead
{Debug}         buffer wait!...
{Debug}         Read:  " 0x02 S100 0x0A 00000000000000000 0x0A 00000479 0x0A 00000 0x0A 00000330 0x0A 00000 0x0A 0061 0x0A 0000 0x0A X-XXXXXXXX 0x0A XXXXXXXXX 0x0A 221715 0x0A 120414 0x0A  0x03  0x1B "
{Debug}         buffer size:  103
{Critical}      Serial Port Error:  0

(我将设备的实际响应替换为'X'字符)

(I replace the actual response of the device by the 'X' characters)

我在Linux中的日志:

My log in Linux:

{Debug}         Init Setting!...
{Debug}         Setting ready!...
{Debug}         Write:  " 0x05 "
{Debug}         onBytesWritten:  1
{Debug}         buffer wait!...
{Debug}         Signal onReadyRead
{Debug}         Read:  " 0x02 `@ 0x03 #"
{Debug}         buffer size:  5
{Critical}      Serial Port Error:  0
{Debug}         Write:  " 0x02 S1 0x03 a"
{Debug}         onBytesWritten:  5
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         buffer wait!...
{Debug}         timeout!... (15 sec for timeout)

USB串行适配器:CH340

USB Serial Adapter: CH340

In Windows: USB\VID_1A86&PID_7523&REV_0254
In Linux:
    Apr 13 01:16:58 kali kernel: [47844.260136] usb 2-1: new full-speed USB device number 16 using uhci_hcd
    Apr 13 01:16:58 kali kernel: [47844.428098] usb 2-1: New USB device found, idVendor=1a86, idProduct=7523
    Apr 13 01:16:58 kali kernel: [47844.428115] usb 2-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
    Apr 13 01:16:58 kali kernel: [47844.428126] usb 2-1: Product: USB2.0-Ser!
    Apr 13 01:16:58 kali kernel: [47844.431268] ch341 2-1:1.0: ch341-uart converter detected
    Apr 13 01:16:58 kali kernel: [47844.445398] usb 2-1: ch341-uart converter now attached to ttyUSB0
    Apr 13 01:16:58 kali mtp-probe: checking bus 2, device 16: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1"
    Apr 13 01:16:58 kali mtp-probe: bus: 2, device: 16 was not an MTP device

PD:对不起,我的英语,请尝试使用Google翻译:: ......

PD: Sorry for my English, try to do my best with Google Translator :(...

更多信息1:

Apr 13 04:10:55 kali kernel: [ 4872.627980] tty ttyUSB0: serial_write - 1 byte(s)
Apr 13 04:10:55 kali kernel: [ 4872.629763] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:55 kali kernel: [ 4872.629778] tty ttyUSB0: serial_wait_until_sent
Apr 13 04:10:55 kali kernel: [ 4872.638252] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:55 kali kernel: [ 4872.638267] tty ttyUSB0: serial_write_room
Apr 13 04:10:55 kali kernel: [ 4872.638278] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:55 kali kernel: [ 4872.638287] tty ttyUSB0: serial_write_room
Apr 13 04:10:55 kali kernel: [ 4872.639438] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:55 kali kernel: [ 4872.639458] tty ttyUSB0: serial_write_room
Apr 13 04:10:55 kali kernel: [ 4872.639475] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:55 kali kernel: [ 4872.639488] tty ttyUSB0: serial_write_room
Apr 13 04:10:56 kali kernel: [ 4873.641799] tty ttyUSB0: serial_ioctl - cmd 0x540b
Apr 13 04:10:56 kali kernel: [ 4873.646884] tty ttyUSB0: serial_write - 5 byte(s)
Apr 13 04:10:56 kali kernel: [ 4873.647152] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change
Apr 13 04:10:56 kali kernel: [ 4873.647176] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01
Apr 13 04:10:56 kali kernel: [ 4873.647384] tty ttyUSB0: serial_chars_in_buffer
Apr 13 04:10:56 kali kernel: [ 4873.647401] tty ttyUSB0: serial_wait_until_sent
Apr 13 04:10:56 kali kernel: [ 4873.649144] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change
Apr 13 04:10:56 kali kernel: [ 4873.649166] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01
Apr 13 04:10:56 kali kernel: [ 4873.692152] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change
Apr 13 04:10:56 kali kernel: [ 4873.692170] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01
Apr 13 04:10:56 kali kernel: [ 4873.694133] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change
Apr 13 04:10:56 kali kernel: [ 4873.694148] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01

我重建ch341.c并添加:

I rebuild ch341.c and add:

if (!delta)
    return;

dev_info(&port->dev, "%s - delta=0x%02X\n", __func__, delta); // <---- New Line

if (delta & CH341_BIT_CTS)
    port->icount.cts++;
if (delta & CH341_BIT_DSR)
    port->icount.dsr++;
if (delta & CH341_BIT_RI)
    port->icount.rng++;
if (delta & CH341_BIT_DCD) {
    port->icount.dcd++;
    tty = tty_port_tty_get(&port->port);
    if (tty) {
        usb_serial_handle_dcd_change(port, tty,
                    status & CH341_BIT_DCD);
        tty_kref_put(tty);
    }
}

日志中的

delta = 0x01是标志:

delta=0x01 in the log is flag:

#define CH341_BIT_CTS 0x01

更多信息2:

我希望在write/read线程中可以在onReadyRead上运行akeAll.如果您经过一秒钟,请先检查所有缓冲区是否为空,然后再执行一次readAll.例如:

In the thread of write / read I hope for wakeAll, running on onReadyRead. If you pass a second make a readAll before checking if the buffer is empty. example:

// In the main class:
QWaitCondition bufferNotEmpty;

// In my function write/read:
serial.write(data, size);
buffer_mutex.lock();
while(time(NULL)-timeStart<timeoutWait && serial.isOpen()) {
    buffer += serial.readAll();
    if(buffer.count()>0){
        qDebug()<<"buffer size: "<<buffer.count();
        //Interprete the buffer here...

        if(bufferComplete)
            break;
    }
    qDebug()<<"buffer wait!...";
    bufferNotEmpty.wait(&buffer_mutex, 1000);
}
buffer.clear();
buffer_mutex.unlock();

更多信息3:

我的内核是3.12.6,但是我从GitHub更新了此文件,并重新构建了该驱动程序:

My Kernel is 3.12.6, but i updated from GitHub this file an rebuild this drivers:

https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c https://github.com/torvalds/linux /blob/master/drivers/usb/serial/usb-serial.c (提交d9a38a8741fdffabc32e6d0943b1cdcf22712bec)

https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.chttps://github.com/torvalds/linux/blob/master/drivers/usb/serial/usb-serial.c(commit d9a38a8741fdffabc32e6d0943b1cdcf22712bec)

推荐答案

感谢Linux的开发人员,解决了我的问题,邮件列表中未实现奇偶校验的CH34x驱动程序是将来有此问题的人的链接PATCH ,而不是它们是否适用于官方内核,目前唯一的方法是重建驱动程序.

Thanks to the developers of Linux, solved my problem, the CH34x driver not implemented parity in the maillist is the link PATCH for those who have this problem in the future, not whether they apply to the official kernel, for now only way is rebuild the driver.

http://marc.info/?l=linux- serial& m = 139749273432052& w = 2

这篇关于驱动程序CH341 USB适配器串行端口或QSerialPort在Linux中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 18:42