汽车电子 -- vector CanApe 离线标定

想要实现vector CanApe 离线标定功能,使用A2L文件开发来实现。

一、什么是标定

1、标定

汽车行业经常听到“标定”这个名词,此外,“虚拟标定”也常出现。
车辆标定英文名称为 Vehicle Calibration 或 Automotive Calibration。

2、汽车标定(Automotive Calibration)的含义是什么?

标定是指对各种车辆系统进行微调,以确保其性能符合设计规范的过程。这可能涉及调整软件设置、标定传感器或修改机械部件,以达到预期效果。
标定意味着教授(teach),目标是让标定的对象学到些东西。例如在标定传感器时,你要告诉它相对于车辆的位置,以及它应该看哪里。

3、汽车上哪些系统通常需要标定?

  • 高级驾驶员辅助系统(ADAS): 包括车道偏离警告、自动制动和自适应巡航控制等功能。
  • 发动机控制模块(ECM):管理发动机功能、燃料燃烧和排放。
  • 变速箱系统: 确保平稳换挡和最佳性能。
  • 各种传感器: 从胎压传感器到泊车辅助系统。

二、标定使用工具 CANape

CANape 是一种测量和标定工具。用于实时分析和优化控制单元参数。它为工程师提供了测量、记录和分析来自各种传感器和 ECU 的数据的能力。

  • 为 ECU 提供测量和标定功能
  • 允许实时数据记录和分析
  • 支持 CAN、LIN、FlexRay 等总线
  • 实现 ECU 的快速原型设计、测试和标定
  • 具有用户友好的图形界面

三、基础知识回想

1、存储空间布局

在这里插入图片描述

2、map文件

在编译链接阶段,编译器会为变量、常量、函数等分配地址,分配的地址是固定唯一的,可以通过编译器生成的map文件查看。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、ld文件

在编译链接阶段,gcc编译器会加载ld(link description)文件,将程序中定义的数据按照ld文件描述分配地址。

四、标定实现

1、生成srec文件

  • 在标定功能实现的过程中,我们期望标定的参数存储在一个固定的区域,该区域仅存储需要标定的变量或者常量。这个时候就需要调整GCC的LD文件,在LD文件中添加一个标定区域。
    在这里插入图片描述
    在这里插入图片描述
  • 在定义需要标定的参数的时候通过GCC的attribute扩展将参数量定义到标定参数区。
    在这里插入图片描述

编译完成后,查看对应的map文件,可以看到编译器给这几个变量分配的地址。
在这里插入图片描述
生产的对应的bin文件中,按照地址空间定义对应
对应的bin文件地址为add=0x410000 -(0x300000+0x30000)=0xe0020
在这里插入图片描述
arc-elf32-objcopy 将elf文件转换为srec文件。

arc-elf32-objcopy -O srec sensor_gnu_arcem6.elf firmware.srec
  • arc-elf32-objcopy在ARC_GUN eclipse安装软件bin文件夹中有包含。
    在这里插入图片描述
    生成的 firmware.srec 0x410020地址下包含要标定的数据。
    在这里插入图片描述

2、生成a2l文件

参看:通过.map文件填写XCP标定需要的A2L文件

import re
from copy import  deepcopy

class Map_to_A2L(object):

    def __init__(self):
        self.__mapfile_buf = []
        self.__a2lfile_buf = []
        self.a2lfile_adrr = r"C:\Users\Desktop\example.a2l"
        self.mapfile_adrr = r"C:\Users\Desktop\test.map"
        self.__measurement_vars_list = []
        self.__a2file_buflen_previous = 0
        self.__map_characteristic_buf = r".calipara"
        self.__insert_pos = 0
        self.measurement_sec_template = "    /begin MEASUREMENT"+"\n"   \
                                       + "      name\n"                 \
                                       + "      \"this is for test\n"   \
                                       + "      FLOAT32_IEEE\n"         \
                                       + "      none\n"                 \
                                       + "      0\n"                    \
                                       + "      0\n"                    \
                                       + "      0\n"                    \
                                       + "      0\n"                    \
                                       + "      ECU Address"            \
                                       + "        "+"0X32\n"            \
                                       + "    /end MEASUREMENT"+"\r\n"
                                                                    
        self.characteristic_template = '   /begin CHARACTERISTIC Name               \n'\
                                     + '     \"DESCRIPTION FOR THIS QUANTITATIVE\"  \n'\
                                     + '     VALUE                                  \n'\
                                     + '     ECUADDRESS                             \n'\
                                     + '     __ULONG_S                              \n'\
                                     + '     0                                      \n'\
                                     + '     NO_COMPU_METHOD                        \n'\
                                     + '     0                                      \n'\
                                     + '     4294967295                             \n'\
                                     + '     FORMAT \"%10.3\"                       \n'\
                                     + '   /end CHARACTERISTIC                      \n'\
                                     + '                                            \n'

    def __open_and_get_mapfile(self):
        with open(self.mapfile_adrr, mode = "rb") as f:
            while True:
                line = f.readline().decode('ascii', 'ignore')
                if not line:
                    break
                else:
                    self.__mapfile_buf.append(line)

    def __get_info_from_map_file(self):
        row = 0
        buf_measurement_index = []
        while row != len(self.__mapfile_buf):
            if re.findall(self.__map_characteristic_buf, self.__mapfile_buf[row], re.I):
                buf_measurement_index.append(row)   
            row = row + 1          
        buf_measurement_index = buf_measurement_index[1:]
        measurement_dict = {"Name": None, "ECU Address": None}
        for i in range(len(buf_measurement_index)):
            if i == len(buf_measurement_index) - 1:
                break
            index1 = buf_measurement_index[i]
            index2 = buf_measurement_index[i + 1]
            
            my_characteristic_buf = (' ' + self.__map_characteristic_buf + '\r\n')
            if my_characteristic_buf == self.__mapfile_buf[index1]:
                start_index = index1 + 2 #Skip the next invalid line
            else:
                start_index = index1 + 1 #Skip current invalid line
            endof_index = index2 
            
            for j in range(start_index, endof_index):
                if str(self.__mapfile_buf[j]).strip() == "" :
                    break
                dict_ = deepcopy(measurement_dict)
                data = self.__mapfile_buf[j].replace("\r\n", "").strip().split()
                dict_["Name"] = data[1]
                dict_["ECU Address"] = data[0]
                self.__measurement_vars_list.append(dict_)
          
          
        for index in  self.__measurement_vars_list:     
            print(index)

                
    def __open_and_get_a2l_file(self): #store origin a2l file in buf and then rewrite it(I consider to use the default template and create a new a2l file in the same folder as mapfile) 
        with open(self.a2lfile_adrr, mode="r") as f:
            while True:
                line = f.readline()
                if not line:
                    self.__a2file_buflen_previous = len(self.__a2lfile_buf)
                    break
                else:
                    self.__a2lfile_buf.append(line)

    def __del_old_characteristic_sec_in_a2l_file(self): #find measurement sectors in origin or default a2l file and delete them (just in buf not in file)
        a2l_buf_index = []
        index = 0
        for line in  self.__a2lfile_buf:
            if re.findall(r'/begin CHARACTERISTIC',line,re.I) or re.findall(r'/end CHARACTERISTIC',line,re.I): 
                a2l_buf_index.append(index)
            index = index + 1    

        if len(a2l_buf_index) >= 2 and len(a2l_buf_index) % 2 == 0:
            del self.__a2lfile_buf[a2l_buf_index[0] : (a2l_buf_index[-1] + 1)]
            self.__a2lfile_buf.pop(a2l_buf_index[0])
            # a2file_buflen_change = self.__a2file_buflen_previous - len(self.__a2lfile_buf) - 2
            # self.__insert_pos = a2l_buf_index[-1] - a2file_buflen_change
            self.__insert_pos = a2l_buf_index[0]
            print("self.__insert_pos = %d" % (self.__insert_pos))
        else:
            print("A2L Contains no keywords CHARACTERISTIC...\r\n")
        

    def __update_a2l_characteristic_paragraph(self):  
        for i in range(len(self.__measurement_vars_list)):
            NAME = self.__measurement_vars_list[i]["Name"]
            ADRR = self.__measurement_vars_list[i]["ECU Address"]  
            my_characteristic_template = self.characteristic_template.replace("Name",NAME).replace("ECUADDRESS",ADRR)
            self.__a2lfile_buf.insert(self.__insert_pos + i, my_characteristic_template)
            print(my_characteristic_template)                      
        print('----------------------------------------------------------------------------------------------------')                       
     
    def __update_a2l_measurement_paragraph(self):  
            for i in range(len(self.__measurement_vars_list)):
                name = self.__measurement_vars_list[i]["Name"]
                ECU_ADRR = self.__measurement_vars_list[i]["ECU Address"]
                self.__a2lfile_buf.insert(self.__insert_pos+i, self.measurement_sec_template.replace("name",name).replace("0X32",ECU_ADRR))


    def __update_a2l_buf(self):
        self.__update_a2l_characteristic_paragraph()
        # self.__update_a2l_measurement_paragraph()
        

    def __update_a2lfile(self):
        with open(self.a2lfile_adrr, mode = "w") as f:
            for line in self.__a2lfile_buf:
                f.write(line)


    def exchange(self):
        self.__open_and_get_mapfile()
        if len(self.__mapfile_buf) >=1:
            self.__get_info_from_map_file()
        else:
            print("map为空") 
            
        self.__open_and_get_a2l_file()
        if len(self.__a2lfile_buf) >=1:
            self.__del_old_characteristic_sec_in_a2l_file()
        else:
            print("a2l文件为空")
            
        self.__update_a2l_buf()
        if len(self.__a2lfile_buf) >=10:
            self.__update_a2lfile()
        else:
            print("A2L_File_Error")
        
ob=Map_to_A2L()
ob.exchange()

其中 example.a2l模板,可从下面的CDM Studio安装路径获取。
在这里插入图片描述
或者将下面拷贝到新建example.a2l文件中。

ASAP2_VERSION 1 60
/begin PROJECT CCPSIM ""

  /begin MODULE CPP ""


    /begin MOD_COMMON ""
      BYTE_ORDER MSB_FIRST
    /end MOD_COMMON
	
	/*
	/begin IF_DATA ASAP1B_CCP

    /end IF_DATA
	*/
	
	/begin COMPU_METHOD Method_AAAA "AAAA"
      RAT_FUNC "" ""
      COEFFS 0 1 0 0 0 1
    /end COMPU_METHOD
    
                                      
   /begin CHARACTERISTIC PARAME_DATE_VER               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e0000                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
   /begin CHARACTERISTIC PARAME_DATE_DAY               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e0004                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
   /begin CHARACTERISTIC PARAME_DATE_MONTH               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e0008                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
   /begin CHARACTERISTIC PARAME_DATE_YEAR               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e000c                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
   /begin CHARACTERISTIC PARAME_VERSION               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e0010                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
   /begin CHARACTERISTIC DEVICE_VERSION               
     "DESCRIPTION FOR THIS QUANTITATIVE"  
     VALUE                                  
     0x004e0014                             
     __ULONG_S                              
     0                                      
     NO_COMPU_METHOD                        
     0                                      
     4294967295                             
     FORMAT "%10.3"                       
   /end CHARACTERISTIC                      
                                            
                                          
    /begin RECORD_LAYOUT CurveNxVub 
      FNC_VALUES 2 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveNxXVub 
      FNC_VALUES 3 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 2 UBYTE INDEX_INCR DIRECT
      NO_AXIS_PTS_X 1 UBYTE
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveV8ub 
      FNC_VALUES 1 UBYTE ROW_DIR DIRECT
      FIX_NO_AXIS_PTS_X 8
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveVub 
      FNC_VALUES 1 UBYTE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveX8V8ub 
      FNC_VALUES 2 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
      FIX_NO_AXIS_PTS_X 8
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveX8V8ubAlternate 
      FNC_VALUES 2 UWORD ALTERNATE_WITH_X DIRECT
      AXIS_PTS_X 1 UWORD INDEX_INCR DIRECT
      FIX_NO_AXIS_PTS_X 8
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT CurveX8ub 
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
      FIX_NO_AXIS_PTS_X 8
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapColRowuw 
      FNC_VALUES 1 UWORD COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapNxNyVub 
      FNC_VALUES 3 UBYTE ROW_DIR DIRECT
      NO_AXIS_PTS_X 1 UBYTE
      NO_AXIS_PTS_Y 2 UBYTE
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapNxNyXYVub 
      FNC_VALUES 5 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 3 UBYTE INDEX_INCR DIRECT
      AXIS_PTS_Y 4 UBYTE INDEX_INCR DIRECT
      NO_AXIS_PTS_X 1 UBYTE
      NO_AXIS_PTS_Y 2 UBYTE
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapNxXNyYVuc 
      FNC_VALUES 5 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 2 UBYTE INDEX_INCR DIRECT
      AXIS_PTS_Y 4 UBYTE INDEX_INCR DIRECT
      NO_AXIS_PTS_X 1 UBYTE
      NO_AXIS_PTS_Y 3 UBYTE
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapRowColub 
      FNC_VALUES 1 UBYTE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapV86ub 
      FNC_VALUES 1 UBYTE ROW_DIR DIRECT
      FIX_NO_AXIS_PTS_X 8
      FIX_NO_AXIS_PTS_Y 6
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapX8Y6V86ub 
      FNC_VALUES 3 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
      AXIS_PTS_Y 2 UBYTE INDEX_INCR DIRECT
      FIX_NO_AXIS_PTS_X 8
      FIX_NO_AXIS_PTS_Y 6
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapX8Y8V88ub 
      FNC_VALUES 3 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
      AXIS_PTS_Y 2 UBYTE INDEX_INCR DIRECT
      FIX_NO_AXIS_PTS_X 8
      FIX_NO_AXIS_PTS_Y 8
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT MapXYVub 
      FNC_VALUES 3 UBYTE ROW_DIR DIRECT
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
      AXIS_PTS_Y 2 UBYTE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __UBYTE_Z 
      FNC_VALUES 1 UBYTE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __UWORD_Z 
      FNC_VALUES 1 UWORD ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __ULONG_Z 
      FNC_VALUES 1 ULONG ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SBYTE_Z 
      FNC_VALUES 1 SBYTE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SWORD_Z 
      FNC_VALUES 1 SWORD ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SLONG_Z 
      FNC_VALUES 1 SLONG ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __FLOAT32_IEEE_Z 
      FNC_VALUES 1 FLOAT32_IEEE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __FLOAT64_IEEE_Z 
      FNC_VALUES 1 FLOAT64_IEEE ROW_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __UBYTE_S 
      FNC_VALUES 1 UBYTE COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __UWORD_S 
      FNC_VALUES 1 UWORD COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __ULONG_S 
      FNC_VALUES 1 ULONG COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SBYTE_S 
      FNC_VALUES 1 SBYTE COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SWORD_S 
      FNC_VALUES 1 SWORD COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __SLONG_S 
      FNC_VALUES 1 SLONG COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __FLOAT32_IEEE_S 
      FNC_VALUES 1 FLOAT32_IEEE COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT __FLOAT64_IEEE_S 
      FNC_VALUES 1 FLOAT64_IEEE COLUMN_DIR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__UBYTE_S 
      AXIS_PTS_X 1 UBYTE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__UWORD_S 
      AXIS_PTS_X 1 UWORD INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__ULONG_S 
      AXIS_PTS_X 1 ULONG INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__SBYTE_S 
      AXIS_PTS_X 1 SBYTE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__SWORD_S 
      AXIS_PTS_X 1 SWORD INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__SLONG_S 
      AXIS_PTS_X 1 SLONG INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__FLOAT32_IEEE_S 
      AXIS_PTS_X 1 FLOAT32_IEEE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

    /begin RECORD_LAYOUT SSV__FLOAT64_IEEE_S 
      AXIS_PTS_X 1 FLOAT64_IEEE INDEX_INCR DIRECT
    /end RECORD_LAYOUT

  /end MODULE
/end PROJECT

执行上面的python脚本,生成新的example.a2l, 将map文件中标定量的地址信息和标定量名称更新到该A2L文件中。
在这里插入图片描述
其中:

  • Type
    在这里插入图片描述
  • A2L文件预定义类型:
    在这里插入图片描述
  • ConversionType:
    在这里插入图片描述

在这里插入图片描述
BYTE_ORDER:字节序,
MSB_LAST=Intel,默认为Intel
MSB_FIRST = Motorola

3、安装和使用CDM Studio

下载:CDM Studio 12.6 SP1
在这里插入图片描述

通过CDM读取A2L的标定量以及更新S19文件中对应的标定值

  • File → Open 打开雷达APP文件,然后打开对应A2L文件。将srec和A2L文件文件导入CDM Studio中。
    在这里插入图片描述
    将013A0009h改为024A0009h,点击save as,保存为新的srec文件。
    在这里插入图片描述

srec_cat 将srec文件转换为bin文件

srec_cat firmware.srec  -offset - -minimum-addr firmware.srec -Output out_firmware.bin -Binary
  • srec_cat 即 srecord官网下载:http://srecord.sourceforge.net/

查看对应的bin文件地址为add=0x410000 -(0x300000+0x30000)=0xe0020
已经标定成功。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聚优致成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值