技术博客

30/09/2015 作者 Troy

设置CANlib:事件驱动

这是CANlib开发3篇系列文章的最后一篇:

CANlib 简介

在我们的上一个视频中,我们演示了如何创建一个控制台应用程序,它可以使用CANlib SDK中提供的基本API调用来配置和读取CAN总线上的报文。 在本视频中,我们将重点介绍如何使循环事件驱动读取更高效。

示例

在前面的示例中,我们使用了Windows C#控制台应用程序。由于我们想在多线程应用程序中显示事件驱动循环,本示例将使用Windows Presentation Foundation程序,其中主线程处理图形用户界面(GUI)以及后台线程从CAN总线读取数据。

我们有一个简单的图形用户界面,一个按钮启动后台线程和一个按钮停止后台线程。我们还添加了一个文本框以显示接收到的报文。我们使用XAML设计了这个GUI。

我们将使用.NET后台工作线程来执行所有的CAN总线操作。这意味着我们必须包括System ComponentModel命名空间,并在创建主窗口时创建后台工作程序。 GUI所要做的就是在按下总线开启按钮时启动后台工作,当按下总线关闭按钮时停止后台工作,并显示后台线程报告的字符串。

我们的后台工作程序将执行ReceiveMessageLoop函数来从CAN总线中检索数据。 像我们前面的例子,我们需要包括canlibCLSNET命名空间和设置Kvaser设备的句柄。我们在InitializeChannel函数中放置了句柄设置指令。 我们初始化库,获取句柄,设置比特率,并使总线上的通道有效。我们还添加了对canIoCtl的调用,以获取一个Windows事件句柄,当驱动程序中发生某些事件时,它将触发。这可能是接收到的报文,报文传输或CAN控制器状态的改变。无论事件触发的原因是什么,你必须清空接收缓冲区,否则不会再获得另一个事件触发器。你会注意到canIoCtl返回的指针必须放在从WaitHandle类派生的类中。要使用WaitHandle类,我们必须包括System.Threading命名空间。

我们现在有一个正确初始化的通道句柄和一个事件句柄,所以回到ReceiveMessageLoop循环,直到GUI请求后台工作程序停止。在循环内,我们使用WaitAny方法等待1秒钟直到事件发生。 如果没有事件发生,我们再次循环。 如果CAN事件触发,我们使用canRead调用循环读取报文,直到该函数指示接收缓冲区为空且具有canERR_NOMSG状态。对于每个报文的消息,我们使用BackgroundWorker类中内置的ReportProgress方法将报文信息传递回GUI。

如果GUI请求后台工作程序停止,我们将退出while循环,进入ReleaseChannel函数,通过使通道处于非活动状态并关闭句柄来执行我们的标准清理。

现在应用程序仍然响应,并且使用较少的CPU资源,因为我们只检查消息以及当CAN事件或用户事件发生时更新显示。请记住,当使用多线程时,canOpenChannel调用返回的句柄不是线程安全的。因此每个线程必须使用canOpenChannel函数声明自己的物理通道句柄。

CANlib更多信息

有关CANlib的更多信息,您可以查看我们的CANlib SDK帮助,并查看我们的技术博客中的系列文章。

Author Image

Troy Via

Troy Via是Kvaser股份有限公司的软件和支持工程师。Troy为Kvaser编写了多个培训视频,是产品开发团队的关键成员。他也代表Kvaser参加NMEA讨论。工作之余,他还是一名狂热的游戏玩家。