STM32CubeMX CAN收发数据

目录

一、CAN总线

1. 差分信号

2. CAN收发器

3. CAN帧结构

4. CAN波特率设置

5. 标识符筛选

二、CubeMX配置

三、Keil代码


一、CAN总线

CAN(Controller Area Network,控制器局域网络)是一种用于车辆、工业自动化等领域的通信协议,由德国BOSCH公司开发。CAN总线通过两条差分信号线(CAN-H和CAN-L)进行数据传输,具有较强的抗干扰能力和高效的通信性能。

1. 差分信号

CAN总线的通信是通过CAN-H和CAN-L两条信号线之间的电位差来实现的。总线电平分为两种逻辑状态:

  • 显性电平:表示逻辑“0”,此时CAN-H电压约为3.5V,CAN-L电压约为1.5V。
  • 隐性电平:表示逻辑“1”,此时CAN-H和CAN-L电压均为约2.5V,差分电压近似为零。
2. CAN收发器

在本实验中,使用了SN65HVD230作为CAN收发器,其主要作用是将微控制器的TTL电平转换为CAN总线电平。CAN收发器的主要引脚包括:

  • D(发送):连接到微控制器的CAN_TX引脚。
  • R(接收):连接到微控制器的CAN_RX引脚。
  • CAN-H 和 CAN-L:连接到CAN总线。
3. CAN帧结构

CAN通信的帧结构主要分为以下几种类型:

  • 数据帧:携带实际数据的帧,由7个域组成,包括帧开始、仲裁域、控制域、数据域、CRC域、ACK域和帧结束。
  • 远程帧:用于请求发送具有相同识别符的数据帧。
  • 错误帧:当检测到总线错误时发送的帧,由错误标志和错误界定组成。
  • 过载帧:用于延迟下一帧的发送,通常在接收器还未准备好时发送。
4. CAN波特率设置

CAN波特率设置涉及到多个参数,包括同步段(SYNC_SEG)、位段1(BS1)、位段2(BS2)和同步跳转宽度(SJW)。波特率的计算公式为:

例如,在系统时钟为72MHz,APB1时钟为36MHz,Prescaler为9,BS1为4,BS2为3,SJW为1的情况下,CAN波特率计算如下:

5. 标识符筛选

在CAN通信中,接收节点根据帧的标识符(ID)来判断是否接收该帧。通过设置过滤器,接收器可以选择性地接收所需的数据帧,而忽略无关的帧。

二、CubeMX配置

确保cubemx最新版本,cubemx无法更新,退出使用管理员权限

打开调试

选择高速时钟

配置时钟树

配置LED引脚PD5

 配置CAN

接收中断配置

打开串口4 和 PD5LED 

生成工程

三、Keil代码

1.can发送数据

main.c

uint8_t TxData[8] = {0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x10};

自定义发送函数 

// 发送 CAN 消息函数
void CAN_SendMessage(uint32_t id, uint8_t *data, uint8_t len) {
    CAN_TxHeaderTypeDef TxHeader;  // 定义 CAN 发送头
    uint32_t TxMailbox;  // 邮箱标识

    TxHeader.DLC = len;                 // 数据长度,最大 8 字节
    TxHeader.StdId = id;                // 标准标识符
    TxHeader.IDE = CAN_ID_STD;          // 使用标准 ID
    TxHeader.RTR = CAN_RTR_DATA;        // 数据帧
    TxHeader.TransmitGlobalTime = DISABLE;  // 关闭全局时间戳

    // 发送 CAN 消息,使用 HAL 库提供的函数
    if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, data, &TxMailbox) != HAL_OK) {
        // 如果发送失败,调用错误处理函数
        Error_Handler();
    }
}

while循环中


		CAN_SendMessage(0x02,TxData,8);
		HAL_Delay(1000);
		CAN_SendMessage(0x01,TxData,8);

can.c中配置过滤器启动CAN外设和中断 并在CAN初始化调用函数

void CAN_Config(void)
{	
 
	CAN_FilterTypeDef  sFilterConfig;
 
  /*配置CAN过滤器*/
  sFilterConfig.FilterBank = 0;                     //过滤器0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;              //32位ID
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;          //32位MASK
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器0关联到FIFO0
  sFilterConfig.FilterActivation = ENABLE;          //激活滤波器0
  sFilterConfig.SlaveStartFilterBank = 14;
	
	
 if(HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)//初始化过滤器
 {
  Error_Handler();
 }
 if(HAL_CAN_Start(&hcan) != HAL_OK)//打开can
 {
  Error_Handler();
 }
 if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//开启接受邮邮箱0挂起中断
 {
  Error_Handler();
 }
 
}

Can分析仪显示数据

 2.中断接收数据函数

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
    CAN_RxHeaderTypeDef RxHeader;  // CAN 接收头
    uint8_t RxData[8];  // 数据缓存,最大 8 字节

    // 获取接收到的消息
    if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK) {
        // 如果接收失败,直接返回(避免执行后续无效操作)
        Error_Handler();
        return;
    }

    // 发送接收到的数据通过 UART
    if (HAL_UART_Transmit(&huart4, RxData, RxHeader.DLC, 0xFFFF) != HAL_OK) {
        // UART 传输失败的错误处理
        Error_Handler();
    }

    // 切换 GPIO 引脚状态,控制 LED 状态改变(指示接收到消息)
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_5);
}

发送

接收

 

例程: 

链接: https://pan.baidu.com/s/1s4_dWpP1but54HLcP7herg?pwd=sahk 提取码: sahk 

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chem4111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值