10.5 CAN通信项目:双机通信

# 10.5 CAN通信项目:双机通信

本实验通过STM32的CAN总线协议实现双机通信,MCU1(主节点)检测按键动作并发送计数值,MCU2(从节点)接收数据并在OLED实时显示。
核心功能

  • 主节点:按键触发CAN数据帧发送,OLED显示发送次数。
  • 从节点:中断接收数据,OLED实时更新接收值。

# 10.5.1 CAN项目电路设计

# 硬件架构

  • 主节点(MCU1):
    • 按键接口:PC13
    • CAN接口:PA12(TX)/PA11(RX) → TJA1040收发器
  • 从节点(MCU2):
    • OLED接口:PB8(SCL)/PB9(SDA)
    • CAN接口:PA12(TX)/PA11(RX) → TJA1040收发器
  • CAN总线:120Ω终端电阻,屏蔽双绞线连接。
CAN通信电路原理图

# 10.5.2 STM32CubeMX配置

# 1. 基础配置(主/从节点相同)

  1. 工程设置
    • 芯片型号:STM32F103C8T6
    • 主频:72MHz
    • 调试接口:SWD
  2. GPIO配置
    • 按键引脚(PC13):GPIO_Input(无上下拉)
    • CAN引脚(PA11/PA12):CAN_RX/CAN_TX

# 2. CAN参数配置

  • 模式:Normal
  • 波特率预分频:45
  • 位时序
    • TimeSeg1 = 13TQ
    • TimeSeg2 = 2TQ
    • SyncJumpWidth = 1TQ
  • 中断配置:启用CAN接收中断(FIFO0)
CAN中断及接口配置

# 10.5.3 CAN项目软件设计

# 主节点代码(MCU1)

# 1. 初始化配置

// CAN过滤器配置(标准帧,ID=0x123)
CAN_FilterTypeDef filter;
filter.FilterIdHigh = 0x123 << 5;      // 标准帧ID左移5位
filter.FilterMaskIdHigh = 0x7FF << 5;  // 全匹配模式
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
filter.FilterFIFOAssignment = CAN_RX_FIFO0;
HAL_CAN_ConfigFilter(&hcan, &filter);
HAL_CAN_Start(&hcan);  // 启动CAN
1
2
3
4
5
6
7
8
9

# 2. 数据发送逻辑

// 定义发送帧头
CAN_TxHeaderTypeDef TxHeader;
TxHeader.StdId = 0x123;    // 标准帧ID
TxHeader.IDE = CAN_ID_STD; // 标准帧
TxHeader.DLC = 4;          // 数据长度4字节

// 主循环:检测按键并发送数据
while (1) {
  if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
    HAL_Delay(50);  // 消抖
    if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
      keyPressCount++;
      memcpy(txData, &keyPressCount, 4);  // 数据拷贝
      HAL_CAN_AddTxMessage(&hcan, &TxHeader, txData, &TxMailbox); // 发送
    }
  }
  // OLED显示发送次数
  sprintf(message, "TransmitData: %d", keyPressCount);
  OLED_PrintString(0, 20, message, &font16x16, OLED_COLOR_NORMAL);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 从节点代码(MCU2)

# 1. 中断接收配置

// 启用接收中断
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);

// 中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
  if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, rxData) == HAL_OK) {
    if (RxHeader.StdId == 0x123) {
      memcpy(&receivedCount, rxData, 4);  // 解析数据
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

# 2. 数据显示逻辑

// 主循环:更新OLED显示
while (1) {
  sprintf(message, "ReceiveData: %d", receivedCount);
  OLED_PrintString(0, 20, message, &font16x16, OLED_COLOR_NORMAL);
  HAL_Delay(100);
}
1
2
3
4
5
6

# 10.5.4 CAN项目下载验证

# 步骤与现象

  1. 硬件连接
    • CAN_H/CAN_L使用屏蔽双绞线连接主从节点,接入120Ω终端电阻。
  2. 烧录程序
    • 主节点烧录发送程序,从节点烧录接收程序。
  3. 功能验证
    • 按下主节点按键,OLED显示发送次数递增。
    • 从节点OLED实时同步显示接收值。
CAN项目效果图

关键说明

  • CAN总线需严格匹配终端电阻,避免信号反射。
  • 帧标识符(0x123)需在主从节点中一致。
  • 中断接收模式确保数据实时性,消抖逻辑防止误触发。