cubemx+stm32f407+双Can通信

最近几天在用CUBEMX实现stm32f407zgt6的双can通讯,中间走了一些弯路,记录下来供需要的人参考借鉴,希望可以帮助大家节省开发周期。

准备工作:

一、硬件

使用启明高配版开发板,因为启明的板子上有两个can可以使用,在调试之前,需要先将can1_H连接can2_H,can1_L连接can2_L,并且需要将P15和P21跳线帽连接好。

二、软件工具

1.我使用的软件版本是CUBEMX4.27,使用的库为fw_f4_v1210。

 

2.keil版本

程序编写

 

can在网上有很多介绍,可以在网上搜索一些基础介绍,之前调试can主要是卡在了新的库包里对滤波器以及FIFO和回调函数的设置上出现一些问题。

一、cubemx设置

1.Pinout部分

使能RCC,CAN1,CAN2以及开发板的PE3,PE4,PG9,SYS可以选择SW模式。点亮灯主要是想在调试的时候使用方便

2.Clock Configuration,建议将系统时钟设置为168

3.configuration设置

can1设置,波特率设置为500并勾选RX0中断

can2设置和can1相同

NVIC部分

点击生成代码

建议勾选下图中选项,生成的代码各部分会更清晰

因为使用的是MDK5,所以我勾选图中选项

完成配置后生成代码

二、代码编写

点开工程目录中的MDK-ARM文件夹中的MDK工程

用cubemx生成的代码是基础配置代码,里面一些具体的服务函数和配置仍需要我们添加,主要有以下几个部分

can.c部分。

 

 

添加接收和发送函数句柄

在can的初始化函数中添加对滤波器的配置,SlaveStartFilterBank为从过滤器配置,用来选择从过滤器的寄存器编号。当选择双can模式时,这个参数要跟can2的FilterBank一致。

以下是can1的滤波器配置

以下是can2的配置,HAL_CAN_ConfigFilter的第一个参数可以是can1也可以是can2

接下来编写两个发送函数CAN_TRANSMIT1和CAN_TRANSMIT2

以下是CAN_TRANSMIT1函数

以下是CAN_TRANSMIT2,因为我想实现的是can2接收的数据在发回给can1,所以我将can2接收的数据在赋值给can1

 

书写回调函数,因为我将can1和can2都绑定在FIFO0上,所以只写了一个回调函数(也可以将can1绑定FIFO0,can2绑定FIFO1,写两个回调函数)

can.h部分

主要是声明几个结构体和两个函数

 

 

main.c部分,调用传递函数即可

 

到此,配置完成,下载到开发板中即可实现can之间的通信,实验成功的现象是led1和led2灯亮起

 

 

 

 

 

 

 

 

 

 

 

对于在STM32F407上使用CAN通信接收多包数据,你可以使用STM32CubeMX来配置CAN控制器,并编写代码来处理接收的数据。以下是一些步骤和示例代码,帮助你实现多包数据接收: 1. 打开STM32CubeMX并创建一个新的工程。 2. 选择你的目标芯片(STM32F407)并配置CAN控制器。在"Peripherals"选项卡中找到CAN,并启用它。 3. 在"Configuration"选项卡中,配置CAN的参数,如波特率、传输模式等。确保启用接收中断和FIFO模式。 4. 生成代码并导出到你的开发环境(如Keil、IAR等)。 接下来,你可以在生成的代码中编写CAN接收的处理逻辑。以下是一个简单的示例代码,用于接收多包数据: ```c #include "stm32f4xx_hal.h" // 定义接收缓冲区大小 #define RX_BUFFER_SIZE 64 // 定义全局变量 CAN_HandleTypeDef hcan; uint8_t rxBuffer[RX_BUFFER_SIZE]; uint32_t rxIndex = 0; void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *hcan) { // 接收到新的CAN帧时调用此回调函数 // 判断是否为第一个包 if (rxIndex == 0) { // 获取数据长度 uint8_t dataLength = hcan->pRxMsg->DLC; // 判断数据长度是否超过缓冲区大小 if (dataLength > RX_BUFFER_SIZE) { // 数据长度超过缓冲区大小,发生溢出错误 // 处理错误逻辑 } } // 将接收到的数据存储到缓冲区 for (uint8_t i = 0; i < hcan->pRxMsg->DLC; i++) { rxBuffer[rxIndex++] = hcan->pRxMsg->Data[i]; } // 判断是否为最后一个包 if (rxIndex >= hcan->pRxMsg->DLC) { // 接收完成,处理接收到的数据 // 处理完后可以重置rxIndex以准备下一次接收 rxIndex = 0; } // 启动下一次接收 HAL_CAN_Receive_IT(hcan, CAN_FIFO0); } int main(void) { // 初始化CAN控制器 HAL_CAN_Init(&hcan); // 配置CAN接收中断 HAL_CAN_Receive_IT(&hcan, CAN_FIFO0); while (1) { // 主循环 // 在这里可以处理其他事情 } } ``` 以上示例代码中,我们定义了一个接收缓冲区rxBuffer和一个索引rxIndex来跟踪接收数据的位置。当接收到新的CAN帧时,会调用HAL_CAN_RxCpltCallback()回调函数。在该回调函数中,我们首先判断是否为第一个包,并获取数据长度。然后将接收到的数据存储到缓冲区中,并判断是否为最后一个包。如果是最后一个包,我们可以在此处理接收到的完整数据,并重置rxIndex以准备下一次接收。最后,我们使用HAL_CAN_Receive_IT()函数启动下一次接收。 请注意,这只是一个简单的示例代码,你可能需要根据你的具体需求进行适当的修改和扩展。 希望这能对你有帮助!如果有任何进一步的问题,请随时提问。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值