概述
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
-
USB串口设备不稳定,容易掉线?
一般都是USB HUB芯片导致,USB转串口芯片本身很稳定。上层软件可以应对这种异常情况,例如前面提到的C#下System.IO.Ports.SerialPort类可以通过变量"IsOpen"来判断。无论是Windows还是Linux下send数据时都会返回错误值,重新再open串口即可。 -
与CH340系列芯片的区别
CH340系列芯片需要安装专有的驱动,本产品操作系统内置驱动。CH340只有一通道,本产品有多个通道(共享1个USB带宽)。
最后是自己USB转多路串口模块的推广_