littlebot
Published on 2025-04-03 / 0 Visits
0

【源码】基于C++14的CANopen从站库

项目简介

本项目是一个基于C++14编写的CANopen从站库,依据官方的CIA 301 CANopen应用层和通信配置文件文档开发。该库能够根据设备的EDS文件自动生成对象字典的头文件,并且支持对象字典的非易失性存储,拥有多种CANopen协议相关功能。

项目的主要特性和功能

  1. 对象字典生成:可依据设备的EDS文件自动生成对象字典头文件,对象字典为静态分配,其大小在编译时即可确定。
  2. 存储功能:支持对象字典的非易失性存储。
  3. 网络管理:包含可由主站或应用程序控制的NMT从站。
  4. 服务数据对象:具备支持常规和块事务的SDO服务器。
  5. 过程数据对象:支持传输和接收PDO,支持动态PDO映射和RTR。
  6. 心跳和同步:有心跳生产者和触发TPDO传输的同步消费者。
  7. 错误处理:支持带管理错误寄存器和预定义错误字段的紧急生产者。

安装使用步骤

生成对象字典头文件

在编译前,需使用Python脚本生成对象字典头文件,步骤如下: 1. 安装依赖包:进入/generator文件夹,执行pip3 -r requirements.txt。 2. 运行脚本:执行python3 generator.py example.eds 1,其中example.eds是EDS文件路径,1是节点ID。脚本会进行基本验证,成功后会创建od.hpp文件。

实现硬件接口

本库与设备无关,用户需实现库与设备的接口,编写以下类方法的函数定义: - Node::sendFrame:向CAN网络发送帧。 - Node::getTime_us:用于内部计时。 - ObjectDictionnary::saveData:将对象字典数据保存到非易失性存储器。 - ObjectDictionnary::loadData:从非易失性存储器加载对象字典数据。 - ObjectDictionnary::restoreData:将对象字典数据重置为默认值。

使用库

库的使用通过Node对象完成,使用时需注意: 1. 每个程序建议只使用一个Node对象。 2. 库无内置并发保护,需用户自行处理。 3. 节点必须在循环中更新,同时能异步接收消息。

示例代码

以下是一些使用示例: ```cpp // 获取和更改NMT状态 if (node.nmt().getState() == NMTState_PreOperational) { node.nmt().setTransition(NMTServiceCommand_Start); cout << "Entered operationnal state" << endl; }

// 订阅RPDO事件 node.pdo().onTimeout( { cout << "Timeout occured on RPDO" << index << endl; }); node.pdo().onReceive( { cout << "Received RPDO" << index << endl; });

// 发送TPDO node.od()[OD_OBJECT_6048]->setValue(0, (float)49.3); node.od()[OD_OBJECT_6048]->setValue(1, (float)420.42); node.pdo().transmitTPDO(0);

// 发送紧急消息 if(voltage < MIN_VOLTAGE) { node.emcy().raiseError(EMCYErrorCode_Voltage); throw "Error: Voltage too low!"; }

// 清除错误 node.emcy().clearErrorBit(ErrorRegisterBit_Voltage); node.emcy().clearErrorBit(ErrorRegisterBit_Generic); if(node.emcy().getErrorRegister() == 0) { cout << "All errors cleared, clearing history" << endl; node.emcy().clearHistory(); }

// 访问对象字典数据 float value; Object *obj = node.od()[OD_OBJECT_6048]; if (!obj->getValue(0, &value)) throw "Error: Could not read value from entry. Invalid size?"; cout << "Value: " << value << endl; if (!obj->setValue(0, (float)64.23)) throw "Error: Could not write value to entry. Invalid size?"; ```

添加对象

若需添加特殊对象,需按以下步骤操作: 1. 创建Python类:在generator/objects文件夹中创建新的Python类,继承VarObjectArrayObjectRecordObject类。 2. 修改generator.py文件:导入新类,并在toCANopenObject函数中添加相应条件。 3. 创建C++类:在src/objects文件夹中创建object_XXXX.hppobject_XXXX.cpp文件,继承Object类。 4. 包含头文件:在src/od_include.hpp文件中包含新创建的头文件。

下载地址

点击下载 【提取码: 4003】【解压密码: www.makuang.net】