欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > STM32CubeMX 配置CAN通信 HAL库

STM32CubeMX 配置CAN通信 HAL库

2024/10/25 17:20:38 来源:https://blog.csdn.net/m0_61973119/article/details/141369404  浏览:    关键词:STM32CubeMX 配置CAN通信 HAL库

一、CAN总线波特率计算

CAN总线通信的各节点通信时会产生相位差,所以要进行位同步,两个节点保持步调一致。
CAN_SJW:重新同步跳跃宽度(SJW) 。定义了在每位中可以延长或缩短多少个时间单元的上限。其值可以编程为1到4个时间单元。
CAN_BS1:时间段1(BS1):定义采样点的位置。其值可以编程为1到16个时间单元,但也可以被自动延长,以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。
CAN_BS2:时间段2(BS2):定义发送点的位置。其值可以编程为1到8个时间单元,但也可以被自动缩短以补偿相位的负向漂移。
CAN_Prescaler:直观理解就是分频率。


CAN总线的波特率是取自于总线APB1(PCLK1),通过函数RCC_PCLK1Config给PCLK1配置频率。设置了以上的四个值之后,
CAN总线的波特率=PCLK1/((CAN_SJW +CAN_BS1 + CAN_BS2)*CAN_Prescaler)
假设PCLK1=36MHz、CAN_SJW=1、CAN_BS1=8、CAN_BS2=7、CAN_Prescaler=9
则CAN总线的波特率=PCLK1/((1 + 8 + 7) * 9) = 36MHz / 16 / 9 = 250Kbits

二、查看数据手册(stm32F407ZG),看CAN挂载在哪条总线上面,以及对应的引脚 

三、CAN过滤器介绍

typedef struct
{__IO uint32_t FR1;           //标识符屏蔽位模式中标识符寄存器,配置ID__IO uint32_t FR2;           //标识符屏蔽位模式中屏蔽寄存器
}CAN_FilterRegister_TypeDef;  //标识符列表模式中为2个标识符寄存器,配置ID

例如:屏蔽位寄存器的bit15=1,标识符寄存器的bit15=0,那么接受的Message里面的标识符的bit15必须为0才可能被硬件接受。如果屏蔽位寄存器的bit15=0,Message里面的标识符的bit15无论为什么值,bit15都能匹配通过。

32位屏蔽位模式下:1个过滤器。FR2指定需要关心哪些位,FR1指定这些位的标准值
32位列表模式下:2个过滤器,FR1指定过滤器0的标准值,FR2指定过滤器1的标准值
16位屏蔽位模式下:2个过滤器。FR1高位配置过滤器0标准值,低位配置给过滤器1的标准值。FR2高位配置过滤器0关心的位,低位配置给过滤器1的关心的位。
16位列表模式下:4个过滤器。FR1低位配置过滤器0,高位配置过滤器1。FR2配置过滤器2和过滤器3

IDE=0为标准ID,IDE=1为扩展ID。
RTR=0代表数据帧,RTR=1代表远程帧。
MASKID设置屏蔽码,ID设置标准值。

四、STM32CubeMX配置CAN通信

(1)通过配置分频值和三个时间的比例,可以得出CAN的波特率

(2)针对CAN基本参数设置,具体含义如下

在这里插入图片描述

这些是配置基本参数用的:

  1. 时间触发模式:会自动为报文生成时间戳,没有研究过,暂时默认关闭。
  2. 自动总线关闭管理:没有研究过,暂时默认关闭。
  3. 自动唤醒模式:使能后,当CAN外设在休眠状态时如果CAN总线有数据,则自动唤醒CAN外设。
  4. 自动重发:使能后,如果因为仲裁失败(总线冲突)或是其他原因导致发送失败,会自动重发。建议使能。
  5. 接收FIFO锁定模式:如果使能,当接收FIFO满时,下一条数据会被丢失。如果不使能,则覆盖前面的数据。
  6. 发送FIFO优先级:当发送邮箱中同时有多个帧,是按照先进先出的顺序发送还是按照ID的优先级发送。如果不使能,则按照ID优先级发送。如果使能,则按照先进先出优先级发送。

使能CAN接收中断

(3)CAN几种模式

Advanced Parameters

在这里插入图片描述

这一项主要是用来调试用的,如果只是正常使用,选择 Normal 模式。

  1. 正常模式:CAN外设正常地向CAN总线发送数据并从CAN总线上接收数据。
  2. 回环模式:CAN外设正常向CAN总线发送数据,同时接收自己发送的数据,但不从CAN总线上接收数据。
  3. 静默模式:CAN外设不向CAN总线发送数据,仅从CAN总线上接收数据,但不会应答。一般用于检测CAN总线的流量。
  4. 静默回环模式:CAN外设不会往CAN总线收发数据,仅给自己发送。一般用于自检。

五、使能CAN通信

HAL_CAN_Start(&hcan1);

六、发送数据

写法一:测试时直接发送

CAN_TxHeaderTypeDef can_Tx;
uint8_t sendBuf[5] = {"hello"};
uint32_t box;int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_CAN_Init();HAL_CAN_Start(&hcan1);//使能CAN通信can_Tx.StdId = 0x123;can_Tx.ExtId = 0;can_Tx.IDE = CAN_ID_STD;can_Tx.RTR = CAN_RTR_DATA;can_Tx.DLC = 5;can_Tx.TransmitGlobalTime = DISABLE;while (1){HAL_CAN_AddTxMessage(&hcan1, &can_Tx, sendBuf, &box);HAL_Delay(100);}
}

写法二:测试成功后可以封装成发送函数,下面之所以有while循环等待发送完成是为了避免出现发送5条数据,只能接受到一条数据的情况

uint8_t can1_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{uint16_t t = 0;uint32_t TxMailbox = CAN_TX_MAILBOX0;g_canx_txheader.StdId = id;         /* 标准标识符 */g_canx_txheader.ExtId = id;         /* 扩展标识符(29位) */g_canx_txheader.IDE = CAN_ID_STD;   /* 使用标准帧 */g_canx_txheader.RTR = CAN_RTR_DATA; /* 数据帧 */g_canx_txheader.DLC = len;if (HAL_CAN_AddTxMessage(&hcan1, &g_canx_txheader, msg, &TxMailbox) != HAL_OK) /* 发送消息 */{return 1;}while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3)   /* 等待发送完成,所有邮箱为空 */{t++;if (t > 0xFFF){HAL_CAN_AbortTxRequest(&hcan1, TxMailbox);     /* 超时,直接中止邮箱的发送请求 */return 1;}}return 0;
}

七、配置过滤器接收数据

写法一:直接主函数测试接收是否配置成功

#include <stdio.h>CAN_RxHeaderTypeDef can_Rx;
uint8_t recvBuf[8];int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_CAN_Init();MX_USART1_UART_Init()CAN_FilterTypeDef can_Filter = {0};can_Filter.FilterIdHigh = 0;can_Filter.FilterIdLow = 0;can_Filter.FilterMaskIdHigh = 0;can_Filter.FilterMaskIdLow = 0;can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;can_Filter.FilterBank = 0;can_Filter.FilterMode = CAN_FILTERMODE_IDMASK;can_Filter.FilterScale = CAN_FILTERSCALE_32BIT;can_Filter.FilterActivation = CAN_FILTER_ENABLE;HAL_CAN_ConfigFilter(&hcan1, &can_Filter);HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);HAL_CAN_Start(&hcan1);while (1){}
}void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);}

写法二:让CAN接收更加系统化 

(1) 直接加在CAN1初始化的下面即可,配置过滤器,只有配置了过滤器之后才能接收数据

/* 配置CAN过滤器 */CAN_FilterTypeDef sFilterConfig;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.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */sFilterConfig.SlaveStartFilterBank = 14;				//设置CAN2的起始过滤器组(对于单CAN的CPU或从CAN此参数无效;对于双CAN的CPU此参数为从CAN的起始过滤器组编号)HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);/* 过滤器配置 */

(2) 除开之前在cubemx配置时使能了CAN接收总中断,还需要打开CAN的FIFO消息挂起中断请求(也就是CAN外设的中断使能位)。

HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);

(3)重写CAN接收中断回调函数 

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);/*下面是你用来处理收到数据的代码,可以通过串口把内容发送出来,也可以用来控制某些外设*/
}

八、CAN调试心得

(1)如果使用CAN盒调试CAN通信时,出现发送或者接收数据失败,将CAN配置为静默回环模式,先排除硬件文件,保证软件无误

(2)发送5帧数据只能接收到一帧数据,说明CAN发送较快,发送完一帧数据之后可以等待发送完成在发送下一帧数据,修改CAN配置

(3)如果静默回环模式配置正确,使用CAN盒通信时只能接收错误帧,检查CAN波特率是否正确。有两种可能性,第一种就是CAN的波特率计算错误,第二种就是系统时钟配置错误,倒是CAN时钟不是默认时钟

九、配置两个CAN通信

如果配置两个CAN通信,他们的过滤器配置需要稍作修改

CAN1

/* 配置CAN过滤器 */CAN_FilterTypeDef sFilterConfig;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.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */sFilterConfig.SlaveStartFilterBank = 14;				 设置CAN2的起始过滤器组(对于单CAN的CPU或从CAN此参数无效;对于双CAN的CPU此参数为从CAN的起始过滤器组编号)HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);/* 过滤器配置 */

CAN2 

CAN_FilterTypeDef sFilterConfig;sFilterConfig.FilterBank = 14;                             /* 过滤器14 */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.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */sFilterConfig.SlaveStartFilterBank = 28;				    //无效HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig);/* 过滤器配置 */

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com