# CAN 通信使用说明 ## 文件说明 1. **ControlCAN.h** - CAN 设备 API 头文件(位于 lib 目录) 2. **ControlCAN.dll** - CAN 设备动态链接库(位于 lib 目录) 3. **ControlCAN.lib** - 导入库(位于 lib 目录) 4. **CANController.h/cpp** - CAN 控制器封装类 5. **can_complete_example.cpp** - 完整使用示例 ## 快速开始 ### 1. 编译项目 使用 g++ 编译(MinGW): ```bash # 编译封装类 g++ -c CANController.cpp -o CANController.o -std=c++11 # 编译完整示例 g++ can_complete_example.cpp CANController.o -o can_demo.exe -Llib -lControlCAN -std=c++11 # 或者使用提供的编译脚本 ./build_can.sh ``` 使用 MSVC 编译: ```bash cl /EHsc /std:c++17 can_complete_example.cpp CANController.cpp /link /LIBPATH:lib ControlCAN.lib ``` ### 2. 运行示例 确保 ControlCAN.dll 在可执行文件同目录或系统路径中: ```bash # 复制 DLL copy lib\ControlCAN.dll . # 运行示例 ./can_demo.exe ``` ## API 使用说明 ### 初始化流程 ```cpp #include "CANController.h" // 1. 创建 CAN 控制器对象 CANController can(VCI_USBCAN2, 0, 0); // 设备类型、设备索引、CAN通道 // 2. 初始化(波特率 500Kbps) if (!can.Initialize(0x00, 0x1C, 0)) { // 初始化失败处理 return -1; } // 3. 发送数据 BYTE data[] = {0x11, 0x22, 0x33, 0x44}; can.SendStandardFrame(0x123, data, 4); // 4. 接收数据 std::vector frames; DWORD count = can.Receive(frames, 100); for (const auto& frame : frames) { // 处理接收到的数据 } // 5. 关闭(析构函数自动调用) can.Close(); ``` ### 常用波特率配置 | 波特率 | Timing0 | Timing1 | 示例代码 | |--------|---------|---------|----------| | 1Mbps | 0x00 | 0x14 | `can.Initialize(0x00, 0x14, 0)` | | 800Kbps| 0x00 | 0x16 | `can.Initialize(0x00, 0x16, 0)` | | 500Kbps| 0x00 | 0x1C | `can.Initialize(0x00, 0x1C, 0)` | | 250Kbps| 0x01 | 0x1C | `can.Initialize(0x01, 0x1C, 0)` | | 125Kbps| 0x03 | 0x1C | `can.Initialize(0x03, 0x1C, 0)` | | 100Kbps| 0x04 | 0x1C | `can.Initialize(0x04, 0x1C, 0)` | ### 工作模式 | 模式值 | 说明 | 应用场景 | |--------|------|----------| | 0 | 正常模式 | 正常的 CAN 通信,可收发 | | 1 | 只听模式 | 总线监控,不影响总线 | | 2 | 自发自收 | 设备测试,环回模式 | ## AGV 控制示例 ### 速度控制 ```cpp // AGV 速度控制函数 void sendAGVVelocity(CANController& can, int16_t left_speed, int16_t right_speed) { BYTE data[8] = {0}; data[0] = 0x10; // 速度控制命令 data[1] = 0x00; data[2] = (left_speed >> 8) & 0xFF; // 左轮速度高字节 data[3] = left_speed & 0xFF; // 左轮速度低字节 data[4] = (right_speed >> 8) & 0xFF; // 右轮速度高字节 data[5] = right_speed & 0xFF; // 右轮速度低字节 data[6] = 0x00; data[7] = 0x00; can.SendStandardFrame(0x200, data, 8); } // 使用示例 sendAGVVelocity(can, 100, 100); // 直行,速度 100 sendAGVVelocity(can, 50, 100); // 左转 sendAGVVelocity(can, 100, 50); // 右转 sendAGVVelocity(can, 0, 0); // 停止 ``` ### 周期性心跳 ```cpp // 在独立线程中发送心跳 std::thread heartbeat_thread([&can]() { int counter = 0; while (running) { BYTE data[8] = {0xAA, 0x00, 0x00, 0x00}; data[1] = (counter >> 8) & 0xFF; data[2] = counter & 0xFF; can.SendStandardFrame(0x100, data, 4); counter++; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }); ``` ### 接收处理(回调方式) ```cpp // 设置接收回调函数 can.SetReceiveCallback([](const VCI_CAN_OBJ& frame) { if (frame.ID == 0x201) { // 电机反馈 int16_t speed = (frame.Data[0] << 8) | frame.Data[1]; std::cout << "电机速度: " << speed << " RPM" << std::endl; } else if (frame.ID == 0x300) { // AGV 状态 uint8_t status = frame.Data[0]; std::cout << "AGV 状态: " << (int)status << std::endl; } }); // 在主循环中接收数据 while (running) { std::vector frames; can.Receive(frames, 100); // 会自动调用回调函数 std::this_thread::sleep_for(std::chrono::milliseconds(10)); } ``` ## 故障排查 ### 常见问题 1. **打开设备失败** - 检查 USB-CAN 设备是否正确连接 - 检查设备驱动是否安装 - 检查设备索引是否正确(从0开始) 2. **初始化失败** - 检查波特率参数是否正确 - 确保设备未被其他程序占用 3. **发送/接收失败** - 检查 CAN 总线是否正常连接 - 检查终端电阻是否正确 - 使用示例3的监控模式检查总线通信 4. **DLL 加载失败** - 确保 ControlCAN.dll 在可执行文件目录 - 或将 dll 路径添加到系统 PATH ## 进阶功能 ### 智能滤波 ```cpp // 设置滤波器(仅接收特定 ID 范围) VCI_FILTER_RECORD filter; filter.ExtFrame = 0; // 标准帧 filter.Start = 0x100; // 起始 ID filter.End = 0x1FF; // 结束 ID // 注意:需要直接调用 VCI_SetReference VCI_SetReference(VCI_USBCAN2, 0, 0, 1, &filter); // 添加滤波规则 VCI_SetReference(VCI_USBCAN2, 0, 0, 2, nullptr); // 启用滤波 ``` ### 多设备支持 ```cpp // 查找所有 USB-CAN 设备 VCI_BOARD_INFO devices[50]; DWORD count = VCI_FindUsbDevice2(devices); std::cout << "找到 " << count << " 个设备:" << std::endl; for (DWORD i = 0; i < count; i++) { std::cout << "设备 " << i << ": " << devices[i].str_Serial_Num << std::endl; } // 打开特定设备 CANController can1(VCI_USBCAN2, 0, 0); // 第一个设备 CANController can2(VCI_USBCAN2, 1, 0); // 第二个设备 ``` ## 参考资料 - ControlCAN 接口函数库使用说明书(docs/protocol/CAN_Protocol.pdf) - can_complete_example.cpp - 完整示例代码 - CANController.h/cpp - 封装类实现 ## 技术支持 如有问题,请参考: - 官方文档:docs/protocol/CAN_Protocol.pdf - 邮箱:zhcxgd@163.com