基本介绍:
CAN,是ISO国际标准化的串行通信协议。
低速CAN 10~125K 长度达1000M
高速CAN 125K~1M 总线<=40M
CAN总线拓扑图:
多主控制,每一个设备都可以主动发送数据;没有地址的信息,添加设备不改变原来总线的状态;速度块,距离远;错误检测&错误通知&错误恢复功能;判断故障类型,并进行隔离;
使用差分信号进行数据传输,根据CANH、CANL电位差判断总线电平。
CAN(Controller Area Network)通信 是一种广泛应用于汽车、工业控制等领域的高可靠性串行通信协议,具备抗干扰、多主节点、实时性强等特点。以下是CAN通信的全面解析:
一、CAN核心特性
-
多主架构
- 任一节点均可主动发送数据,总线仲裁机制避免冲突。
-
高可靠性
- 差分信号(CAN_H/CAN_L)抗电磁干扰。
- CRC校验 + ACK确认保证数据完整性。
-
实时性
- 非破坏性仲裁(基于标识符ID优先级),高优先级数据优先传输。
-
灵活拓扑
- 支持总线型、星型等多种拓扑,最大节点数可达110个(理论值)。
二、CAN协议帧结构
1. 数据帧
| SOF | ID(11/29位) | RTR | IDE | DLC | Data(0-8字节) | CRC | ACK | EOF |
- SOF:帧起始(1 bit)。
- ID:标识符(标准帧11位,扩展帧29位)。
- DLC:数据长度码(0~8字节)。
- Data:有效载荷。
2. 远程帧
用于请求其他节点发送数据(无数据字段)。
3. 错误帧与过载帧
用于错误通知和流量控制。
三、CAN通信实现步骤(以STM32为例)
1. 硬件连接
- CAN收发器(如TJA1050)连接MCU与总线:
STM32 CAN_TX → 收发器TXD STM32 CAN_RX ← 收发器RXD 收发器CAN_H → 总线CAN_H 收发器CAN_L → 总线CAN_L
- 终端电阻:总线两端需接120Ω电阻(抑制信号反射)。
2. 初始化CAN控制器
// 启用CAN时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
// 配置GPIO(CAN_TX: PA12, CAN_RX: PA11)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置CAN工作模式与波特率
CAN_InitTypeDef CAN_InitStruct;
CAN_InitStruct.CAN_TTCM = DISABLE; // 关闭时间触发模式
CAN_InitStruct.CAN_ABOM = ENABLE; // 自动离线恢复
CAN_InitStruct.CAN_Prescaler = 4; // 分频系数
CAN_InitStruct.CAN_SJW = CAN_SJW_1tq; // 同步跳转宽度
CAN_InitStruct.CAN_BS1 = CAN_BS1_9tq; // 时间段1长度
CAN_InitStruct.CAN_BS2 = CAN_BS2_4tq; // 时间段2长度
CAN_InitStruct.CAN_Mode = CAN_Mode_Normal; // 正常模式
CAN_Init(CAN1, &CAN_InitStruct);
3. 配置过滤器(接收特定ID数据)
CAN_FilterInitTypeDef CAN_FilterInitStruct;
CAN_FilterInitStruct.CAN_FilterNumber = 0; // 过滤器编号
CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask; // 标识符掩码模式
CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_32bit; // 32位过滤
CAN_FilterInitStruct.CAN_FilterIdHigh = 0x123 << 5; // 标准ID高16位(左对齐)
CAN_FilterInitStruct.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xFFF << 5; // 掩码匹配所有扩展ID
CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_FIFO0; // 数据存入FIFO0
CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStruct);
4. 发送数据
CanTxMsg TxMessage;
TxMessage.StdId = 0x123; // 标准ID
TxMessage.ExtId = 0x00; // 扩展ID(标准帧时为0)
TxMessage.IDE = CAN_Id_Standard; // 标准帧
TxMessage.RTR = CAN_RTR_Data; // 数据帧
TxMessage.DLC = 8; // 数据长度8字节
TxMessage.Data = 0xAA; // 数据内容
// ...填充Data~Data
// 发送数据
uint8_t mailbox;
mailbox = CAN_Transmit(CAN1, &TxMessage);
while (CAN_TransmitStatus(CAN1, mailbox) != CANTXOK); // 等待发送完成
5. 接收数据(中断方式)
// 启用CAN接收中断
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
// 中断处理函数
void CAN1_RX0_IRQHandler(void) {
if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET) {
CanRxMsg RxMessage;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
// 处理接收到的数据(例如解析ID和Data)
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
}
}
四、CAN波特率计算
- 公式:
波特率 = APB1时钟 / (Prescaler × (BS1 + BS2 + 1))
- 示例(APB1=36MHz,目标波特率=500kbps):
Prescaler = 36MHz / (500k × (9 + 4 + 1)) = 36,000,000 / (500,000 × 14) ≈ 5.14 → 取Prescaler=5 实际波特率 = 36MHz / (5 × 14) = 514,285 bps(误差可接受)
五、常见问题与调试
1. 无法发送或接收数据
- 检查硬件:确认收发器供电、CAN_H/CAN_L接线、终端电阻。
- 验证波特率:确保所有节点波特率一致。
- 逻辑分析仪:抓取总线信号,观察波形是否正常。
2. 总线错误频繁
- 终端电阻:总线两端必须接120Ω电阻。
- 电磁干扰:使用屏蔽双绞线,避免与强电线路平行走线。
3. 数据丢失或冲突
- ID分配:确保高优先级数据使用更小的ID值。
- 总线负载:控制发送频率(建议负载率<70%)。
六、CAN高层协议
-
CANopen
- 工业自动化标准协议,定义对象字典、PDO/SDO通信方式。
-
J1939
- 汽车领域协议,用于商用车(如卡车、工程机械)的参数传输。
-
DeviceNet
- 基于CAN的设备级网络,适用于工业控制。
七、典型应用场景
领域 | 应用 |
---|---|
汽车电子 | 发动机控制、车身网络(ECU间通信) |
工业自动化 | PLC控制、传感器网络 |
医疗设备 | 监护仪、手术机器人内部通信 |
航空航天 | 飞行控制系统、机载设备通信 |
通过掌握CAN通信的核心原理与实现方法,开发者能够构建高可靠、实时的分布式嵌入式系统,满足复杂环境下的通信需求。