CAN总线支持

CAN(控制器区域网络)总线是一种无需中央总线控制器的微控制器和其他设备之间的通信标准。它最初是为汽车行业设计的,但它在其他领域的采用也越来越广泛。

概述

Squish 6.7及以后版本允许测试运行应用的设备发送和接收的CAN消息。为了方便这一点,测试设置必须包含一个连接到与测试系统相同CAN总线的带有支持CAN硬件的PC,并已安装相应的驱动程序包。

{}

Squish CAN总线测试设置图

设备厂商驱动器名称与...使用
通用socketcan使用标准SocketCAN接口的设备。仅在Linux上可用。
SYS TEC电子systeccan使用SYS TEC CAN接口的设备。仅在Windows上可用。
PEAK-Systempeakcan使用PEAK CAN接口的设备。
MHS电子tinycan使用MHS CAN接口的设备。
Vector Informatikvectorcan使用Vector CAN接口的设备。仅在Windows上可用。

CAN总线类型仅在用创建的应用程序上下文中可用

ApplicationContext startCAN(options)

ApplicationContext startCAN(options, host)

ApplicationContext startCAN(options, host, port)

ApplicationContext startCAN(options, host, port, timeoutSecs)

创建、激活并返回一个新的应用程序上下文,该上下文提供与CAN总线相关的类型和实用工具。在上下文活动期间,所有对CAN对象的访问都必须完成。

第一个参数是一个字典,允许为新的上下文指定更多的选项。目前唯一支持的关键字是schema。如果提供,相关值应为有效的CAN帧模式

可选地,作为第二个和第三个参数,可以指定一个host和一个port。如果使用这些参数,而不是连接到默认的主机(如squishide的设置中指定或在squishrunner的命令行上指定)和端口号,将创建到指定主机和指定端口号的squishserver的连接。

第四个参数,timeoutSecs(整数秒数)也可以指定。这告诉Squish在抛出错误之前应该等待上下文初始化多长时间。如果指定,此值会覆盖squishrunner的默认超时。如果没有指定,除非更改过,否则使用squishserver的默认20秒。

如果您想指定超时,但不更改主机或端口,您可以通过将主机参数作为空字符串传递(这将使Squish使用配置的主机——默认情况下为localhost)和将端口参数作为-1传递来实现。

CanBusDeviceInfo类

CanBusDeviceInfo.deviceName

设备名称。

CanBusDeviceInfo.hasFlexibleDataRate

一个布尔值,表示设备是否支持灵活的数据速率。

CanBusDeviceInfo.isVirtual

一个布尔值,表示设备是否是虚拟的。

CanBusDevice类

CanBusDevice类是Squish CAN总线支持的核心。它表示对特定CAN设备的连接。

CanBusDevice CanBusDevice(driver, device)

此构造函数使用指定的driverdevice打开到CAN硬件的连接。

List CanBusDevice.pluginNames()

此静态方法返回当前平台上支持的驱动程序名称列表。

List CanBusDevice.availableDevices(driver)

此静态方法使用指定的driver枚举可用设备,并返回CanBusDeviceInfo类对象列表。

CanBusFrame CanBusDevice.readFrame(timeout)

此方法等待接收新CAN帧,并返回一个CanBusFrame对象。如果在指定的timeout内没有接收到帧,则抛出异常。

List CanBusDevice.readAllFrames()

返回累积在CAN设备输入缓冲区中的所有帧,作为一个包含CanBusFrame对象的列表。

CanBusDevice.writeFrame(frame)

计划将frame发送到CAN总线。该帧将尽可能快地发送,但是在此方法返回后可能需要一段时间。

CanBusDevice.disconnectDevice()

暂时断开与设备的连接。在此调用之后到达的所有帧将不会添加到内部队列,并且无法使用CanBusFrame CanBusDevice.readFrame(timeout)List CanBusDevice.readAllFrames()方法获取。

CanBusDevice.connectDevice()

通过使用CanBusDevice.disconnectDevice()方法之前挂起的CanBusDevice.disconnectDevice()方法重新连接到设备。

CanBusFrame类

CanBusFrame对象表示单个CAN帧。

CanBusFrame.frameId

帧的ID。

CanBusFrame.isValid

一个布尔值,指定帧是否有效。

CanBusFrame.frameType

帧的类型。

CanBusFrame.hexPayload

作为十六进制字符串的帧的有效负载。

CanBusFrame.extendedFrameFormat

一个布尔值,指示帧是否使用扩展29位帧ID。

CanBusFrame.bitrateSwitch

一个布尔值,指示帧是否使用支持该功能的CAN硬件上的更高比特率进行传输。

CanBusFrame CanBusFrame()

此构造函数创建一个新的无效帧。

CanBusFrame CanBusFrame(frameId)

CanBusFrame CanBusFrame(frameId, payload)

这些构造函数创建一个新的帧,并指定ID。可选地,可以指定十六进制字符串形式的帧数据负载。

String CanBusFrame.toString()()

此方法返回关于帧的可读描述,包括帧ID和二进制有效负载。

CanBusFrameRepeater类

CanBusFrameRepeater对象会以可配置的间隔重复地将指定的帧发送到CAN总线。它可以用来模拟发送帧的CAN设备。

CanBusFrameRepeater.device

用于向总线发送帧的CanBusDevice类对象。此属性不能修改。

CanBusFrame.interval

CAN帧发送到总线的间隔时间(毫秒)。默认间隔为500毫秒。

CanBusFrame.enabled

一个布尔值,指示重发器是否应向总线发送其帧。它可以用来暂时暂停其操作。

CanBusFrameRepeater CanBusFrameRepeater(device)

CanBusFrameRepeater CanBusFrameRepeater(device, frame)

这些构造函数创建一个新的指定设备的帧重复器。可选地,可以指定要发送的帧。

CanBusFrameReceiver类

CanBusFrameReceiver对象接收传入的CAN帧,并保存接收到的帧的历史记录。可以配置接收到的最大帧数。

一旦为CanBusDevice类对象创建了一个接收器,就不能使用CanBusFrame CanBusDevice.readFrame(timeout)List CanBusDevice.readAllFrames()方法获取帧。创建后,接收器将接管管理传入帧的任务。

CanBusFrameReceiver.device

用于接收帧的CanBusDevice类对象。此属性不能修改。

CanBusFrameReceiver CanBusFrameReceiver(device)

为指定的CanBusDevice类创建一个新的CanBusFrameReceiver实例。

CanBusFrameReceiver CanBusFrameReceiver(driver, device)

为指定的driverdevice名称创建一个新的CanBusDevice类对象和一个该设备的新的CanBusFrameReceiver实例。

CanBusFrameReceiver.setHistorySize(frameId, length)

将指定帧ID的历史记录长度更改为指定的值。

Integer CanBusFrameReceiver.frameCount(frameId)

返回接收器中当前累积的指定ID的帧数。

CanBusFrame CanBusFrameReceiver.latestFrame(frameId)

检索指定ID的最新捕获帧。

CanBusFrame CanBusFrameReceiver.pastFrame(frameId, index)

从接收器中检索一个累计的过往帧。索引必须在 [0, frameCount()) 范围内,其中 0 是最近接收到的帧。

CanBusFrame CanBusFrameReceiver.pastFrames(frameId)

检索接收器中所有累计的过往帧。

CanBusFrameReceiver.clearHistory(frameId)

清除接收器中累计的指定ID的帧。

CanBusFrameReceiver.waitForFrame(filter, timeout)

等待匹配指定过滤器的帧并返回它。参数 filter 必须是一个字典,包含 frameId 字段。另外,对于已知的帧类型,字典可以包含帧字段的预期值。如果直到超时仍没有匹配的帧到达,将抛出异常。

timeout 参数以毫秒指定。超时是可选的,默认值为 30 秒。

为了避免并发问题,首先考虑接收器中已经累计的帧。这可能会导致错误地找到一个过往帧,为了防止需要使用 CanBusFrameReceiver.clearHistory(frameId) 方法清除接收器缓冲区。

CAN帧架构

CAN帧负载的内容没有标准化。因为这样,Squish无法提供有关负载缓冲区内容的任何见解,除其十六进制表示外。由于通过这种方式访问负载成员非常不便,所以 ApplicationContext startCAN(options) 可以接受一个方案,该方案基于帧ID定义帧负载的内容。

CAN方案是一个具有 canschema 根元素和 version="1" 属性的 XML 文件。帧内容在 frames 元素中定义。每个帧类型作为 frame 元素定义。每个 frame 元素必须具有 idname 属性,分别包含数字帧ID和帧类型的名称。每个 frame 应包含一个定义帧中已知字段的 fields 元素。每个 field 元素定义一个字段。该 field 元素的属性可以是

  • name — 字段的名称。此属性是必需的;
  • type — 字段类型。目前支持的类型有 integralfloating。此字段的默认值为 integral
  • signed — 一个布尔值,表示整数类型是否带符号。此字段的默认值为 false。对于除 integral 之外的字段类型,忽略此属性。
  • size — 字段的大小(位)。整数字段可以指定介于 1 和 64 之间的任何大小。浮点字段可以是32位或64位长。此字段的默认值为 32

对于架构中的每个帧类型,Squish 将创建一个指定名称和 Frame 后缀的 CanBusFrame 类的子类。帧类将数据作为帧对象的属性定义。此外,提供了静态字段称为 frameId,以便于访问。

以下文件演示了一个示例 CAN 架构

<canschema version="1">
  <frames>
    <frame id="0x100" name="Thermometer">
      <fields>
        <field name="temperature" type="floating" size="32"/>
      </fields>
    </frame>
    <frame id="0x200" name="AirConditioning">
      <fields>
        <field name="targetTemp" type="integral" size="32"/>
        <field name="cooler" type="integral" size="1"/>
        <field name="heater" type="integral" size="1"/>
      </fields>
    </frame>
  </frames>
</canschema>

使用上述架构,可以按以下方式访问为帧类型定义的字段

var th = new ThermometerFrame();
th.temperature = 10.1;
test.log( th.hexPayload ); // Logs "4121999a"

test.log( AirConditioningFrame.frameId ); // Logs "512"
var ac = new AirConditioningFrame({targetTemp: 10, cooler: 0, heater: 1});
test.log( ac.targetTemp ); // Logs "10"
th = ThermometerFrame();
th.temperature = 10.1;
test.log( th.hexPayload ); # Logs "4121999a"

test.log( AirConditioningFrame.frameId ); # Logs "512"
ac = AirConditioningFrame({"targetTemp": 10, "cooler": 0, "heater": 1});
test.log( ac.targetTemp ); # Logs "10"
my $th = Squish::ThermometerFrame->new();
$th->temperature = 10.1;
test::log( $th->hexPayload ); # Logs "4121999a"

test::log( Squish::AirConditioningFrame->frameId ); # Logs "512"
my %args = ( targetTemp => 10, cooler => 0, heater => 1);
my $ac = Squish::AirConditioningFrame->new(%args);
test::log( $ac->targetTemp ); # Logs "10"
th = ThermometerFrame.new();
th.temperature = 10.1;
Test.log( th.hexPayload ); # Logs "4121999a"

Test.log( AirConditioningFrame.frameId ); # Logs "512"
ac = AirConditioningFrame.new(( "targetTemp" => 10, "cooler" => 0, "heater" => 1));
Test.log( ac.targetTemp ); # Logs "10"
set th [ThermometerFrame new]
ThermometerFrame set th temperature 10.1
test log [ThermometerFrame get hexPayload $th] # Logs "4121999a"

test log [AirConditioningFrame get frameId] # Logs "512"
set ac [ AirConditioningFrame new (targetTemp, 10, cooler, 0, heater, 1) ]
test log [ AirConditioningFrame get targetTemp $ac ] # Logs "10"

©2024 Qt公司有限公司。在此包含的文档贡献是各自所有者的版权。
提供的文档是根据自由软件基金会发布的GNU自由文档许可协议第1.3版许可证的条款提供的。
Qt及其标志是芬兰以及全球其他国家的Qt公司的商标。所有其他商标均为各自所有者的财产。