LabVIEW Actor学习案例可自行修改添加至项目 1. 封装 can设备类抽象类已实现ZLG的简单封装 2. 使用actor 封装 CAN设备 ISO15765协议UDS传输层 3. 全局使用actor构建 CAN设备层和协议层相互分离不同的类中间使用一个管理类进行消息调度若使用其他设备更换CAN硬件类即可最近在搞汽车电子诊断工具发现LabVIEW Actor框架在处理硬件通信层和协议层解耦时特别顺手。今天咱们就拿实际项目中CAN设备的ISO15765协议封装当案例聊聊怎么用Actor模型玩转设备驱动和协议分离。第一步抽象硬件操作所有硬件驱动的封装都得从抽象类开始。比如咱们先定义一个CAN_Device.lvclass内部用多态方法处理不同厂商设备的差异。举个ZLG设备的具体实现// CAN_Device_ZLG.lvclass 私有数据 - 设备句柄 - 波特率 方法 打开设备(Override) 调用ZLG DLL初始化 关闭设备(Override) 释放资源 发送报文(Override) 转换报文格式调用底层API 接收报文(Override) 轮询或中断方式获取数据这里的关键是抽象类里定义了发送/接收/初始化等必须实现的方法。当需要切换周立功、PEAK等不同硬件时只需要继承这个类重写具体实现上层调用完全不用改。Actor化协议层ISO15765协议最麻烦的是处理多帧报文组装。咱们用Actor模型把协议处理封装成独立对象// ISO15765_Actor.lvclass 消息处理循环 Case 接收原始CAN帧 按FlowControl分片处理 超时检测 重组多帧报文 Case 发送多帧请求 自动拆分帧 处理流控帧 重传机制这里有个骚操作——给Actor配置两个独立队列一个处理外部指令比如诊断请求另一个专门啃底层硬件的实时数据流。实测这样处理3000帧/秒的数据流也不会卡。全局消息调度设备层和协议层的通信全靠CANDeviceManager这个中间商赚差价不是。看看它的消息路由实现// CAN_Device_Manager.vi While循环 从硬件Actor接收报文 - 根据ID分发到对应协议Actor 从协议Actor接收指令 - 转发到对应硬件Actor最妙的是这里用了动态调用Actor的Send Message方法。当需要接入第二路CAN通道时只需要在管理类里加个路由规则已有协议Actor根本不知道硬件层发生了什么变化。代码片段解析看个协议层处理多帧的典型代码// ISO15765处理单帧 if 首帧: 启动超时计时器 回复流控帧 缓存数据 elif 连续帧: 拼装数据 if 数据完整: 触发报文接收事件 重置状态机这里用了LabVIEW的移位寄存器做状态保持比全局变量清爽多了。注意超时处理一定要放在独立定时器线程避免阻塞主消息循环。踩坑实录硬件层队列深度别设太大实测超过200条会引入微妙级延迟Actor销毁时要先清空队列再关闭引用否则容易内存泄漏协议层的时间戳最好由管理类统一打上避免各Actor时钟不同步这种架构改造成本极低上次把周立功卡换成Vector设备只花了半天时间——新写个硬件子类改下管理类的初始化参数协议测试用例都不用动就直接跑通了。Actor模型在解耦方面的优势谁用谁知道。LabVIEW Actor学习案例可自行修改添加至项目 1. 封装 can设备类抽象类已实现ZLG的简单封装 2. 使用actor 封装 CAN设备 ISO15765协议UDS传输层 3. 全局使用actor构建 CAN设备层和协议层相互分离不同的类中间使用一个管理类进行消息调度若使用其他设备更换CAN硬件类即可