STM32---CAN2.0B读取新能源汽车BMS报文

CAN2.0B

CAN的简单概述

CAN-BUS即CAN总线技术,全称为“控制器局域网总线技术(Controller Area Network-BUS)”。Can-Bus总线技术最早被用于飞机、坦克等武器电子系统的通讯联络上。将这种技术用于民用汽车最早起源于欧洲,在汽车上这种总线网络用于车上各种传感器数据的传递。
大家知道当今车辆的电控系统是越来越多,例如电子燃油喷射装置、ABS装置、安全气囊装置、电动门窗、主动悬架等等。同时遍布于车身的各种传感器实时的监测车辆的状态信息,并将此信息发送至相对应的控制单元内。CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。
CAN 协议具有一下特点:
1) 多主控制。 在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元
同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。 ID 并不是
表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始
发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级
最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
2) 系统的柔软性。 与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单
元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
3) 通信速度较快,通信距离远。 最高 1Mbps(距离小于 40M),最远可达 10KM(速率低
于 5Kbps)。
4) 具有错误检测、错误通知和错误恢复功能。 所有单元都可以检测错误(错误检测功能),
检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单
元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新
发送此消息直到成功发送为止(错误恢复功能)。
5) 故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)
还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上
发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
6) 连接节点多。 CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没
有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通
信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。
ISO11898标准 物理层特性如下图(是针对通信速率为125Kbps~1Mbps 的高速通信标准)
物理层特性
注意:终端电阻别丢!由于用CAN_H跟CAN_L的电平差来表示显性位和隐性位,所以整个总线上电压基本为0,也减小了总线上的消耗,这也是汽车要用CAN通信的原因之一。

此次要讲解的是用STM32的CAN2.0B来访问现今新能源汽车上电池内部的BMS(电池管理系统)的CAN报文,根据协议手册来解码信息。

先简单介绍一下STM32的CAN外设
需要详细了解CAN数据帧类型的去问度娘!!!
CAN 协议是通过以下 5 种类型的帧进行的:

  • 数据帧
  • 要控帧
  • 错误帧
  • 过载帧
  • 帧间隔
    我们主要讲解数据帧,下图是数据帧的构成
    数据帧的构成
    (1) 帧起始。表示数据帧开始的段。
    (2) 仲裁段。表示该帧优先级的段。
    (3) 控制段。表示数据的字节数及保留位的段。
    (4) 数据段。数据的内容,一帧可发送 0~8 个字节的数据。
    (5) CRC 段。检查帧的传输错误的段。
    (6) ACK 段。表示确认正常接收的段。
    (7) 帧结束。表示数据帧结束的段。
    标准格式ID为11位,而扩展格式ID为29位。在汽车通信中数据种类的多样化,11位ID是不能够满足需求的。所以汽车CAN通信国标必将引用29位ID扩展格式。(后边将讲解汽车通信协议:国标SAE J1939-21

##STM32四个段和波特率计算
几个概念:
 同步段(SS)
 传播时间段(PTS)
 相位缓冲段 1(PBS1)
 相位缓冲段 2(PBS2)
 Tq:最小时间单元
这几个概念不懂的去百度!!!

STM32 CAN 位时序:
这里写图片描述

我用的STM32F103, 250Kbps(BMS方式250Kbps,只能是这个)。
波特率=36000/[(9+8+1)*8]=250Kbps。

##FIFO邮箱和过滤器的内容,可以去翻STM32中文手册,介绍特别详细!

##ST官方库讲解
寄存器 CAN_TIxR :
这里写图片描述

该寄存器在库中对应的结构体如下

typedef struct
{
  uint32_t StdId;  /*!< Specifies the standard identifier.
                        This parameter can be a value between 0 to 0x7FF. */

  uint32_t ExtId;  /*!< Specifies the extended identifier.
                        This parameter can be a value between 0 to 0x1FFFFFFF. */

  uint8_t IDE;     /*!< Specifies the type of identifier for the message that 
                        will be received. This parameter can be a value of 
                        @ref CAN_identifier_type */

  uint8_t RTR;     /*!< Specifies the type of frame for the received message.
                        This parameter can be a value of 
                        @ref CAN_remote_transmission_request */

  uint8_t DLC;     /*!< Specifies the length of the frame that will be received.
                        This parameter can be a value between 0 to 8 */

  uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to 
                        0xFF. */

  uint8_t FMI;     /*!< Specifies the index of the filter the message stored in 
                        the mailbox passes through. This parameter can be a 
                        value between 0 to 0xFF */
} CanRxMsg;
结构体成员作用
StdId标准标识符或扩展标识符,MSB取决于IDE位的值
ExtId扩展标识符,扩展标识符的LSB
IDE标识符扩展,此位用于定义邮箱中信息的标识符类型。0:标准标识符;1:扩展标识符
RTR远程发送请求 。 0:数据帧;1:遥控帧
TXRQ发送邮箱请求,由软件置1,用于请求发送相应邮箱的内容。邮箱变为空后,此位由硬件清零。

##对STM32的介绍先到这里,下面介绍国标J1939-21
SAE J1939- - SAE 标准
由卡车及客车电子电气委员会所属的卡车及客车控制及通信小组委员会制定,用于公路设备的
控制及通信网络推荐操作规程。
网络拓扑图
这里写图片描述
图上很明确的标明了汽车内部控制器跟BMS(电池管理系统)的连接关系!

##协议数据单元(PDU)格式
这个也就是上边STM32内部CAN外设里边说的那个扩展格式
帧格式图如下:
这里写图片描述
每一帧数据包含了:优先级、数据页、ID、数据。
直接看可能不好理解,我直接举例说明;
ID:0x0C019ED0 用二进制表示为:0 1100 0000 0001 1001 1110 1101 0000(ID位29位)
按照PDU要求的对以上二进制数进行拆分;
|P | R | DP | PF | PS | SA

011 | 0 | 0 | 00000001 | 10011110 | 11010000

3 | 0 | 0 | 1 | 158 | 208 |

以上是对ID的解析,参照PDU格式表,应该很容易理解。
ID后边紧跟着就是8bit数据,数据格式每个厂家都不一样(由于保密原因无法公开数据格式),需要根据厂家提供的解析方式进行解析(无非也就是一个数乘上一个比例,在加上一个偏移0.0)
这一帧数据是BMS发送到CAN总线上的,我们的目的就是为了得到这个ID里边的数据

##下面通过STM32读取PDU里的数据
我们只介绍对报文接收,发送报文道理也是一样的

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)
{
  /* Check the parameters */
  assert_param(IS_CAN_ALL_PERIPH(CANx));
  assert_param(IS_CAN_FIFO(FIFONumber));
  /* 获取ID数值*/
  RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR;
  if (RxMessage->IDE == CAN_Id_Standard)//判断是标准格式,还是扩展格式,并赋值给结构体变量
  {
    RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);
  }
  else
  {
    RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);
		
  }
  //因为BMS里都是扩展帧格式,下面直接判断
  if((RxMessage->ExtId & (uint32_t)0x0000000F)==0x0000000E)//总线上数据帧很多,筛选结尾为E的ID串口打印ID
	{
		printf("ExtId=%08X\r\n",RxMessage->ExtId);
  		RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR;
  		/* 获取DLC数值 */
  		RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR;
  		/* 获取FMI数值 */
  		RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8);
  		/* 获取数据区并赋值给结构体数组,调试时直接打印RxMessage.Data即可*/
  		RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;
  		RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8);
  		RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16);
  		RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);
  		RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;
  		RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8);
  		RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16);
  		RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24);
	}
  /* Release the FIFO */
  /* Release FIFO0 */
  if (FIFONumber == CAN_FIFO0)
  {
    CANx->RF0R |= CAN_RF0R_RFOM0;
  }
  /* Release FIFO1 */
  else /* FIFONumber == CAN_FIFO1 */
  {
    CANx->RF1R |= CAN_RF1R_RFOM1;
  }
}

判断FIFO0是否有数据,接收到数据是返回非零数值,存入u8 buff[8].

//CAN口接收数据
//buf:数据缓冲区,存放8bit数据
//返回值:0,无数据返回;
//		非0,接收数据长度,即为DLC值;
u8 Can_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		//ûÓнÓÊÕµ½Êý¾Ý,Ö±½ÓÍ˳ö 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//¶ÁÈ¡Êý¾Ý	
		
    for(i=0;i<8;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

main函数打印数据区:
(省略一些初始化,数据解析等等一些操作)

	CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,8,0);//CAN普通模式初始化,波特率250kbps
 
 	while(1)
	{
		//printf("XX-21 CAN2BMS test program;\r\n");
		flag=Can_Receive_Msg(canbuf);
		if(flag)//非0即为接收到数据
		{			
			for(i=0;i<key;i++)
			{									    
				printf("%02X ",canbuf[i]);//打印数据
 			}
			printf("\r\n");
		}
	}

##到这里,我们就可以清楚的看到串口给我们打印出来的数据了。
这里写图片描述
注:这个是未筛选前的输出,有的优先级高,输出频率会快一些。

  • 25
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: 新能源汽车BMS(电池管理系统)学习资料包括了BMS的基础知识、设计原理、电池组的选型和布置、控制策略、故障诊断等方面的内容。 BMS新能源汽车的关键部件之一,它能够对电池组进行多方面的保护和管理,确保汽车的驱动性能和安全可靠。BMS的基础知识内容主要包括了BMS的定义和功能、BMS电池管理策略、电池组的构成和特性等。 设计原理方面,BMS的设计需要考虑到多种因素,如电池的充放电过程、温度、电压、电流等参数,以及汽车的运行模式、充电方式等。因此,BMS的设计需要结合多种技术手段,如传感器、控制电路、通讯协议等。 电池组的选型和布置方面,需要根据车型和性能需求来选择合适的电池,同时考虑电池的安全性、重量、成本等因素,布置也需要严格按照规范进行,确保电池组的稳定性和可维护性。 控制策略方面,BMS需要实现多种控制策略,如充电控制、放电控制、温度控制等。故障诊断方面,BMS需要实现对电池组和BMS本身的故障诊断和报警功能,确保在发生异常情况时能够及时采取措施。 总之,新能源汽车BMS学习资料涵盖了多种知识点,需要全面掌握并不断实践和提高技术水平,以确保新能源汽车的性能和安全可靠。 ### 回答2: BMS(电池管理系统)是新能源汽车电池能量管理的重要组成部分,负责监测电池状态、实时控制配电和限制充电和放电速度等。作为新一代汽车技术的代表,BMS是电动汽车安全、性能和可靠性的关键保障。 关于新能源汽车BMS的学习资料,可以从以下方面入手: 1.理论知识:首先需要了解电池的基本组成和功能特点,掌握电池的充放电原理、电池化学反应和能量转换等基本理论知识。 2.技术标准:国内外众多组织和机构都发布了相应的技术标准和规范,例如国家标准《电动汽车动力电池系统安全技术规范》和国际标准IEC 62660-1等。 3.应用实践:实践是检验理论的重要途径,可以通过实践培养掌握BMS设计和应用的技能,例如构建一个简单的电池包和BMS系统模型进行实验验证。 4.电子书和视频教程:现在很多优质学习资源都可以在网上供学生学习,并且某些资源含义图片和视频等丰富多彩的形式。 总之,在学习新能源汽车BMS方面,除了基础理论知识外,还需要关注国内外的技术标准和规范,并进行实践训练和学习资料的积累,以便在电动汽车领域快速积累经验和技能,为将来助力电动汽车技术的发展做出贡献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值