1. CAN 是什么CANController Area Network是一种面向工业与汽车场景的现场总线使用CAN_H、CAN_L两根差分线通信。它不区分固定的主机和从机总线空闲时每个节点都可以发送消息因此属于多主通信。2. CAN 的核心特点特点说明差分传输抗干扰能力强适合工业现场。多节点一条总线可连接多个 CAN 节点。自动仲裁多节点同时发送时ID 数值越小的消息优先级越高。错误处理支持 CRC、位错误检测和自动重发。速率与距离速率越高可通信距离通常越短。同一 CAN 总线上的所有节点必须配置为相同的通信速率否则会持续报错并影响总线通信。3. CAN 帧基础CAN 协议包含数据帧、遥控帧、错误帧、过载帧和帧间隔。日常开发最常用的是数据帧。经典 CAN 的数据帧可使用标准帧11 位 ID。扩展帧29 位 ID。数据区最多 8 字节。CAN 的 ID 不仅用于标识消息也决定仲裁优先级。它不是传统串口通信中的“设备地址”。4. RT-Thread CAN 设备模型应用程序 ↓ I/O 设备管理接口 ↓ CAN 驱动框架 ↓ 芯片 CAN 驱动 ↓ CAN 控制器与收发器CAN 设备一般命名为can1、can2等。驱动层负责适配配置、控制、发送和接收操作应用层统一使用rt_device_*()接口访问。5. 常用 API接口/命令作用rt_device_find()查找 CAN 设备。rt_device_open()以中断收发模式打开设备。rt_device_write()发送一帧 CAN 消息。rt_device_read()读取一帧 CAN 消息。rt_device_set_rx_indicate()注册接收通知回调。RT_CAN_CMD_SET_BAUD设置通信速率。RT_CAN_CMD_SET_MODE设置工作模式。RT_CAN_CMD_SET_FILTER设置硬件过滤表。6. 初始化并配置 CAN#define CAN_DEV_NAME can1 ​ rt_device_t can_dev; rt_err_t result; ​ can_dev rt_device_find(CAN_DEV_NAME); if (can_dev ! RT_NULL) { result rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX); if (result RT_EOK) { rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN500kBaud); rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_NORMAL); } }代码解析rt_device_find()按名称取得 CAN 设备句柄。打开时同时指定RT_DEVICE_FLAG_INT_RX和RT_DEVICE_FLAG_INT_TX让收发使用中断模式。RT_CAN_CMD_SET_BAUD把速率设置为 500kbit/s必须与总线其他节点一致RT_CAN_MODE_NORMAL表示正常通信模式。示例应继续检查每个rt_device_control()的返回值以便及时发现 BSP 不支持或参数错误。7. 发送一帧 CAN 数据struct rt_can_msg txmsg {0}; ​ txmsg.id 0x78; txmsg.ide RT_CAN_STDID; txmsg.rtr RT_CAN_DTR; txmsg.len 2; txmsg.data[0] 0x11; txmsg.data[1] 0x22; ​ if (rt_device_write(can_dev, 0, txmsg, sizeof(txmsg)) sizeof(txmsg)) { /* 发送请求已成功提交 */ }代码解析rt_can_msg用于描述一帧报文。id 0x78是报文 IDRT_CAN_STDID表示 11 位标准帧RT_CAN_DTR表示数据帧len 2说明只有前两个data字节有效。rt_device_write()的pos对 CAN 无意义传0即可。返回值等于sizeof(txmsg)才表示该帧已成功交给驱动发送。8. 中断接收回调通知线程读取static struct rt_semaphore rx_sem; ​ static rt_err_t can_rx_ind(rt_device_t dev, rt_size_t size) { rt_sem_release(rx_sem); return RT_EOK; } ​ /* 初始化时注册回调 */ rt_sem_init(rx_sem, can_rx, 0, RT_IPC_FLAG_FIFO); rt_device_set_rx_indicate(can_dev, can_rx_ind); ​ /* 在接收线程中读取 */ struct rt_can_msg rxmsg {0}; rxmsg.hdr -1; rt_sem_take(rx_sem, RT_WAITING_FOREVER); rt_device_read(can_dev, 0, rxmsg, sizeof(rxmsg));代码解析CAN 中断到来时驱动调用can_rx_ind()回调只释放信号量避免在中断中进行复杂处理。接收线程被唤醒后再调用rt_device_read()读取完整报文。hdr -1表示从默认接收链表取消息如果设置了指定硬件过滤表号读取时应填写对应的hdr。实际线程中应循环等待、读取并检查返回值。9. 硬件过滤表过滤表让 CAN 控制器只接收关心的报文减少 CPU 处理无关消息。过滤条件通常由以下内容组成id要匹配的报文 ID。ide标准帧或扩展帧。rtr数据帧或遥控帧。maskID 中哪些位必须匹配。过滤配置不正确时可能表现为“总线上有数据但应用收不到”。调试初期可先使用较宽松的过滤规则确认通信后再收紧条件。总结CAN 的优势是高可靠、多节点和基于 ID 的优先级仲裁。RT-Thread 中的基本流程是查找设备 → 打开并配置 → 设置过滤/接收回调 → 收发 CAN 报文 → 关闭设备初学阶段先掌握标准数据帧的收发与中断接收再逐步学习过滤规则和总线错误处理。