2022-12-14
Kvaser | 如何使用Excel发送和接收CAN报文数据
作者:triv 点击:909
从1980年代,Kvaser就开始CAN产品的研发,在相关产品开发领域有近40多年的经验,对CAN和相关总线技术有着非常深入的研究。我们将分享一些有趣的发现和一些特定情况的技术处理,欢迎关注!
所有人的电脑上都有Microsoft Office,平时我们用它列表和计算,除此之外,它还可以被用来进行CAN总线数据收发的工作,进而辅助你进行其他工作。本文就分享如何巧用Excel进行该操作。
我们可以利用Windows电脑上的Microsoft Office Excel进行如下操作:
◾从工作表中的任意单元格向CAN总线发送数据
◾以工作表的任意单元格从CAN总线接收数据
Kvaser CANlib可用于Visual Basic for Applications (VBA)。此多功能库支持Kvaser的所有适配器,并辅助你编写高级和创新的解决方案。
有这么多其他语言可以用,为什么还要使用VBA呢?
首先,如果你平时使用Microsoft Office,那么使用它会更容易。Excel使用广泛,通过VBA,你可应用Excel的所有功能,以及你自己的创意和创新想法。另外,使用Excel不会产生额外成本,也更方便与他人或其他公司分享数据。
本文我们会简要介绍如何在Microsoft Excel中使用CANlib、VBA向CAN总线发送/接收数据。
应用此方法,你需要:
根据本文的步骤,你需要使用Kvaser CANlib和Excel VBA。任意版本的Microsoft Office都可以,但最好是Office 2010,因为VBA 7是在2010年推出的。64位和32位Office均可使用。本文中,使用的是Office 365和Excel(版本2202 Build 16.0.14931.20116)64位。
你还需要安装“用于Windows的Kvaser驱动程序”。请联系广州智维最新版本CANlib并依照其步骤进行安装。如果你需要进一步使用CANlib,我们建议下载Kvaser CANlib SDK。
VBA介绍
VBA(Visual Basic for Applications)是Visual Basic的一种宏语言,是在其桌面应用程序中执行通用的自动化(OLE)任务的编程语言。主要能用来扩展Windows的应用程序功能,特别是Microsoft Office软件。它也可以说是一种应用程式视觉化的 Basic 脚本。
VBA是Microsoft编程语言Visual Basic 6的一个子集,它使用同一编辑器的精简版本以及类似的调试功能。因此,如果你了解VB6,也就能了解VBA的使用方法。Visual Basic是为了简化编程而创建的,VBA编程的过程不难,使用它就类似于用英语的语句来告诉电脑该做什么。
将活动文档另存为 “New Document Name.docx”
需要注意的是,VBA是单线程的,这意味着它将一次执行一个任务。(请参阅下文“VBA示例”中的“多任务处理”内容)
默认情况下,Office不显示“开发工具”选项卡,你必须通过如下步骤启用它:
1️⃣从“File文件”选项卡中,选择“Options选项”打开对话框。
2️⃣选择对话框左侧的“Customize Ribbon自定义功能区”。
3️⃣在对话框左侧的“Choose Commands From从中选择命令”中,选择“Common Commands常用命令”。
4️⃣在右侧的“Customize the ribbon自定义功能区”中,从下拉列表中选择“Main Tab主选项卡”,然后选择“Developer开发工具”复选框。
5️⃣选择OK。
从“开发工具”选项卡,你可以打开编辑器并创建按钮、下拉菜单等。或者,你可以在Office应用程序中使用快捷键:ALT+F11。
如果你还是不了解如何操作,可以在网上进行VBA示例搜索,即使需求不完全相同,你也能从中参考到类似的步骤。
VBA实例
第一个示例将显示当某个单元出现更改时如何作出反应,并将该值发送到CAN总线。
在VBA编辑器中,双击你需要对其作出反应的单元格所在的工作表,然后选择该工作表的“更改(Change)”步骤。
每当该工作表中发生更改时,都会执行工作表更改事件,将其缩小到特定的一个单元格,我使用VBA中的Intersect()函数。此函数确定更改的单元格是否与我们指定的单元格“匹配”。为了简化此示例,我假设工作表处于活动状态,并且我们要发送的值介于0-255之间。有关canWrite中使用的参数,以及如何从CAN总线接收数据的更多信息,请见下一个示例。
在另一个示例中,我已将一个记录文件导入Excel(在此示例中,它是一个.ASC文件)。我这样做只是为了向CAN总线发送数据。
当然,你的数据可以是来自任何地方的,在VBA中打开一个文件,也可以在Excel中编写几个具体应发送的帧等。
在这里,不会深入探讨CANlib,这个示例主要是启发你可以如何利用VBA和CANlib。在本文,我将演示如何使用Kvaser CANlib从Excel中的任意单元格发送数据,以及如何以Excel中的任意单元格接收数据。
编码
CANlib API - 和句柄声明
这些声明是必要的,以便指定哪些dll调用可用,并指出此dll的位置。通过Kvaser的安装程序安装时,CANlib32.dll位于系统路径中。这就是说你不必指定它的具体位置。
[ Public | Private ] Declare Sub name Lib “libname” [ ( [ arglist ] ) ]
[ Public | Private ] Declare Function name Lib “libname” [ ( [ arglist ] ) ] [ As type ]
使用Private表明,只有在声明它的模块中才能访问它。
Kvaser CANlib SDK目前不包含任何VB或VBA声明,因此你必须根据需要编写这些声明。
有任何问题,你可以联系我们的技术支持人员,本文结尾处提供了联系方式。
调用 CANlib API
初始化CANlib并获取可用通道数
在使用任何其他函数之前,必须先调用canInitializeLibrary函数。它将初始化驱动程序。
canGetNumberOfChannels, 此函数将返回电脑中可用CAN通道的数量。虚拟通道包括在此通道数中。
准备工作表以读取一些设备信息
在这里,我们给第一个位置添加一个新的工作表,并在该工作表的单元格B1中写入可用通道数。
读取每个可用通道的一些设备信息
在这里,我们查看每个可用的通道,并询问设备的序列号,并且我们将其写入每个通道的第二列中的新行(即B)。
打开通道,设置参数并启动总线
在这里,我们打开第一个和第二个通道,以获得所有其他调用所需的句柄。我们继续准备这两个打开的通道,为它们设置相同的比特率。
为读取数据准备工作表
这里我们准备一个工作表来存储读取的数据。我首先删除“读取数据(Read data)”表,如果它已经存在。然后我创建此工作表并命名,同时添加一些标题注释,以便更好地理解输出内容。
发送、接收和填充单元格
首先确定要读取的工作表已激活。在我的示例中,我将导入数据的工作表命名为TestLog,并将其设置为ListObject变量。我这样做是为了在获取要发送的值时更容易循环操作,这样我可以使用工作表的标题来指定我正在读取的列。第一个循环设置为读取导入数据的整个范围。我读取数据长度代码(dlc)值,以了解还要读取和稍后发送的字节数。第二个循环迭代数据字节,将它们从文本格式的十六进制转换为十进制值,并将值存储在字节数组中。
然后,通过调用CANlib函数canWrite,将CAN数据的字节数组与报文id(在本例中为行号)和数据长度代码(dlc)一起发送。
DoEvents可以更轻松地停止正在运行的宏。DoEvents函数允许中断执行代码,并允许计算机处理器同时运行其他任务。使用DoEvents会延长执行时间,但另一方面,它也会让宏停止运行。
canReadWait从接收缓冲区读取报文。如果没有可用的报文,则该函数将等待报文到达或超时。
最后,用该读取值填充之前创建的“读取数据”工作表并使用报文id指定单元格行。通过在写入单元格时使用命名工作表,我不必激活该工作表(Worksheets(“Read data”). Cells (Row, Column).Value),同时能保持保存导入数据的工作表处于活动状态。
操作后清理
canBusOff把指定句柄关闭。如果同一通道上没有其他句柄处于活动状态,则也将把此通道关闭。canUnloadLibrary将释放分配的内存,卸载已加载的DLL canlib32.,并取消初始化数据结构。
结果
本示例的结果如下图所示:
如果选择将输出数据格式化为十六进制,这样更便于比较,然后将单元格格式化为文本: ws.Columns(“A:I”).NumberFormat = “@”,当将值放入这些单元格时,需要进行如下转换:Cells(col, row).Value = CStr(Hex(MyDecValue))。
但在本次操作中,为了让后续分析更方便,我选择了十进制。(也可以使用十六进制值,但有时需要进行转换,因为VBA和Excel中的图表对象需要其值为十进制格式。)
可使用Excel图表可视化数据,例如:
图表可以在VBA代码中生成,也可以在以后使用Excel的工具栏生成。
32位与64位Microsoft Office
两个Office版本都可用,但VBA版本7中添加了一些新的64位功能。
VBA中除数据类型Byte外,没有无符号数据类型。但这并不是完全不可行 – 可以在VBA中读取无符号值,例如本例介绍了如何对2147483647以上的值使用双精度类型。
多任务处理
VBA是单线程的,这意味着它将一次执行一个任务。仍然可以创建一个线程或使用回调函数,如CANlib中的kvSetNotifyCallback,但我不建议这样做。如果关闭一个线程并在主线程中等待,则创建一个线程是可以的,但创建更多线程或尝试写入主线程外的单元格,可能会导致Excel冻结并关闭。为了避免麻烦和花费额外时间,建议保持它的简单性和主线程。
对于那些有使用VBA经验的用户,有一些方法可以解决这个问题,例如从代码中的循环中启动一个新的Excel实例,并从该新实例调用主工作簿中的一个过程。
我的建议是保持在主线程里。
结论
在本文中,我们简要介绍了如何在Microsoft Excel中使用CANlib和VBA向CAN总线发送和从CAN总线接收数据。希望此示例可让你了解如何操作可行,并辅助你进一步分析数据或编写解决方案。