2023-03-01
如何在虚拟CAN设备上设置虚拟通道和总线
作者:triv 点击:514
之前我们分享过《如何仅需一台电脑搞定CAN理论、实践与测试》,里面有提到设置虚拟通道,构建虚拟设备可以帮助我们更好地理解、实践CAN总线。本文将详细介绍如何安装、修改和使用Kvaser Driver驱动生成虚拟设备(无需CAN设备硬件)。
本篇文章将介绍虚拟设备,虚拟通道和虚拟总线。需要注意的是,本文主要关注的是WINDOWS驱动,但也有提到有关LINUX系统的内容(见本文末尾附录A)。
我们将介绍怎样安装,修改和使用虚拟设备:
虚拟设备模拟一个Kvaser CAN适配器
虚拟通道模拟一个Kvaser CAN通道
虚拟总线提供一个虚拟导线连接到虚拟通道上

安装相关软件
下载和安装下列软件:
⚫️Kvaser CAN设备驱动程序(v5.22版本或更高的版本)
⚫️Kvaser CANlib软件开发包(Kvaser CANLib SDK,v5.22版本或更高的版本)
硬件设备
本文介绍的内容不需要使用硬件(Kvaser CAN适配器)。
在Windows上安装Kvaser CAN驱动
在安装CAN驱动的同时, 一个虚拟设备就自动被装上了。

查看已安装设备
使用 “Kvaser Device Guide(产品说明)”查看已安装的设备。

预设置是一个有两个通道的设备,这两个通道借助一个虚拟回路导线(虚拟总线)彼此相连。
一共最多可以添加16个虚拟设备,我们将在下一节介绍这部分内容。
在Windows里加虚拟设备
在我们添加更多虚拟设备之前,我们必须在注册部分修改两个值。
预设值(2018年2月8日) 是 2 个虚拟设备, 请将它改为16个虚拟设备或你需要的任何数量。Windows最多允许16个硬件。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESOFTWAREWOW6432NodeKVASER ABCANDriver
1.0Driverskcanv]
"MaxCards"=dword:00000010
[HKEY_LOCAL_MACHINESOFTWAREKVASER ABCANDriver 1.0Driverskcanv]
"MaxCards"=dword:00000010
注意:数值是16进制的!
拷贝上面的文字到一个文档文件, 将它命名为 “Allow16KvaserVirtualDevices.REG”, 然后双击 “run” 来运行。你也可以用Regedit.EXE来直接修改注册。

点击“Yes”。

点击“OK”, 检查在RegEdit的值:

已完成。
添加虚拟设备
按下 “WinButton + R”,键入“HDWWIZ”并点击OK,启用硬件助手“HardwareWizard”。(在你开始生成另外15 个设备之前, 请阅读后面的“修改通道数量”部分!)

你也可以通过一个命令提示符开始。

点击“Next”。

选择“ Select Manual Install (Advanced)(手动安装)”,然后点击“Next”。

选择 “CAN Hardware (Kvaser)”, 然后点击“Next”。

下拉到“Kvaser Virtual CAN Driver(虚拟CAN驱动)”, 然后点击“Next”。

点击“Next”。

你可以添加16个Kvaser 虚拟 CAN 设备的驱动, 但是如果想再加一个, Windows 会显示下面的信息:

而且在Device Manager框里你会看到:

但本文我们假设16个有两个虚拟总线的虚拟设备就足够了。
检查设置

我们现在应该能看到我们选择安装的设备数量,和CANLib 通道数量。在此例中,一共有16个虚拟设备和32 个虚拟通道。
修改通道数量
你可以修改虚拟设备上的通道数。每个虚拟设备的预设通道数是两个。
要想修改通道数,你需要更改注册里的一个设置,然后重启电脑。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceskcanvParameters]
"ChannelCount"=dword:00000005
在一个虚拟设备上最多可以生成8个虚拟通道。改变通道数值时需要重启电脑。
我现在要生成两个各有5个虚拟通道的虚拟设备,并在下一节里进行测试。

虚拟总线
每个虚拟设备的所有虚拟通道都被预设为连接到一个私用虚拟总线上 (通常为虚拟总线#0)。当我们生成两个有5个通道的设备 , 每个设备的所有5个通道都被连接到虚拟总线#0。然而,这两个虚拟设备之间没有连接,尽管它们被连接到同一个编号的虚拟总线上! 虚拟通道只能与连接在同一个虚拟设备上的其他通道联系。
每个虚拟设备可以生成一套数量为32个的私用虚拟总线。
私用虚拟总线

上面所示例子中有一些错误。通道2(Channel 2)不能和通道5(Channel 5)联系, 通道3不能和通道4联系(通道0可以和通道1联系)。
虚拟适配器不能共享虚拟总线!
用CANLib操作虚拟设备
你可以在CANLib里打开虚拟通道, 同样使用你在操作CAN适配器硬件时使用的命令。唯一不同之处是我们必须加一个旗标FLAG。
MyHnd[ChNo] := canOpenChannel(ChNo, flags OR canOPEN_ACCEPT_VIRTUAL);
在使用命令canOpenChannel()时,我们必须加旗标canOPEN_ACCEPT_VIRTUAL。它不会妨碍你打开普通总线,因此你可以把旗标保留在你的软件里。
每个虚拟设备有32个虚拟总线, 在同一个虚拟设备上,你可以将任何一个虚拟通道跟任何虚拟总线相连接。
将虚拟通道和虚拟总线断开
我们可以用命令canIoCtl()来断开一个通道的连接。
Var
BusNo:INT32;
Begin
BusNo := 0;
canBusOff(MyHnd);
canIoCtl(MyHnd,canIOCTL_DISCONNECT_FROM_VIRTUAL_BUS,@BusNo,4);
End;
这里看上去不需要BusOff() 和 BusOn(), 但是尽管它们是虚拟的,我们仍建议修改它们之前使用它们,这会更好一些。
我们必须知道虚拟总线数量。如果你忘记了总线数量,可以使用下面操作(断开所有连接):
// This routine disconnects the channel from ALL virtual buses!
Var
BusNo:INT32;
Begin
BusNo := 0;
canBusOff(MyHnd);
For BusNo := 0 to 31 do
begin
canIoCtl(MyHnd,canIOCTL_DISCONNECT_FROM_VIRTUAL_BUS, @BusNo,4);
end;
End;
现在,我们可以很确定虚拟通道已和虚拟总线断开。
将虚拟通道和虚拟总线连接
我们可以用命令canIoCtl()来连接一个通道。(总是要先断开通道, 不然有时可能会连接到多个总线。)
Var
BusNo:INT32;
Begin
BusNo := 7;
canIoCtl(MyHnd,canIOCTL_CONNECT_TO_VIRTUAL_BUS,@BusNo, 4);
canBusOn(MyHnd);
End;
现在我们连接到了虚拟总线No 7.
请注意,你必须断开一个通道。当连接到一个‘新’虚拟总线时,通道并没有与‘旧’总线断开。所有连接和断开都是由你的软件发起控制。
举例
(有五个虚拟通道的两个虚拟设备)

让我们建立各有五个通道的两个设备(此处列出的编码不是完整版)。
虚拟设备 0
通道CH0 和 通道CH1可以在 VB1 (虚拟总线 1)上联系。
通道CH2, CH3 和 CH4 可以在VB3 (虚拟总线3) 上联系。
虚拟设备1/b>
通道CH5-CH9 可以在虚拟总线VB1上联系。
但是CH0 和 CH1不能和 CH5-CH9联系。虽然它们似乎在同一个总线上,但它们在不同的虚拟设备上。每个虚拟设备生成一套私用虚拟总线。
附录A
(LINUX)
我能用LINUX操作虚拟设备吗?
是的, 在Linux里你要在源代码上做一个修改(virtualcan.h):
#define NR_CHANNELS 2
#define MAX_CHANNELS NR_CHANNELS
#define NR_VIRTUAL_DEV 1
#define VIRTUAL_MAX_DEV NR_VIRTUAL_DEV
并且以下面的命令打开该设备:
/usr/sbin/virtualcan.sh start