【DBC专题】-10-CAN DBC转换C语言代码Demo_接收Rx报文篇
创始人
2024-05-31 03:56:16
0

案例背景(共15页精讲):
该篇博文将告诉您,CAN DBC转换C语言代码Demo,只需传递对应CAN信号关联参数,无需每个信号"左移"和"右移",并举例介绍:在CANoe/Canalyzer中CAPL中的应用:对接收报文,进行解包。其它场景的应用,也可参考该篇。

目录

1 背景:CAN信号在CAN 报文/Frame中位置的决定因素

2 讲解:CAN DBC转换C语言代码Demo

2.1 定义一些宏定义

2.2 定义一些结构体

2.3 API接口函数原型

2.4 对CANFD DBC的支持

2.5 如何使用该API接口

3 举例:在CANoe/Canalyzer中CAPL中的应用:对接收报文,进行解包

3.1 信号的字节顺序Byte Order: Intel小端模式

3.1.1 CAPL文件can的完整代码

3.1.2 系统变量定义

3.1.3 测试结果

3.2信号的字节顺序Byte Order: Motorola大端模式

3.2.1 CAPL文件can的完整代码

3.2.2 系统变量定义

3.2.3 测试结果

结尾


优质博文推荐阅读(单击下方链接,即可跳转):

Vector工具链

CAN Matrix DBC

CAN Matrix Arxml

1 背景:CAN信号在CAN 报文/Frame中位置的决定因素

一个CAN信号在CAN 报文/Frame中的位置,由3个条件决定,见图1-1:

  • 信号的起始位Startbit:默认为信号的Lsb;
  • 信号的长度Length
  • 信号的字节顺序Byte Order: Intel小端模式和Motorola大端模式。

详见博文“【DBC专题】-4-DBC文件中的Signal信号字节顺序Motorola和Intel介绍icon-default.png?t=N176https://blog.csdn.net/qfmzhu/article/details/111561710”,这里不再重复讲解。

下面我们根据这个背景,来设计一个通用算法,封装成一个函数,只需输入几个参数,即可得到对应的信号值。

图1-1

 

2 讲解:CAN DBC转换C语言代码Demo

2.1 定义一些宏定义

#define FRAME_TJW_ZERO_DLC  0   // unit:Byte
#define FRAME_TJW_MAX_DLC  8    // unit:Byte
#define SIGNAL_TJW_ZERO_LENGTH  0    // unit:Bit
#define SIGNAL_TJW_MAX_LENGTH  64    // unit:Bit
#define SIGNAL_TJW_INIT_VALUE  0
#define SIGNAL_TJW_INIT_MASK  0#define SIGNAL_TJW_BYTE_ORDER_INTEL  0
#define SIGNAL_TJW_BYTE_ORDER_MOTOROLA  1#define CAN_SIGNAL_TJW_NORMAL  0
#define CAN_SIGNAL_TJW_NO_VALUE  1
#define CAN_FRAME_TJW_DLC_OUT_OF_RANGE  2
#define INVALID_INPUT_PARAMETERS_TJW  3/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/

2.2 定义一些结构体

typedef struct
{uint8 Signal_State;      // Describes the state of a signaluint64 Signal_Value;     // Describes the value of a signal
} Unpack_CAN_Signal;
/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/

2.3 API接口函数原型

/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/Unpack_CAN_Signal Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex_Fun(
uint8* data_buff,          /**Byte array of CAN data field**/
uint8 signal_start_bit,    /**Rang:0~(FRAME_TJW_MAX_DLC * 8 - 1)**/
uint8 signal_length,       /**Rang:1~SIGNAL_TJW_MAX_LENGTH**/
boolean signal_byte_order, /**0:Intel;1:Motorola**/
uint8 frame_length)        /**Rang:1~FRAME_TJW_MAX_DLC**/
{Unpack_CAN_Signal can_signal;uint8 i = 0;uint8 byte_num = 0;uint8 low_data_byte = 0;uint8 high_data_byte = 0;uint8 low_data_byte_position = 0;uint8 high_data_byte_position = 0;uint8 remaining_bit_number = 0;uint8 remaining_byte_number = 0;	uint64 can_signal_mask = SIGNAL_TJW_INIT_MASK;can_signal.Signal_State = CAN_SIGNAL_TJW_NORMAL;can_signal.Signal_Value = SIGNAL_TJW_INIT_VALUE;if(frame_length == FRAME_TJW_ZERO_DLC)            /**DLC of CAN frame is 0**/{can_signal.Signal_State = CAN_SIGNAL_TJW_NO_VALUE;}else if(frame_length > FRAME_TJW_MAX_DLC)         /**DLC of CAN frame is out of range**/{can_signal.Signal_State = CAN_FRAME_TJW_DLC_OUT_OF_RANGE;}else if((signal_length > (frame_length * 8))         /**Invalid signal_length: The length of the signal is not in the range of DLC**/|| (signal_length > SIGNAL_TJW_MAX_LENGTH)          /**Invalid signal_length: The length of the signal exceeds the maximum Unsigned of C language**/|| (signal_length == SIGNAL_TJW_ZERO_LENGTH)        /**Invalid signal_length: The length of the signal is not equal to 0**/				){can_signal.Signal_State = INVALID_INPUT_PARAMETERS_TJW;}else{		/**Byte Order: Intel**/if(signal_byte_order == SIGNAL_TJW_BYTE_ORDER_INTEL)  {/**Bytes used by CAN signal,Byte[0] is low byte,Byte[frame_length] is high byte**/low_data_byte = signal_start_bit / 8;high_data_byte = (signal_start_bit + signal_length - 1) / 8;  // 2 + 6 - 1 /8 = 0;  2 + 7 - 1 /8 = 1 ;  2 + 14 - 1 /8 = 1 ;  2 + 15 - 1 /8 = 2if((high_data_byte + 1) > frame_length)  /** CAN signal is not in the range of DLC**/{can_signal.Signal_State = CAN_FRAME_TJW_DLC_OUT_OF_RANGE;}else{for(i = 0;i < signal_length;i++)  /**Generate signal mask according to signal length**/{can_signal_mask |= 0x0000000000000001 << i;}low_data_byte_position = signal_start_bit % 8;  /**Distance from the lowest bit of each byte**//**CAN Signal is in a bytes**/if(low_data_byte == high_data_byte) {					can_signal.Signal_Value = (((uint64)data_buff[low_data_byte]) >> low_data_byte_position) & can_signal_mask;				}/**CAN Signal in multiple bytes**/else{					for(byte_num = low_data_byte;byte_num <= high_data_byte;byte_num++){if(byte_num == low_data_byte){can_signal.Signal_Value |= ((uint64)data_buff[low_data_byte]) >> low_data_byte_position;}else{can_signal.Signal_Value |= ((uint64)data_buff[byte_num]) << ((byte_num - low_data_byte - 1) * 8 + (8 - low_data_byte_position));}						}can_signal.Signal_Value = can_signal.Signal_Value & can_signal_mask;					}				}}/**Byte Order: Motorola**/else  /**signal_byte_order == SIGNAL_TJW_BYTE_ORDER_MOTOROLA**/{/**Bytes used by CAN signal,Byte[0] is low byte,Byte[frame_length] is high byte**/high_data_byte = signal_start_bit / 8;	if((high_data_byte + 1) > frame_length)        /** CAN signal is not in the range of DLC**/{can_signal.Signal_State = CAN_FRAME_TJW_DLC_OUT_OF_RANGE;}else{for(i = 0;i < signal_length;i++)  /**Generate signal mask according to signal length**/{can_signal_mask |= 0x0000000000000001 << i;}high_data_byte_position = signal_start_bit % 8;  /**Distance from the lowest bit of each byte**//**CAN Signal is in a bytes**/if(signal_length <= (8 - high_data_byte_position)){				can_signal.Signal_Value = (((uint64)data_buff[high_data_byte]) >> high_data_byte_position) & can_signal_mask;					}/**CAN Signal in multiple bytes**/else{			remaining_bit_number = signal_length - (8 - high_data_byte_position); // 剩余bit = 12 - (8 - 2) = 6if((remaining_bit_number % 8) != 0)     {remaining_byte_number = remaining_bit_number / 8 + 1;          // remaining_byte_number = 1}else{remaining_byte_number = remaining_bit_number / 8;}for(byte_num = high_data_byte;byte_num >= (high_data_byte - remaining_byte_number);byte_num--)  // high_data_byte = 2  remaining_byte_number = 1{						if(byte_num == high_data_byte){can_signal.Signal_Value |= ((uint64)data_buff[high_data_byte]) >> high_data_byte_position;}else{can_signal.Signal_Value |= ((uint64)data_buff[byte_num]) << ((high_data_byte - byte_num - 1) * 8 + (8 - high_data_byte_position));}		if(byte_num == 0)	{break;}						}can_signal.Signal_Value = can_signal.Signal_Value & can_signal_mask;									}			}				}}return can_signal;
}
/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/

2.4 对CANFD DBC的支持

只需将宏定义FRAME_TJW_MAX_DLC的值由8调整为64,即可适配CANFD DBC。

2.5 如何使用该API接口

1、提供的demo,使用了uint8,uint64,boolean类型,在将该代码集成至开发环境中,需要注意这些类型的替换:

  • typedef unsigned char               uint8
  • typedef unsigned long long           uint64

2、调用函数Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex_Fun时,需要确认传参data_buff,signal_start_bit,signal_length,signal_byte_order,frame_length的准确性,需与DBC保持一致,这样您可以得到对应信号的状态与值;

3 举例:在CANoe/Canalyzer中CAPL中的应用:对接收报文,进行解包

CAPL语法和C语言有一些差异,我们将第2.3章节中的demo稍作修改,以满足测需要。其它场景的应用与其类似。

3.1 信号的字节顺序Byte Order: Intel小端模式

3.1.1 CAPL文件can的完整代码

/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/
/*@!Encoding:936*/
includes
{}variables
{byte CAN_Data_Byte[8];byte Signal_State;word Signal_Value;
}on message 0x100
{CAN_Data_Byte[0] = this.byte(0);CAN_Data_Byte[1] = this.byte(1);CAN_Data_Byte[2] = this.byte(2);CAN_Data_Byte[3] = this.byte(3);CAN_Data_Byte[4] = this.byte(4); CAN_Data_Byte[5] = this.byte(5);  CAN_Data_Byte[6] = this.byte(6);CAN_Data_Byte[7] = this.byte(7);@sysvar::CAN_Frame::sysvar_Test_Signal_1 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(0,2,8);@sysvar::CAN_Frame::sysvar_Test_Signal_2 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(50,12,8);@sysvar::CAN_Frame::sysvar_Test_Signal_3 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(62,2,8);
}word Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(
byte signal_start_bit,    /**Rang:0~(8 * 8 - 1)**/
byte signal_length,       /**Rang:1~64**/
byte frame_length)        /**Rang:1~8**/
{byte i = 0;byte byte_num = 0;byte low_data_byte = 0;byte high_data_byte = 0;byte low_data_byte_position = 0;byte high_data_byte_position = 0;byte remaining_bit_number = 0;byte remaining_byte_number = 0;	word can_signal_mask = 0;Signal_State = 0;Signal_Value = 0;if(frame_length == 0)            /**DLC of CAN frame is 0**/{Signal_State = 1;}else if(frame_length > 8)         /**DLC of CAN frame is out of range**/{Signal_State = 2;}else if((signal_length > (frame_length * 8))         /**Invalid signal_length: The length of the signal is not in the range of DLC**/|| (signal_length > 16)          /**Invalid signal_length: The length of the signal exceeds the maximum Unsigned of C language**/|| (signal_length == 0)        /**Invalid signal_length: The length of the signal is not equal to 0**/				){Signal_State = 3;}else{/**Byte Order: Intel**/{/**Bytes used by CAN signal,Byte[0] is low byte,Byte[frame_length] is high byte**/low_data_byte = signal_start_bit / 8;high_data_byte = (signal_start_bit + signal_length - 1) / 8;  // 2 + 6 - 1 /8 = 0;  2 + 7 - 1 /8 = 1 ;  2 + 14 - 1 /8 = 1 ;  2 + 15 - 1 /8 = 2if((high_data_byte + 1) > frame_length)  /** CAN signal is not in the range of DLC**/{Signal_State = 2;}else{		for(i = 0;i < signal_length;i++)  /**Generate signal mask according to signal length**/{can_signal_mask |= 0x0000000000000001 << i;}low_data_byte_position = signal_start_bit % 8;  /**Distance from the lowest bit of each byte**//**CAN Signal is in a bytes**/if(low_data_byte == high_data_byte) {			Signal_Value = (((word)CAN_Data_Byte[low_data_byte]) >> low_data_byte_position) & can_signal_mask;				}/**CAN Signal in multiple bytes**/else{			for(byte_num = low_data_byte;byte_num <= high_data_byte;byte_num++){				if(byte_num == low_data_byte){		Signal_Value |= ((word)CAN_Data_Byte[low_data_byte]) >> low_data_byte_position;}else{			Signal_Value |= ((word)CAN_Data_Byte[byte_num]) << ((byte_num - low_data_byte - 1) * 8 + (8 - low_data_byte_position));}				}Signal_Value = Signal_Value & can_signal_mask;					}				}}}return Signal_Value;
}
/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/

3.1.2 系统变量定义

3.1.3 测试结果

使用的DBC:

CAN DBC中信号与系统变量的解析结果一致:

3.2信号的字节顺序Byte Order: Motorola大端模式

3.2.1 CAPL文件can的完整代码

/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/
/*@!Encoding:936*/
includes
{}variables
{byte CAN_Data_Byte[8];byte Signal_State;word Signal_Value;
}on message 0x100
{CAN_Data_Byte[0] = this.byte(0);CAN_Data_Byte[1] = this.byte(1);CAN_Data_Byte[2] = this.byte(2);CAN_Data_Byte[3] = this.byte(3);CAN_Data_Byte[4] = this.byte(4); CAN_Data_Byte[5] = this.byte(5);  CAN_Data_Byte[6] = this.byte(6);CAN_Data_Byte[7] = this.byte(7);  @sysvar::CAN_Frame::sysvar_Test_Signal_4 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(6,2,8);@sysvar::CAN_Frame::sysvar_Test_Signal_5 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(10,12,8);@sysvar::CAN_Frame::sysvar_Test_Signal_6 = Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(56,2,8);
}word Rx_CAN_Frame_Data_Buff_to_CAN_Signal_Hex(
byte signal_start_bit,    /**Rang:0~(8 * 8 - 1)**/
byte signal_length,       /**Rang:1~64**/
byte frame_length)        /**Rang:1~8**/
{byte i = 0;byte byte_num = 0;byte low_data_byte = 0;byte high_data_byte = 0;byte low_data_byte_position = 0;byte high_data_byte_position = 0;byte remaining_bit_number = 0;byte remaining_byte_number = 0;	word can_signal_mask = 0;Signal_State = 0;Signal_Value = 0;if(frame_length == 0)            /**DLC of CAN frame is 0**/{Signal_State = 1;}else if(frame_length > 8)         /**DLC of CAN frame is out of range**/{Signal_State = 2;}else if((signal_length > (frame_length * 8))         /**Invalid signal_length: The length of the signal is not in the range of DLC**/|| (signal_length > 16)          /**Invalid signal_length: The length of the signal exceeds the maximum Unsigned of C language**/|| (signal_length == 0)        /**Invalid signal_length: The length of the signal is not equal to 0**/				){Signal_State = 3;}else{/**Byte Order: Motorola**/{/**Bytes used by CAN signal,Byte[0] is low byte,Byte[frame_length] is high byte**/high_data_byte = signal_start_bit / 8;	if((high_data_byte + 1) > frame_length)        /** CAN signal is not in the range of DLC**/{Signal_State = 2;}else{for(i = 0;i < signal_length;i++)  /**Generate signal mask according to signal length**/{can_signal_mask |= 0x0000000000000001 << i;}high_data_byte_position = signal_start_bit % 8;  /**Distance from the lowest bit of each byte**//**CAN Signal is in a bytes**/if(signal_length <= (8 - high_data_byte_position)){				Signal_Value = (((word)CAN_Data_Byte[high_data_byte]) >> high_data_byte_position) & can_signal_mask;					}/**CAN Signal in multiple bytes**/else{			remaining_bit_number = signal_length - (8 - high_data_byte_position); // 剩余bit = 12 - (8 - 2) = 6if((remaining_bit_number % 8) != 0)     {remaining_byte_number = remaining_bit_number / 8 + 1;          // remaining_byte_number = 1}else{remaining_byte_number = remaining_bit_number / 8;}for(byte_num = high_data_byte;byte_num >= (high_data_byte - remaining_byte_number);byte_num--)  // high_data_byte = 2  remaining_byte_number = 1{						if(byte_num == high_data_byte){Signal_Value |= ((word)CAN_Data_Byte[high_data_byte]) >> high_data_byte_position;}else{Signal_Value |= ((word)CAN_Data_Byte[byte_num]) << ((high_data_byte - byte_num - 1) * 8 + (8 - high_data_byte_position));}		if(byte_num == 0)	{break;}						}Signal_Value = Signal_Value & can_signal_mask;									}			}				}}return Signal_Value;
}
/** 使用该Demo需注明出处,以表对作者的尊重 **/
/** 版权归CSDN博客“汽车电子助手”所有,https://blog.csdn.net/qfmzhu **/

3.2.2 系统变量定义

3.2.3 测试结果

使用的DBC

CAN DBC中信号与系统变量的解析结果一致:

结尾

获取更多“汽车电子资讯”和“工具链使用”,

请关注CSDN博客“汽车电子助手”,做您的好助手。

相关内容

热门资讯

安卓系统没有通话界面,探索安卓... 你有没有遇到过这种情况?手机屏幕上明明显示着通话界面,但是当你点进去的时候,却发现什么都没有?没错,...
安卓子系统没反应,安卓子系统故... 手机突然卡壳了,安卓子系统没反应,这可怎么办?别急,让我带你一步步排查,找出问题所在,让你的手机重焕...
安卓系统装树莓派,安卓系统下树... 你有没有想过,把安卓系统装到树莓派上,会是个什么样子呢?想象一个迷你的小树莓派,竟然能运行起我们熟悉...
海信操作系统和安卓,打造智能生... 你知道吗?在智能电视的世界里,操作系统可是个大角色呢!今天,咱们就来聊聊海信的操作系统和安卓,看看它...
召唤抽奖系统1.9安卓pc,惊... 你知道吗?最近网上掀起了一股热潮,那就是召唤抽奖系统1.9安卓PC版。这款游戏可是让不少玩家为之疯狂...
安卓如何导入鸿蒙系统文件,鸿蒙... 你有没有想过,让你的安卓手机也来个华丽变身,体验一下鸿蒙系统的魅力呢?别急,今天就来手把手教你如何导...
安卓系统播放sd卡音乐,轻松播... 你有没有遇到过这种情况:手机里存了满满的音乐,却因为系统的问题无法顺畅播放?别急,今天就来给你详细说...
安卓软件内容转苹果系统,探索苹... 你有没有想过,那些在安卓手机上用得得心应手的软件,怎么就能无缝迁移到苹果系统上呢?这可不是简单的复制...
安卓原生系统无线投屏,轻松实现... 亲爱的手机控们,你是否有过这样的体验:坐在沙发上,手里拿着手机,却想在大屏幕上享受游戏或者电影的乐趣...
华为是什么安卓系统版本,探索H... 你知道吗?华为这款手机界的佼佼者,最近又引起了大家的热议。话题是什么呢?就是——华为是什么安卓系统版...
安卓大屏系统怎么更新,轻松实现... 你有没有发现,你的安卓大屏手机最近有点儿慢吞吞的?别急,这可能是时候给你的手机来个“大变身”了——更...
安卓cf怎么转苹果系统,轻松实... 你是不是也和我一样,对安卓CF这款游戏爱得深沉,但又想体验一下苹果系统的独特魅力呢?别急,今天就来手...
怎样关闭安卓双系统,一键操作指... 你是不是也和我一样,手机里装了安卓双系统,有时候觉得有点乱糟糟的,想要关闭其中一个系统呢?别急,今天...
安卓9系统特点不包括,提升了增... 你有没有发现,每次手机系统更新,都像是一场科技盛宴,让人兴奋不已?不过,你知道吗?安卓9系统虽然带来...
恋夜视频安卓系统Uc,恋夜视频... 亲爱的读者,你是否曾在深夜时分,被手机屏幕上跳动的视频吸引?今天,就让我带你一探究竟,揭开恋夜视频安...
鸿蒙套娃安卓系统视频,融合与创... 你知道吗?最近科技圈可是炸开了锅,因为华为的新操作系统鸿蒙OS又有了新动作。这不,他们竟然把鸿蒙套娃...
xp系统连接安卓手机问题,实用... 你有没有遇到过这样的情况:你的电脑上还运行着那个经典的XP系统,而你的安卓手机却时不时地想要和你亲密...
压缩安卓系统储存空间,高效管理... 手机里的照片越来越多,游戏也越玩越上瘾,可这安卓系统的储存空间却越来越紧张,是不是感觉像是在挤牙膏?...
安卓手游转苹果系统教程,轻松实... 你是不是也和我一样,手头有一堆安卓手游,突然之间想换换口味,体验一下苹果系统的魅力呢?别急,今天就来...
安卓原生系统锁屏暗,安卓系统锁... 亲爱的手机控们,你是否曾为安卓手机锁屏时的暗模式而感到好奇?那种在夜晚或光线不足的环境中,屏幕自动调...