BMS通信CAN底层配置
CAN底层配置
什么是CAN通信?
一种局域网通信方式
时间触发通信
中断使能和清除
CAN-FD帧
过滤器
工作模式:睡眠模式、初始化模式、正常工作模式
波特率: BaudRate
中断:发送中断、FIFO0中断、FIFO1中断、错误和状态改变中断。
总结:一种无主从关系的总线型通信方式。通过硬件实现仲裁和检错。
配置要素(需要配置哪些东西)?
* CAN的APB时钟配置
* GPIO口配置
* CAN参数配置\过滤器配置
can_gpio_config
/*GPIO配置*/
void can_gpio_config(void)
{
/* enable CAN clock */
rcu_periph_clock_enable(RCU_CAN0);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_AF);
/* configure CAN0 GPIO */
gpio_init(GPIOD, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
gpio_pin_remap_config(GPIO_CAN0_FULL_REMAP, ENABLE);
}
can_config
void can_config(void)
{
can_parameter_struct can_parameter;
can_filter_parameter_struct can_filter;
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/* initialize CAN register */
can_deinit(CAN0);
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* configure CAN0 baud rate 1MBps, sample point at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 9U;
/* initialize CAN */
can_init(CAN0, &can_parameter);
/* initialize filter */
/* configure filter mode */
can_filter.filter_mode = CAN_FILTERMODE_MASK;
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
/* configure filter ID */
can_filter.filter_list_high = 0x0000U;
can_filter.filter_list_low = 0x0000U;
/* configure filter mask */
can_filter.filter_mask_high = 0x0000U;
can_filter.filter_mask_low = 0x0000U;
/* select receiver fifo */
can_filter.filter_fifo_number = CAN_FIFO0;
can_filter.filter_number = 0U;
can_filter.filter_enable = ENABLE;
can_filter_init(CAN0, &can_filter);
#if defined(GD32E51X_HD)
/* configure CAN0 NVIC */
nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 0U, 0U);
#else
/* configure CAN0 NVIC */
nvic_irq_enable(CAN0_RX0_IRQn, 0U, 0U);
#endif /* GD32E51X_HD */
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
}
如何进行接受与发送?
* can_message_transmit
* can_transmit_states
* can_message_receive
* 发送状态切换:empty -> pending -> scheduled(超过1个邮箱需要发送) -> transmit -> empty
* 发送流程:
1. 选择一个空闲发送邮箱
2. 配置4个发送寄存器(CAN_TMIx,CAN_TMPx,CAN_TMDATA0x和CAN_TMDATA1x)
3. 将 CAN_TMIx 寄存器的 TEN 置 1
4. 检测发送状态和错误信息。典型情况是检测到 MTF 和 MTFNERR 置 1,说明数据被成功发送。
* 数据接收步骤
1. 查看FIFO中帧的数量
2. 通过 CAN_RFIFOMIx , CAN_RFIFOMPx , CAN_RFIFOMDATA0x 和 CAN_RFIFOMDATA1x 读取数据。
3. :将寄存器 CAN_RFIFOx 的 RFD 置 1 释放邮箱,并且等待其由硬件自动清 0。
* 2个深度为3的接收FIFO
28个标识符过滤器
14个独立标识符过滤器
使用中断方式接收
- 中断使能
// configure CAN0 NVIC
nvic_irq_enable(CAN1_RX0_IRQn,1,2);
// enable can receive FIFO0 not empty interrupt
can_interrupt_enable(CAN1, CAN_INT_RFNE0);
- 中断处理函数编写
void CAN1_RX0_IRQHandler(void)
{
/* check the receive message */
can_message_receive(CAN1, CAN_FIFO0, &receive_message);
CAN1_Receice_Analysis(&receive_message);
}
===============================================================================================
问题记录
-
理论知识获取:
FDCAN配置与普通CAN的区别?
STM32配置FDCAN过程- 设置FDCAN时钟为:LL_RCC_FDCAN_CLKSOURCE_HSE
- GPIO初始化
-
调试工具
CAN通信必须外部配备两个120Ω的终端电阻,才可向外通信。调试内部通信可使用回环模式。
状态寄存器、 接收FIFO0寄存器、 接收FIFO1寄存器、 错误寄存器、 接收FIFO邮箱标识符寄存器、接收FIFO邮箱data0寄存器(调试注意) -
宏的打开与关闭:由于项目属于国产替代化项目,存在多处的宏开关。
-
配置到一半时发现芯片为GD32E513,而FDCAN支持的芯片为GD32E518X系列(影响:开始看的FDCAN都无效)
调试过程发现无通信数据发出!!!!
可能原因:
原因1:底层配置不对。断点查看发送数据是否到CAN端口
原因2:硬件连接问题。示波器查看GPIO出口数据(示波器查看GPIO口无任何数据发出)
* 事后分析:观察到CAN1寄存器中值已经放入TMDATA0,但是GPIO无电平变化。应着重思考CAN0的数据到GPIO处的问题,例如复用时钟是否开启。GPIO配置是否正常(根据手册看GPIOB寄存器)。
问题发现点:发现CAN1的ERR寄存器报故障0x05问题。在示波器上看到未上电时为低,上电后出现先高一下,然后常低的问题,打断点分析电平变化的位置,最终找到了Debug.c处重新配置了GPIO。
底层配置不对
通过寄存器观察到:错误寄存器报0x05(位显性错误)
配置结束后(开启复用时钟后),发现err不报故障发送寄存器有数据,但端口无数据,CAN分析仪无数据接收。
can_init返回值不对(0x08015564)
且有些断点无法达到(keil的BUG),让我一度怀疑是条件编译原因导致!!。
发送问题解决后出现:无法接收数据,回环模式下接收FIFO都不能接到数据
配置为回环模式发现


配置回环后

问题定位:看到文章中的回环模式发送规则,寻找寄存器可收到GPIO口未发出问题点。
去查看Datasheet的引脚复用,发现PB12与PB13为CAN1寄存器。而配置的时钟等都是CAN0。
(原意想确认PB12与13是否支持CAN功能)
根因分析:1. 上拉输入、推挽输出、上拉输出等的外部GPIO电平显示为什么?
2. 其他数据初始化时配置了PB13引脚,导致被持续拉低
从CAN0配置到CAN1后,回环模式下,接收寄存器无法收到发送寄存器值,但发送寄存器正常,且CAN_TX抓到通信数据。
1.过滤器配置导致
2.接收中断服务函数未写
3.接收函数不对
4.如果未配置过滤器或者过滤器未使能则不接受任何数据
GD芯片逆天大坑出现!!!
:使用CAN1时,必须开启CAN0时钟.
由于CAN0与CAN1共用过滤器,且CAN1过滤器默认15.
电池发送过程中偶发性上报BMS内部故障
该故障发生条件:BMS通过CAN上传错误标志,软件解析后变量转换进行上报
现象:使用真电池基本上1~2个小时出现一次,是否有变稳定这个还不清除。
思路:这种长时间偶发性问题,感觉是通信干扰导致。其他人给的意见是软件内部赋值可能错误导致。
解决方法:1.通过示波器抓取CAN接收器解析后数据,对比与MCU进入端口是否一致。
经验:示波器打到500ms进行抓取,示波器存在失真现象,导致波形对比不正确形成误判。

通过置起GPIO口减小分辨率,示波器调整为触发抓取故障时刻。
措施:软件增加变量通过Modbus显示。
1. 置起故障时的GPIO标志
2,保存故障时刻的CAN解析帧
3. 保存故障时刻的CAN错误计数器值
-
原因:通过抓取电池包发送数据帧以及CAN通信数据处理数据帧对比发现。
![img]()
数据存在规律性赋值错误问题。
首先可以排查硬件、物理层、干扰等因素,问题主要出现在逻辑层。主要原因为:出现问题的数据帧不是错误数据,而是规律性的半帧赋值。
半帧赋值:当访问过程中FIFO正好接收到外部数据。 -
解决方案:
由于轮询方式调用can_message_receive,出现FiFO为空状态下依旧访问的问题,导致错误赋值。解决代码:
if (can_receive_message_length_get(CAN1, CAN_FIFO0) == 0){
return STATUS_TRUE;
}读取前访问FIFO数据量,如果为空则直接退出,避免出现错误访问。


浙公网安备 33010602011771号