This commit is contained in:
CaiXiang
2025-11-14 16:09:58 +08:00
commit af65c2425d
74 changed files with 14650 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
/**
* CAN API 快速参考
* 基于 ControlCAN 接口函数库
*/
// ============================================
// 1. 基本数据结构
// ============================================
// CAN 帧结构
typedef struct {
UINT ID; // CAN ID
UINT TimeStamp; // 时间戳0.1ms
BYTE TimeFlag; // 时间标志
BYTE SendType; // 0=正常发送, 1=单次发送
BYTE RemoteFlag; // 0=数据帧, 1=远程帧
BYTE ExternFlag; // 0=标准帧(11位), 1=扩展帧(29位)
BYTE DataLen; // 数据长度(0-8)
BYTE Data[8]; // 数据
} VCI_CAN_OBJ;
// 初始化配置
typedef struct {
DWORD AccCode; // 验收码
DWORD AccMask; // 屏蔽码0xFFFFFFFF=接收所有)
DWORD Reserved;
BYTE Filter; // 滤波方式1=所有类型)
BYTE Timing0; // 波特率 T0
BYTE Timing1; // 波特率 T1
BYTE Mode; // 0=正常, 1=只听, 2=自发自收
} VCI_INIT_CONFIG;
// 设备信息
typedef struct {
USHORT hw_Version; // 硬件版本
USHORT fw_Version; // 固件版本
BYTE can_Num; // CAN 通道数
CHAR str_Serial_Num[20]; // 序列号
} VCI_BOARD_INFO;
// ============================================
// 2. 核心 API 函数
// ============================================
// 打开设备
DWORD VCI_OpenDevice(DWORD DevType, DWORD DevIndex, DWORD Reserved);
// 参数DevType=4(USBCAN2), DevIndex=设备索引(0,1,2...)
// 返回1=成功, 0=失败, -1=设备不存在
// 关闭设备
DWORD VCI_CloseDevice(DWORD DevType, DWORD DevIndex);
// 初始化 CAN
DWORD VCI_InitCAN(DWORD DevType, DWORD DevIndex, DWORD CANIndex,
PVCI_INIT_CONFIG pInitConfig);
// 参数CANIndex=CAN通道(0=CAN0, 1=CAN1)
// 启动 CAN
DWORD VCI_StartCAN(DWORD DevType, DWORD DevIndex, DWORD CANIndex);
// 复位 CAN
DWORD VCI_ResetCAN(DWORD DevType, DWORD DevIndex, DWORD CANIndex);
// 发送数据
DWORD VCI_Transmit(DWORD DevType, DWORD DevIndex, DWORD CANIndex,
PVCI_CAN_OBJ pSend, DWORD Len);
// 返回:实际发送的帧数
// 接收数据
DWORD VCI_Receive(DWORD DevType, DWORD DevIndex, DWORD CANIndex,
PVCI_CAN_OBJ pReceive, DWORD Len, INT WaitTime);
// 返回:实际接收的帧数
// 获取接收数量
DWORD VCI_GetReceiveNum(DWORD DevType, DWORD DevIndex, DWORD CANIndex);
// 清空缓冲区
DWORD VCI_ClearBuffer(DWORD DevType, DWORD DevIndex, DWORD CANIndex);
// 读取设备信息
DWORD VCI_ReadBoardInfo(DWORD DevType, DWORD DevIndex, PVCI_BOARD_INFO pInfo);
// ============================================
// 3. 常用波特率配置
// ============================================
// 波特率 Timing0 Timing1
// 1000 Kbps 0x00 0x14
// 800 Kbps 0x00 0x16
// 500 Kbps 0x00 0x1C // 推荐
// 250 Kbps 0x01 0x1C
// 125 Kbps 0x03 0x1C
// 100 Kbps 0x04 0x1C
// ============================================
// 4. 完整使用流程
// ============================================
void CAN_Example() {
// 步骤1打开设备
if (VCI_OpenDevice(VCI_USBCAN2, 0, 0) != 1) {
printf("打开设备失败\n");
return;
}
// 步骤2配置并初始化
VCI_INIT_CONFIG config;
config.AccCode = 0x00000000;
config.AccMask = 0xFFFFFFFF; // 接收所有
config.Filter = 1;
config.Timing0 = 0x00; // 500Kbps
config.Timing1 = 0x1C;
config.Mode = 0; // 正常模式
if (VCI_InitCAN(VCI_USBCAN2, 0, 0, &config) != 1) {
printf("初始化失败\n");
VCI_CloseDevice(VCI_USBCAN2, 0);
return;
}
// 步骤3启动 CAN
if (VCI_StartCAN(VCI_USBCAN2, 0, 0) != 1) {
printf("启动失败\n");
VCI_CloseDevice(VCI_USBCAN2, 0);
return;
}
// 步骤4清空缓冲区
VCI_ClearBuffer(VCI_USBCAN2, 0, 0);
// 步骤5发送数据
VCI_CAN_OBJ send_frame;
memset(&send_frame, 0, sizeof(VCI_CAN_OBJ));
send_frame.ID = 0x123;
send_frame.SendType = 0;
send_frame.RemoteFlag = 0;
send_frame.ExternFlag = 0; // 标准帧
send_frame.DataLen = 8;
send_frame.Data[0] = 0x11;
send_frame.Data[1] = 0x22;
// ...
DWORD ret = VCI_Transmit(VCI_USBCAN2, 0, 0, &send_frame, 1);
printf("发送 %d 帧\n", ret);
// 步骤6接收数据
VCI_CAN_OBJ recv_frames[100];
ret = VCI_Receive(VCI_USBCAN2, 0, 0, recv_frames, 100, 0);
printf("接收 %d 帧\n", ret);
for (DWORD i = 0; i < ret; i++) {
printf("ID=0x%03X, 数据=[", recv_frames[i].ID);
for (int j = 0; j < recv_frames[i].DataLen; j++) {
printf("%02X ", recv_frames[i].Data[j]);
}
printf("]\n");
}
// 步骤7关闭设备
VCI_CloseDevice(VCI_USBCAN2, 0);
}
// ============================================
// 5. 常见应用场景
// ============================================
// 场景1发送标准帧
void Send_StandardFrame(UINT id, BYTE* data, BYTE len) {
VCI_CAN_OBJ frame = {0};
frame.ID = id;
frame.SendType = 0;
frame.RemoteFlag = 0;
frame.ExternFlag = 0; // 标准帧
frame.DataLen = len;
memcpy(frame.Data, data, len);
VCI_Transmit(VCI_USBCAN2, 0, 0, &frame, 1);
}
// 场景2发送扩展帧
void Send_ExtendedFrame(UINT id, BYTE* data, BYTE len) {
VCI_CAN_OBJ frame = {0};
frame.ID = id;
frame.SendType = 0;
frame.RemoteFlag = 0;
frame.ExternFlag = 1; // 扩展帧
frame.DataLen = len;
memcpy(frame.Data, data, len);
VCI_Transmit(VCI_USBCAN2, 0, 0, &frame, 1);
}
// 场景3循环接收
void Receive_Loop() {
VCI_CAN_OBJ frames[2500];
while (running) {
DWORD count = VCI_Receive(VCI_USBCAN2, 0, 0, frames, 2500, 0);
if (count > 0) {
// 处理接收到的数据
for (DWORD i = 0; i < count; i++) {
Process_Frame(&frames[i]);
}
}
Sleep(10); // 10ms 间隔
}
}
// 场景4AGV 速度控制
void AGV_SetVelocity(int16_t left_rpm, int16_t right_rpm) {
BYTE data[8] = {0};
data[0] = 0x10; // 速度命令
data[1] = 0x00;
data[2] = (left_rpm >> 8) & 0xFF; // 左轮高字节
data[3] = left_rpm & 0xFF; // 左轮低字节
data[4] = (right_rpm >> 8) & 0xFF; // 右轮高字节
data[5] = right_rpm & 0xFF; // 右轮低字节
Send_StandardFrame(0x200, data, 8);
}
// ============================================
// 6. 错误处理
// ============================================
// 检查返回值
DWORD ret = VCI_OpenDevice(VCI_USBCAN2, 0, 0);
if (ret == 0) {
printf("操作失败\n");
} else if (ret == (DWORD)-1) {
printf("设备不存在或 USB 掉线\n");
} else {
printf("操作成功\n");
}
// ============================================
// 7. 注意事项
// ============================================
/*
1. 一个设备只能打开一次
2. 发送帧数建议每次 1 帧,提高效率
3. 接收缓冲区建议 2500 帧
4. 多节点通信时 SendType 必须为 0
5. 扩展帧 ID 为 29 位,标准帧为 11 位
6. 数据长度最大 8 字节
7. 波特率配置要与总线其他设备一致
8. 使用完毕后记得关闭设备
*/