记录CAN报文使用CANoe能导入和分析

1、实验目的:
使用CAN卡采集CAN报文,通过mdfSDK记录CAN报文,将记录数据通过CANoe工具导入,在CAoe中对CAN数据进行分析,或导入DBC文件,对CAN数据进行信号量解析。

2、实验方法
模拟CAN报文记录MDF数据文件。

3、mdfSDK的使用
3.1 测试主函数
源码见canlog.c
记录CAN报文使用CANoe能导入和分析_第1张图片
(1) mdf_open为mdfSDK的API函数,创建一个mdf文件,获取mdfFile的文件
(2) mdf_create_canlog_CG()创建CAN记录文件的MDF文件格式。
(3) write_canData 模拟CAN数据,写到MDF文件中。
(4) mdf_close 为mdfSDK的API函数,关闭mdf文件 。

3.2 创建MDF文件结构
记录CAN报文使用CANoe能导入和分析_第2张图片
(1) mdf_new_CG(mdfHandle)为SDK API接口,初始化一个CG数据块。
(2) mdf_create_CN为SDK API接口,在上面的CG数据块下依次创建15个CN数据通道,其中msgTime为时间戳通道。
(3) mdf_create_CG为SDK API接口,创建上面的CG数据块。

3.3 写MDF文件
模拟10条CAN报文,CANID依次为1到10,时间间隔为100us 。依次将数据写入到MDF文件中。
记录CAN报文使用CANoe能导入和分析_第3张图片

4 CANoe加载
使用测试代码 mdf_canlog 生成测试数据 can10.log 。
打开CANoe软件 , 在Trace界面中导入can10.log文件。
记录CAN报文使用CANoe能导入和分析_第4张图片
记录CAN报文使用CANoe能导入和分析_第5张图片

#include 
#include 
#include 
#include 
#include 
#include "mdf.h"


static  mdf_handle    mdfFile ;

static unsigned long long timebase = 0;

unsigned long long tm_get_systick(void)
{
    int ret = -1;
    unsigned long long time;
    int cnt = 0;
    static struct timespec  now = {0, 0};

    while (ret < 0 && cnt < 3)
    {
        ret = clock_gettime(CLOCK_MONOTONIC, &now);
        cnt++;
    }

    time = now.tv_sec * 1000 + now.tv_nsec / (1000 * 1000);

    return time;
}
unsigned long long tm_get_time(void)
{
    return tm_get_systick() - timebase;
}


/****************************************************************************************************************/
static  uint8_t      u8_canlog = 0;
static  pthread_t    canlog_tid;

#define CAN_ERROR_FLAG     0x9
#define CAN_GOOD_FLAG      0x0

static mdf_cc_liner can_ts_liner = {
.factor = 0.000001,
.offset = 0
};

#define    CANLOG_CN_MAX       15
static mdf_CN_options canlog_info[CANLOG_CN_MAX]=
{
	{	 "type", 0  ,  8,	 0  , 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{	 "can" , 8  , 16,	 0  , 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{	 "id"  , 24 , 32,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
    {	 "dir" , 56 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},	
	{	 "rtr" , 64 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{	 "dlc" , 72 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},		
	{ "msg[0]" , 80 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[1]" , 88 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[2]" , 96 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[3]" , 104 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[4]" , 112 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[5]" , 120 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[6]" , 128 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msg[7]" , 136 ,  8,	 0	, 0 , CN_TYPE_DATA , MDF_SIGNAL_UNSIGNED ,MDF_CC_NONE , NULL , NULL , NULL},
	{ "msgTime", 144 , 32,	 0	, 0 , CN_TYPE_TIME , MDF_SIGNAL_UNSIGNED ,MDF_CC_LINEAR , &can_ts_liner , NULL , NULL},
};
int  mdf_create_canlog_CG( mdf_handle mdfHandle )
{
	int  i , ret ;
	mdf_CG_handle* canCG = mdf_new_CG(mdfHandle);
	if (canCG == NULL )
	{
		printf("mdf new CG fail!\n");
		return MDF_ERR_CG ;
	}
	for ( i = 0 ; i < CANLOG_CN_MAX ; i++ )
	{
		if ( (ret = mdf_create_CN( mdfHandle , canCG , &canlog_info[i] ))!= 0 )
		{
			printf("mdf_add_CN fail , errcode = %d!\n" , ret );
			return ret;
		}
	}
	ret = mdf_create_CG(mdfHandle , canCG , "this CG is canlog , it is can import into canoe");
	if ( ret < 0 )
	{
		printf("mdf_add_CG fail , errcode = %d!\n" , ret );
		return ret;
	}
	u8_canlog = (uint8_t) ret;

	return 0;
}


typedef struct
{
	uint64_t ts;
    union
    {
        uint8_t dlc;
        struct
        {
            uint8_t len  : 4;
            uint8_t port : 4;
        };
    };

    union
    {
        uint32_t MsgID; /* CAN Message ID (11-bit or 29-bit) */
        struct
        {
            uint32_t msgid : 31;
            uint32_t exten : 1;
        };
    }; 
    uint8_t  Data[8];
} __attribute__ ((packed)) CAN_MSG;

#define  CAN_ONEINPUT_MAX    10
#define  CAN_TOTAL_MAX       10000

static void *canlog_record(void)
{
	int       ret ;
	uint32_t  u32Temp  = 0 ;
	uint32_t  offset ;
	uint8_t   fileBuf[23*CAN_ONEINPUT_MAX] ;  
	CAN_MSG   canMsg[CAN_ONEINPUT_MAX];
	CAN_MSG  *pt_can;
	int       i , cnt = 0;
	
	while(cnt < CAN_TOTAL_MAX)
	{
		// generate can data
		for ( i = 0 ;i < CAN_ONEINPUT_MAX ; i++ )
		{
			u32Temp++;				
			canMsg[i].MsgID = 0x100 + i ;
			canMsg[i].dlc      = 8;
			memcpy(canMsg[i].Data , &u32Temp , 4 );
			canMsg[i].ts = tm_get_time();
			usleep(100);
		}

		offset = 0;
		for ( i = 0 ;i < CAN_ONEINPUT_MAX ; i++ )
		{		  
			pt_can = &canMsg[i];
			fileBuf[offset++] = u8_canlog ;  
			fileBuf[offset++] = CAN_GOOD_FLAG ;   //type
			fileBuf[offset++] = i + 1 ;            //can 
			fileBuf[offset++] = 0;                //can
			memcpy( &fileBuf[offset] , &pt_can->MsgID , 4 ); //id
			offset += 4;
			fileBuf[offset++] = 0 ;              //dir
			fileBuf[offset++] = 0 ;              //rtr
			fileBuf[offset++] = pt_can->len ;    //dlc
			memcpy( &fileBuf[offset] , &pt_can->Data , 8);//data
			offset += 8;
			memcpy( &fileBuf[offset] , &pt_can->ts , 4 );//timestamp
			offset += 4;
		}
		ret = mdf_append_data( mdfFile , u8_canlog , fileBuf , offset , CAN_ONEINPUT_MAX );
		if (ret != 0 )
		{
			printf(" write can log into mdf err %d\n", ret );
			break;
		}
		cnt += CAN_ONEINPUT_MAX ;		

		usleep(1000);
	}

}

static void write_canData()
{
	int       i ;
	uint32_t  u32Temp = 0 , offset ;
	CAN_MSG   canMsg[CAN_ONEINPUT_MAX];
	CAN_MSG   *pt_can;
	uint8_t   fileBuf[230] ;
		
	for ( i = 0 ;i < CAN_ONEINPUT_MAX ; i++ )
	{
		u32Temp++;
		canMsg[i].MsgID    = i+1 ;
		canMsg[i].dlc	   = 8;
		canMsg[i].Data[0]  = i + 1;
		canMsg[i].Data[1]  = 2;
		canMsg[i].Data[2]  = 3;
		canMsg[i].Data[3]  = 4;
		canMsg[i].Data[4]  = 5;
		canMsg[i].Data[5]  = 6;
		canMsg[i].Data[6]  = 7;
		canMsg[i].Data[7]  = 8;
		canMsg[i].ts       =  tm_get_time();
		usleep(100);
	}
	offset = 0;
	for ( i = 0 ;i < CAN_ONEINPUT_MAX ; i++ )
	{		  
		pt_can = &canMsg[i];
		fileBuf[offset++] = u8_canlog ;  
		fileBuf[offset++] = CAN_GOOD_FLAG ;   //type
		fileBuf[offset++] = pt_can->port ;	  //can 
		fileBuf[offset++] = 0;				  //can
		memcpy( &fileBuf[offset] , &pt_can->MsgID , 4 ); //id
		offset += 4;
		fileBuf[offset++] = 0 ; 			 //dir
		fileBuf[offset++] = 0 ; 			 //rtr
		fileBuf[offset++] = pt_can->len ;	 //dlc
		memcpy( &fileBuf[offset] , &pt_can->Data , 8);//data
		offset += 8;
		memcpy( &fileBuf[offset] , &pt_can->ts , 4 );//timestamp
		offset += 4;
	}
	mdf_append_data( mdfFile , u8_canlog , fileBuf , offset , CAN_ONEINPUT_MAX );
}

int  main(int argc, char *argv[])
{
	int  i ;
	int  ret ;
	mdf_file_options  fileOpt;
	if ( argc < 2 ) 
	{
        printf("Usage: %s file_name", argv[0]);
	}	
	char*  fileName = argv[1];
	timebase = tm_get_systick();
	memset( &fileOpt , 0 ,sizeof(mdf_file_options));	
	fileOpt.opt_company 	=  "TIZA-Info";
	fileOpt.opt_division	=  "roadtest";
	fileOpt.opt_operator	=  "tboxSN=12345678";
	fileOpt.opt_project 	=  "your_project";
	fileOpt.opt_subject 	=  "your_subject";
	fileOpt.opt_description =  "EMS-4G93-CCP-V400";

	mdfFile = mdf_open(fileName , &fileOpt );
	if (mdfFile == NULL )
	{
		printf("mdf open fail!\n");
		return 0;
	}	
	if ( mdf_create_canlog_CG(mdfFile) != 0 )
	{
		printf("mdf create canlog CG fail!\n");
		goto EXIT;
	}
	write_canData();
/*  ret = pthread_create(&canlog_tid, NULL, (void *)canlog_record , NULL);
	if ( ret != 0 )
	{
		printf(" create pthread for record canlog into mdf fail\n");
	}

	pthread_join(canlog_tid, NULL) ;
*/	
EXIT:
	mdf_close(mdfFile);
	return 0;
}

你可能感兴趣的:(MDF)