摘要: 本文深入浅出地介绍CAN(Controller Area Network,控制器局域网络)总线协议,涵盖其基础概念、报文帧格式、仲裁机制、错误处理等关键知识。同时,文章结合STM32平台,从硬件设计、软件开发到实战案例,全面讲解CAN总线应用开发,并提供详细的代码示例和注释,帮助读者快速掌握CAN总线技术。
关键词: CAN总线, STM32, 嵌入式系统, 汽车电子, 工业控制, 物联网
一、 项目概述
1.1 项目背景
CAN总线作为一种高可靠性、实时性强的串行通信协议,广泛应用于汽车电子、工业自动化、医疗设备等领域。 掌握CAN总线技术,对于嵌入式工程师和物联网开发者至关重要。
1.2 项目目标
- 深入理解CAN总线协议的原理和特点
- 掌握基于STM32平台的CAN总线应用开发
- 通过实战项目,提升CAN总线应用开发能力
二、 CAN总线基础
2.1 CAN总线简介
CAN总线是一种多主站的串行通信协议,其特点包括:
- 高可靠性: 具有强大的错误检测和纠错机制。
- 实时性: 采用非破坏性总线仲裁技术,保证高优先级报文优先传输。
- 灵活性: 支持多主站通信,易于扩展。
- 成本效益: 硬件结构简单,成本较低。
2.2 CAN 标准与报文帧格式
常见的CAN标准包括CAN 2.0A、CAN 2.0B和CAN FD。 其中,CAN FD (Flexible Data-Rate) 支持更高的数据速率和更长的数据长度。
CAN总线数据以报文帧的形式传输,常见的报文帧格式包括:
- 数据帧 (Data Frame): 用于传输数据。
- 远程帧 (Remote Frame): 请求其他节点发送数据。
- 错误帧 (Error Frame): 节点检测到错误时发送。
- 过载帧 (Overload Frame): 节点需要延迟发送数据时发送。
2.3 仲裁机制与标识符
CAN总线采用基于标识符的非破坏性仲裁机制,保证高优先级报文优先传输。 标识符越小,优先级越高。
2.4 错误检测与处理
CAN总线具有多种错误检测机制,例如CRC校验、位填充等,并支持错误恢复机制,确保通信的可靠性。
三、 系统设计
3.1 硬件设计
本项目基于STM32F103C8T6微控制器和STM32CubeMX进行开发。
- MCU: STM32F103C8T6
- CAN收发器: TJA1050
- CAN连接器: DB9
连接示意图:
3.2 软件设计
- 开发环境: Keil MDK
- HAL库: STM32 HAL库
- 功能模块:
- CAN初始化
- CAN报文发送
- CAN报文接收
- 中断处理
四、 代码实现
4.1 CAN初始化
/* CAN 初始化 */
void CAN_Init(void)
{
/* CAN 时钟使能 */
__HAL_RCC_CAN1_CLK_ENABLE();
/* 初始化 CAN 句柄 */
hcan1.Instance = CAN1;
/* 设置 CAN 工作模式为普通模式 */
hcan1.Init.Mode = CAN_MODE_NORMAL;
/* 设置波特率为 500Kbps */
hcan1.Init.Prescaler = 6;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_13TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
/* 设置自动离线管理模式 */
hcan1.Init.AutoBusOff = ENABLE;
/* 设置自动重传模式 */
hcan1.Init.AutoRetransmission = ENABLE;
/* 设置接收 FIFO 锁定模式 */
hcan1.Init.ReceiveFifoLockedMode = ENABLE;
/* 设置发送 FIFO 优先级模式 */
hcan1.Init.TransmitFifoPriority = ENABLE;
/* 初始化 CAN */
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* 配置 CAN 过滤器 */
CAN_FilterTypeDef can_filter_config;
can_filter_config.FilterBank = 0;
can_filter_config.FilterMode = CAN_FILTERMODE_IDMASK;
can_filter_config.FilterScale = CAN_FILTERSCALE_32BIT;
can_filter_config.FilterIdHigh = 0x0000;
can_filter_config.FilterIdLow = 0x0000;
can_filter_config.FilterMaskIdHigh = 0x0000;
can_filter_config.FilterMaskIdLow = 0x0000;
can_filter_config.FilterFIFOAssignment = CAN_RX_FIFO0;
can_filter_config.FilterActivation = ENABLE;
can_filter_config.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&hcan1, &can_filter_config) != HAL_OK)
{
Error_Handler();
}
/* 启动 CAN */
if (HAL_CAN_Start(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* 开启 CAN 接收中断 */
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
代码说明:
- 首先,启用 CAN1 的时钟。
- 然后,初始化 CAN 句柄
hcan1
,并设置 CAN 的工作模式、波特率、自动离线管理、自动重传、接收 FIFO 锁定模式、发送 FIFO 优先级模式等参数。 - 配置 CAN 过滤器,设置过滤器模式、标识符、掩码等参数。
- 启动 CAN 模块。
- 最后,开启 CAN 接收中断,以便在接收到数据时及时进行处理。
4.2 CAN 报文发送
/* CAN 报文发送 */
void CAN_Send_Msg(uint32_t std_id, uint8_t *data, uint8_t len)
{
CAN_TxHeaderTypeDef tx_header;
uint32_t mailbox;
/* 设置报文 ID */
tx_header.StdId = std_id;
/* 设置报文类型为数据帧 */
tx_header.RTR = CAN_RTR_DATA;
/* 设置数据长度 */
tx_header.DLC = len;
/* 发送 CAN 报文 */
if (HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &mailbox) != HAL_OK)
{
Error_Handler();
}
}
代码说明:
- 首先,定义一个
CAN_TxHeaderTypeDef
类型的变量tx_header
,用于设置 CAN 报文的 ID、类型、数据长度等信息。 - 然后,调用
HAL_CAN_AddTxMessage()
函数将 CAN 报文添加到发送邮箱。其中,hcan1
是 CAN 句柄,tx_header
是报文头信息,data
是要发送的数据,mailbox
是发送邮箱的编号。 - 如果发送成功,
HAL_CAN_AddTxMessage()
函数返回HAL_OK
,否则返回错误码。
4.3 CAN 报文接收
/* CAN 报文接收 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[8];
/* 接收 CAN 报文 */
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK)
{
Error_Handler();
}
/* 处理接收到的数据 */
if (rx_header.StdId == 0x100) // 判断报文 ID
{
// 处理 ID 为 0x100 的报文
}
}
代码说明:
HAL_CAN_RxFifo0MsgPendingCallback()
函数是 CAN 接收中断回调函数,当接收到 CAN 报文时,该函数会被调用。- 首先,定义一个
CAN_RxHeaderTypeDef
类型的变量rx_header
,用于存储接收到的 CAN 报文头信息,以及一个uint8_t
类型的数组rx_data
,用于存储接收到的数据。 - 然后,调用
HAL_CAN_GetRxMessage()
函数从接收 FIFO 中读取 CAN 报文。 - 根据接收到的报文 ID 进行相应处理。
4.4 中断处理
在 STM32CubeMX 中,可以图形化地配置 CAN 中断。 在代码中,需要实现 HAL_CAN_RxFifo0MsgPendingCallback()
函数来处理接收到的 CAN 报文。
五、 项目总结
本项目介绍了 CAN 总线的基本概念、帧格式、仲裁机制和错误处理等关键知识,并结合 STM32 平台,详细讲解了 CAN 总线的硬件设计、软件开发和实战案例。 通过学习本项目,读者可以快速掌握 CAN 总线技术,并将其应用到实际项目中。