【STM32 CAN通信实战指南】从原理到代码,手把手教你玩转CAN总线

[摘要]
CAN(Controller Area Network)是广泛应用于工业控制、汽车电子等领域的可靠通信协议。本文基于STM32F1系列微控制器,深入解析CAN总线原理,并提供完整的配置代码和实验流程,帮助开发者快速掌握CAN通信核心技术。


一、CAN总线基础原理

1.1 CAN协议核心特点

  • 多主结构:总线上所有节点地位平等,均可主动发送数据

  • 非破坏性仲裁:通过ID优先级解决总线冲突

  • 高可靠性:CRC校验、错误检测与自动重发机制

  • 双线差分信号:CAN_H和CAN_L组成抗干扰传输线

1.2 CAN帧格式(标准帧)

字段长度说明
SOF1 bit帧起始
ID(11位)11 bits报文标识符
RTR1 bit远程传输请求标志
IDE1 bit标识符扩展位(0=标准帧)
r01 bit保留位
DLC4 bits数据长度码(0-8字节)
Data Field0-8字节数据内容
CRC15 bits循环冗余校验码
ACK2 bits应答
EOF7 bits帧结束

1.3 STM32 CAN控制器(bxCAN)

  • 支持CAN 2.0A/B协议

  • 3个发送邮箱

  • 2个接收FIFO,每个FIFO 3级深度

  • 可配置位时间参数

  • 28个过滤器组(STM32F103)


二、硬件设计

2.1 典型电路连接

STM32 CAN_TX --> TJA1050 TXD
STM32 CAN_RX <-- TJA1050 RXD
TJA1050 CAN_H -- 120Ω -- CAN_H
TJA1050 CAN_L -- 120Ω -- CAN_L

2.2 关键参数计算

波特率计算公式
波特率 = APB1时钟 / (Prescaler * (BS1 + BS2 + 1))
例如:APB1=36MHz,目标波特率500kbps
设置Prescaler=6, BS1=5, BS2=3
实际波特率 = 36MHz / (6*(5+3+1)) = 500kbps


三、软件配置(基于STM32CubeMX+HAL库)

3.1 CubeMX配置步骤

  1. 选择CAN模式:NormalLoopback(自测试)

  2. 配置参数:

    • Prescaler: 分频系数

    • Time Quantum: 1/(APB1时钟/Prescaler)

    • BS1: 时间段1(5-20 Tq)

    • BS2: 时间段2(1-16 Tq)

  3. 启用CAN中断(可选)

3.2 过滤器配置

CAN_FilterTypeDef filter;

filter.FilterBank = 0;
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
filter.FilterIdHigh = 0x123 << 5;  // 标准ID左移5位
filter.FilterMaskIdHigh = 0x7FF <<5;
filter.FilterFIFOAssignment = CAN_RX_FIFO0;
filter.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &filter);

四、代码实现

4.1 CAN初始化

void MX_CAN_Init(void)
{
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 6;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_5TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = ENABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  
  HAL_CAN_Init(&hcan);
}

4.2 发送数据

void CAN_SendMessage(uint32_t id, uint8_t* data, uint8_t len)
{
  CAN_TxHeaderTypeDef txHeader;
  uint32_t txMailbox;
  
  txHeader.StdId = id;
  txHeader.RTR = CAN_RTR_DATA;
  txHeader.IDE = CAN_ID_STD;
  txHeader.DLC = len;
  txHeader.TransmitGlobalTime = DISABLE;
  
  if(HAL_CAN_AddTxMessage(&hcan, &txHeader, data, &txMailbox) != HAL_OK)
  {
    Error_Handler();
  }
}

4.3 接收数据(中断方式)

// 启动CAN接收
HAL_CAN_Start(&hcan);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);

// 接收回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  CAN_RxHeaderTypeDef rxHeader;
  uint8_t rxData[8];
  
  HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxData);
  
  printf("Received ID: 0x%03X, Data: ", rxHeader.StdId);
  for(int i=0; i<rxHeader.DLC; i++){
    printf("%02X ", rxData[i]);
  }
  printf("\n");
}

五、实验验证

5.1 硬件连接

  • 两个STM32开发板通过CAN收发器连接

  • 终端电阻配置:总线两端各接120Ω电阻

5.2 测试结果

发送端发送:ID=0x123, Data=AA 55 01 02
接收端显示:Received ID: 0x123, Data: AA 55 01 02

六、常见问题排查

  1. 无法进入中断

    • 检查NVIC中断使能

    • 确认过滤器配置正确

    • 验证HAL_CAN_Start()已调用

  2. 波特率不匹配

    • 使用示波器测量实际波特率

    • 重新计算时间参数

  3. 发送失败

    • 检查CAN控制器是否进入Bus-Off状态

    • 使用CAN分析仪监控总线活动


七、扩展应用

  • CANopen协议栈移植

  • 多节点组网通信

  • 汽车诊断协议(ISO-TP)实现

### STM32F1 CAN Communication Configuration Using CubeMX For configuring the CAN peripheral on an STM32F1 series microcontroller such as the STM32F103RCT6 to enable communication, one can utilize ST's graphical tool called STM32CubeMX. This tool simplifies the initialization of peripherals including CAN by generating initialization code that is ready-to-use within a project framework. #### Setting Up CAN with STM32CubeMX To set up CAN communication: - Launch STM32CubeMX. - Select or create a new project targeting the specific STM32 device model being used. - In the Pinout & Configuration tab, locate and configure the CAN module settings according to application requirements; this includes setting bit timing parameters like baud rate which are critical for proper operation over the bus[^1]. After completing these steps in STM32CubeMX, generate the initialization source files (C/C++) along with any necessary header files. These will include calls to HAL library functions responsible for initializing the hardware abstraction layer associated with CAN operations. #### Example Code Snippet Demonstrating Basic CAN Message Transmission Below demonstrates how messages might be sent via CAN once properly configured through CubeMX: ```c #include "main.h" #include "stm32f1xx_hal.h" CAN_HandleTypeDef hcan; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_CAN_Init(void); int main(void){ /* Reset of all peripherals, Initializes the Flash interface and Systick */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_CAN_Init(); while(1){ // Insert your transmission logic here uint8_t data[] = {0x01, 0x02}; CanTxMsgTypeDef TxMessage; TxMessage.StdId = 0x321; TxMessage.IDE = CAN_ID_STD; TxMessage.RTR = CAN_RTR_DATA; TxMessage.DLC = sizeof(data)/sizeof(uint8_t); memcpy(TxMessage.Data, data, sizeof(data)); if(HAL_CAN_AddTxMessage(&hcan, &TxMessage, NULL) != HAL_OK){ Error_Handler(__FILE__, __LINE__); } HAL_Delay(1000); // Delay between transmissions } } // Initialization function generated from CubeMX setup process static void MX_CAN_Init(void){ hcan.Instance = CAN1; hcan.Init.Prescaler = 9; hcan.Init.Mode = CAN_MODE_NORMAL; hcan.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan.Init.TimeSeg1 = CAN_BS1_13TQ; hcan.Init.TimeSeg2 = CAN_BS2_2TQ; hcan.Init.TimeTriggeredMode = DISABLE; hcan.Init.AutoBusOff = DISABLE; hcan.Init.AutoWakeUp = DISABLE; hcan.Init.GatewayOff = DISABLE; hcan.Init.TxFP = DISABLE; if (HAL_CAN_Init(&hcan) != HAL_OK){ Error_Handler(__FILE__, __LINE__); } } ``` This snippet shows basic message preparation before sending it out onto the network using `HAL_CAN_AddTxMessage()`. The actual implementation details may vary depending upon whether interrupts should handle events asynchronously instead of polling inside loops. --related questions-- 1. How does changing CAN bit-timing affect performance? 2. What role do filters play when receiving frames on the CAN bus? 3. Are there alternative methods besides CubeMX for configuring CAN interfaces on STM32 devices? 4. Could you provide examples demonstrating reception rather than just transmission over CAN? 5. Is it possible to implement more complex protocols atop raw CAN messaging?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值