问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

USB转多路串口应用软件说明

创作时间:
作者:
@小白创作中心

USB转多路串口应用软件说明

引用
CSDN
1.
https://blog.csdn.net/gavinpeng/article/details/140473094

概述

PL731模块实现1个USB接口转7个异步串口(USART[1-7])功能。用于为计算机扩展异步串口,满足大多数一对多应用场景。支持Windows 10及以上系统,绝大多数Linux系统。嵌入式Linux系统有可能经过裁剪,需要系统开发人员确保系统安装正式的驱动程序,后面有相关说明。

PL731 使用1个USB接口与USB主机通信,属于USB 2.0协议下的USB CDC类设备,需要系统已安装对应的驱动才能正确枚举出7个串口设备。

Windows 驱动说明

Windows 10及以上系统自带USB CDC驱动,正常情况下接上USB即会发现7个串口设备。Windows 7及以下操作系统,特别是经过裁剪的精简版系统(包括大多数GHOST系统)可能不能识别该设备。不建议在这些系统上使用本产品。

Linux 驱动说明

Linux内核源码中有USB CDC驱动,路径为:kernel/drivers/usb/class/,"make menuconfig"菜单路径为:Device Drivers —> USB support —> "USB Device class drivers"下的 USB Modem(CDC ACM) support.

Windows 上位机软件说明(C#)

USB设备被枚举为7个串口设备,设备名字一般是"COMx"。如下图所示,USB设备被枚举为从COM20 到 COM26的7个串口设备。大多数情况下,Windows下枚举的名字序号并不与设备实际通道号对应,即下图中的COM20并不代表是设备的第1个串口,上位机软件需要做处理才能知道对应关系。

如下图所示,通过查看串口设备的属性信息,可以知道设备的PID和VID等信息,通过PID和VID作筛选,得到同一类串口设备。通道号是"MI_xx",xx的值分别是:“00, 02, 04, 06, 08, 0a, 0c”,这些值除以2就是硬件实际通道号。

软件筛选设备及获取通道号信息代码如下:

private ArrayList querySerialPorts()
        {
            ArrayList ports = new ArrayList();
            ManagementObjectSearcher s = new ManagementObjectSearcher("select * from Win32_PnPEntity where Name like '%(COM%'");
            foreach (ManagementObject service in s.Get())
            {
                string serviceString = service.ToString();
                if (serviceString.Contains("VID_1A86&PID_FE0C"))
                {
                    int index = serviceString.IndexOf("MI_");
                    if (index == 0)
                        continue;
                    else
                        index += "MI_".Length;
                    string channelString = service.ToString().Substring(index, 2);
                    int channelNumber = Convert.ToInt32(channelString, 16);
                    channelNumber /= 2;
                    string fullName = service.Properties["Name"].Value.ToString(); //获取名称
                    int p = fullName.IndexOf("(COM");
                    string descript = fullName.Substring(0, p); //截取描述(名称)
                    string COMName = fullName.Substring(p + 1, fullName.Length - p - 2); //截取串口号
                    ports.Add(COMName + "(" + channelNumber + ")");
                    //string manufacturer = service.Properties["Manufacturer"].Value.ToString(); //获取制造商
                    //tbCOMInfo.AppendText(fullName + ", " + descript + ", " + COMName + ", " + channelNumber + ", " + manufacturer + "\r\n");
                }
            }
            return ports;
        }

代码中,变量serviceString的内容: "\DESKTOP-8OVDULB\root\cimv2:Win32_PnPEntity.DeviceID=“USB\VID_1A86&PID_FE0C&MI_00\6&245BBDFA&0&0000”,程序对该字符串进行操作,队列变量"ports"内元素的内容为:“COM26(0)”,即"COM26"这个设备对应着通道0,这样就能与硬件设备的通道号对应上了。该上位机软件完整代码在SDK中提供。

由于硬件线路问题或者中间有USB HUB芯片,串口有可能会掉线然后重新连接上,上位机软件可以通过一些手段来检测到,System.IO.Ports.SerialPort类可以通过变量"IsOpen"来判断,串口open后该变量为true,当串口掉线后(即使重新连上也要重新open)该变量为false。串口掉线时会有InvalidOperationExcption异常产生,发送数据的函数用try-catch语句捕获这个异常,并加以处理即可。参考代码:

public void send(string data)
{
    try
    {
        dtuPort.Write(data);
    }
    catch (InvalidOperationException e)
    {
        System.Console.Out.WriteLine(e.ToString());
    }
}

Linux 枚举脚本参考

在Linux操作系统,串口设备文件都会在/dev目录,例如"/dev/ttyACMx"文件。设备及对应的驱动的映射关系体现在目录上,例如在目录"/sys/bus/usb/drivers/cdc_acm/“下存放USB设备在USB总线上的枚举节点,总线枚举关系是固定的,重启系统或者拔掉USB线再接上,这些节点对应的串口设备及硬件通道号都不会改变,通过这些节点信息可以查找到对应”/dev/"目录下的设备名字,这样就能得到设备名及对应的通道号。

以下shell脚本的功能就是查找设备名,并在/tmp目录下建立软链接:

#!/bin/sh
check_ttyUSB_device()
{
    i=0
    while [ $i -le 6 ];
    do
        if [ -f /tmp/rs485-ch${i} ]; then
            i=$((i+1))
            continue
        fi
        dev_path=${CDC_PATH}$((i*2))/tty
        echo $dev_path
        file_name=`ls ${dev_path} | grep ttyACM | awk '{print $0}'`
        dev_file_name=/dev/${file_name}
        echo ${dev_file_name}
        if [ -e "${dev_file_name}" ]; then
            ln -s ${dev_file_name} /tmp/rs485-ch$i
            echo "dev${i}=/tmp/rs485-ch${i}" >> /tmp/dev_map
            echo "tmp/rs485-ch${i} -> ${dev_file_name}"
        else
            let complete_flag=0
        fi
        i=$((i+1))
    done
}
CDC_PATH=/sys/bus/usb/drivers/cdc_acm/1-1.2:1.
complete_flag=1
# 先清掉再创建
for i in 0 1 2 3 4 5 6;do
    rm /tmp/rs485-ch$i
done
index=0
while [ $index -le 10 ];
do
    let complete_flag=1
    check_ttyUSB_device
    if [ $complete_flag = 1 ]; then
        break
    fi
    index=$((index+1))
    sleep 1
done
chmod a+rw /tmp/dev_map
echo "complete!"

FAQ

  1. USB串口设备不稳定,容易掉线?

一般都是USB HUB芯片导致,USB转串口芯片本身很稳定。上层软件可以应对这种异常情况,例如前面提到的C#下System.IO.Ports.SerialPort类可以通过变量"IsOpen"来判断。无论是Windows还是Linux下send数据时都会返回错误值,重新再open串口即可。

  1. 与CH340系列芯片的区别

CH340系列芯片需要安装专有的驱动,本产品操作系统内置驱动。CH340只有一通道,本产品有多个通道(共享1个USB带宽)。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号