USB系列之-一文搞懂CDC虚拟串口COM号变与不变?
前言
可以通过
VID
和
PID
区分不同厂家的
USB
设备,但是同一厂家同一类设备
VID
和
PID
甚至
bcdDevice
等也都是一样的,此时如何区分不同实例呢。 比如常见的
USB
转串口线,可能同时接多个,每个设备都是一模一样的,如何区分呢,此时要用到
iSerialNumber
。
iSerialNumber
不为
0
时,则由
iSerialNumber
区分,不同的值就代表不同的设备实例,
iSerialNumber
为
0
时则
Windows
通过其他方式
(USB
的路径,
HUB
口等
)
等区分。
我们在使用某些
USB
转串口线时
,
可能有疑惑
,
为什么有些换
USB
口
COM
号不会变,有些换
USB
口
COM
号就会变。这一篇我们就通过实测来搞懂,究竟
CDC
虚拟串口的
COM
号什么时候固定,什么时候会自动变。
设备描述符中的
iSerialNumber
以上提到了可以通过设备描述符的
iSerialNumber
区分实例
,
iSerialNumber
为
0x00
则
USB
设备
不使用
序列号
。
iSerialNumber
不为
0x00
则
USB
设备
使用
序列号。
iSerialNumber
字符串索引对应的字符串即序列号字符串
。
如果
使用
序列号,则序列号必须唯一标识同一
类
设备的每个实例
,
即同类设备,不同的个体需要不一样
。
设备描述符的
idVendor
,
idProduct
,
bcdDevice
相同,则
iSerialNumber
必须不同,以便
区分不同设备
。
而使用序列号时,序列号字符串也必须符合为可见有效字符
(0x20~0x7f,
不含
0x2C(
逗号
))
才认为是有效,否则认为无效相当于
iSerialNumber
为
0.
iSerialNumber
== 0
时
此时不使用序列号
,Windows
操作系统会自动根据其他方式区分
(USB
路径,
HUB
口等
)
,自动修改
COM
口。此时可以接多个同样的设备,
COM
号会自动修改,且插入不同的
USB
口时
COM
号不同。
以下进行测试
(
以下是一个双
CDC
设备
),
可以看到
COM
口连续变化,换
USB
口自动变化。
换一个
USB
口则
COM
会自动变
iSerialNumber
!= 0
时
此时使用序列号
,Windows
操作系统以
iSerialNumber
为准区分不同实例,不会自动修改
COM
口。换了
USB
口
COM
号也固定。
此时不可以接多个同样的设备,因为
COM
号会重复。
测试如下
,
可以看到换
USB
口
COM
号不变,且不是连续
:
换
USB
口,依然是
COM22
和
COM25.
如何让
iSerialNumber
!= 0
时也能自动改变
COM
快捷键打开注册表
: win
图标按键
+r
按键
输入
r
egedit
回车
找到表项
[HKEY LOCAL MACHINEISYSTEM\ControlSet001\ControlUsbFlags],
修改如下项目
(
不存在则添加
):
"GlobalDisableSerNumGen"=hex:01
"lgnoreHWSerNum19930101"=hex:01
这里
VID
是
0x1993 PID
是
0x0101
修改之前是如下
测试,此时
iSerialNumber
!= 0
换
USB
口,
COM
口也会自动变化,也支持多个相同设备,
COM
会自动连续变化。效果和
iSerialNumber
=0
一样。
换
USB
口。
总结
注册表修改如下时,就会不管
iSerialNumber
的值,强制认为其相当于
0
不使用设备序列号。
Windows
自动区分同样的设备
(
实际时通过
USB
的路径,
HUB
口等区分
)
。
"GlobalDisableSerNumGen"=hex:01
"lgnoreHWSerNumxxxxyyyy"=hex:01
其中
xxxx
为
16
进制
vid
,
yyyy
为
16
进制
pid
。
所以对于
CDC
如果想要
COM
号不变,则可以设置
iSerialNumber
不为
0
,此时注册表项设置为
"GlobalDisableSerNumGen"=hex:00
。
,但是此时不能接多个同样的实例。
如果既要要求每个实例的
COM
不变,且能区分不同实例,则每个实例的
iSerialNumber
要不一样,可以通过引脚配置,
flash
参数,
efuse
,
otp
等方式初始化时配置。
如果想要
COM
自动变化,可以接多个同样的实例,则可设置
iSerialNumber
为
0
,或者按前面介绍的修改注册表,强制让系统不使用序列号。