目录
1. 概述
2. 测量方式 -- Poll
3. 测量方式 -- DAQ
3.1 ODT概念模型
3.2 DAQ List概念
3.3 ODT 绝对编号和相对编号
3.4 静态DAQ和动态DAQ模式
(1)静态DAQ
(2)动态DAQ
4.小结
在该系列的首篇文章汽车标定技术(一):XCP概述-CSDN博客,我们知道标定系统中Master与Slave的命令交互帧叫做CTO(Command Transfer Objects);Master与Slave的测量数据交互帧叫做DTO(Data Transfer Objects)。
其中关于DTO分为两种:
其数据流如下图所示:
关于DAQ这个比较容易理解,实际上,做过标定的同学下面红框两个动作都非常熟悉:
左边表示与ECU建立连接,右边闪电表示master通知ECU:请开始上传我想要的数据吧!
数据开始传输后,ECU不需要得到Master的响应,可以按照预定义的周期一直发送数据,直到Master关闭闪电:ECU,你不要再传数据了,我不想看了。
至于STIM的功能使用则需要看你处于汽车开发的哪个阶段。一般来说,标定测量会贯穿整个汽车ECU的开发,因此在不同阶段有可能是不同工程师进行标定,台架或者仿真的同学如果家里有条件可能会用到STIM,但常年跑三高的同学就不怎么使用STIM,因为直接上车干了。
那么STIM到底是干什么的?我们留在第4节进行描述。
在概述中,我们看到master可以选择不使用闪电进行测量,那除了这种方式还有没有其他方式进行测量呢?答案肯定是有的。
Master问:"我要看观测量A的值,A的地址在0x00000001“,Slave答:”这个地址存的数据是2,主人“。这种一问一答的方式我们把它叫做轮询(Poll),很明显,这种方式就是用的CTO,而不是DTO了。如下图:
在XCP协议里提供了一条指令SHORT_UPLOAD(0xF4),具体如下:
以下图为例,对观测量Triangle选择Poll的方式进行测量,上位机就会使用F4指令,并把目标地址下发给ECU。
可以看到,ECU根据上位机下发的地址去获取数据,并返回给上位机。但是各位发现没有,这种测量方式一问一答只能针对一个特定的变量;如果我想在10ms同时获取5个观测量的值,这种方式肯定是不可能的。
所以,为了解决这种并发的情况,同时减少这种不必要的问答帧对总线的负荷,DAQ应运而生。
我们首先以一个数据流来具象地体会一下DAQ这种方式,如下图:
可以看到,当上位机Master下发CMD通知ECU开始进行测量时,ECU首先答复:”我要开始咯“ ,然后就开始通过DTO-DAQ的方式不同的传输数据。这种方式只需要上位机提前通知ECU,我想要以什么样的速率获取哪些观测量的数据,ECU就会自动上传数据,而不再需要轮询这种问答制的低效率测量方式。
那么我们具体来看一下DAQ是如何实现的。
在我们讨论DAQ之前,我们先思考一个问题。
以XCP on CAN为例,如果我们想用DAQ的方式进行数据的测量,那么肯定希望Slave传递尽可能多的数据,比方说一帧标准CAN 报文,数据域8个字节,我恨不得这八个字节全是需要的数据,这样就在最有限的资源下干最多的事情。但实际情况,这是不可能的,假设现在有20个1 byte的观测量要以10ms的周期进行测量,这时候至少需要slave发送3帧报文,如果全是都是数据,master是如何直到哪一帧报文对应哪些数据呢?基于这种情况,XCP就规定DTO帧至少有一个字节是用来表示身份,如下:
因此,我们可以看到,在DTO的Identification Field至少有一个PID的身份信息。其余的FILL、DAQ的含义我们后面再讲。
接着我们来看,XCP对于要测量的数据是如何进行抽象的。首先祭出一张大家都看过的图:
这张图的知识点比较密集,但属于会者不难。
在XCP协议中,有几个概念需要理解,分别是Element、ODT、ODT Entry
Slave根据ODT中的描述,把目标观测量数取出组成一个标准CAN帧(一个ODT一帧报文),从上图我们可以看到,ODT里面总共有7个条目,意味着Slave要根据这个ODT来获取7个观测量的数据组成一个CAN报文,但实际上一帧标准CAN只有8个字节,PID占据一个字节,那只有7个字节可以用了,是不是就意味着上图中描述的每个Element的数据长度均为1;
如果上面所有7个观测量都变成了2个Byte,那么总共要传输的数据长度就变成了14个,此时需要CAN 报文2帧,填充方式如下:
这个时候,ODT#0中就有4个ODT enrty,ODT#1中也有4个ODT entry;因此我们可以直到,ODT entry不一定描述的完整观测量地址和长度,它只需要告诉slave在什么地方拿多长的数据即可,具体解析和拼接由master完成。总结下来,一个ODT中可以包含1~7个ODT Entry。如果参数占用1byte,则一个ODT可以容纳7个ODT Entry;如果参数占用2byte,则一个ODT可以容纳3个ODT Entry;如果参数占用4byte,则一个ODT可以容纳1个ODT Entry;如果参数有3个2byte和1个1byte,则一个ODT可以容纳4个ODT Entry。
多个ODT组成一个DAQ List,如下:
DAQ List可以有多个,对应不同的测量周期,例如 10ms对应DAQ list0、100ms对应DAQ list1。因此就引出了ODT的编号问题,比如说两个DAQ 的ODT#0怎么分别;接着往下看。
ODT绝对编号是指每个ODT编号在所有的DAQ List中是唯一的。比如:有2个DAQ List(DAQ0和DAQ1),每个DAQ中都有7个ODT,则DAQ0中的ODT编号是0~6,则DAQ1中的ODT编号是7~13。
相对ODT编号是指每个DAQ List中的ODT编号都是从0开始编号。如比如:有两个DAQ List(DAQ0和DAQ1),每个DAQ都有7个ODT。对于DAQ0来说,ODT编号是0~6,对于DAQ1来说,ODT编号也是0~6。
除此之外,XCP使用了AG(ADDRESS_GRANULARITY)规定了element的对齐方式, 可以取值1、2、4。在配置中多使用1字节对齐。基于CAN的传输,一帧只能传输8个字节。假如标识区采用如下形式,AG=1,则对齐的方式就是1字节对齐,即不管参数是1、2、4字节都可以向该CAN帧中填。
如果AG=2,对于1byte的参数1和参数2,及2byte的参数3排列如下所示,参数1和参数2都是1byte,为保证AG=2,其后使用填充位AA补齐。
数据采集提供了DAQ静态采集和动态采集的模式,具体如下:
DAQ配置信息可通过指令GET_DAQ_PROCESSOR_INFO(0xDA)获取
可以看到,静态配置下,DAQlist数量、ODT入口数量都是固定的,但是每个DAQ列表中的ODT个数可以不一样。
从上图可以看出,动态DAQ中,DAQlist数量是由配置的DAQ(可以为0,1,2,。。。。)+配置好的DAQ(DAQ_COUNT)决定,非固定的;ODT数量由ODT_COUNT决定;而ODT入口长度也可以灵活配置。
在配置动态DAQ列表时,需要严格遵守以下时序:FREE_DAQ, ALLOC_DAQ, ALLOC_ODT ALLOC_ODT_ENTRY,首先,主机发送FREE_DAQ指令来清空DAQ;然后发送ALLOC_DAQ分配DAQ列表数量;接着,发送ALLOC_ODT将所有的ODT分配给DAQ列表;最后发送ALLOC_ODT_ENTRY将所有的ODT入口分配给ODT。具体如下:
动态配置流程
1)释放DAQ(D6):清除之前配置好的DAQ列表、ODT和ODT_Entry等,完成之后在这里会将DAQ配置状态置为FREE
2)分配DAQ(D5):上位机会根据命令(DA)中的DAQlist数量发送命令;
完成之后将DAQ配置状态置为DAQ状态
3)分配ODT(D4):这里的ODTcount推测是根据在上位机中拖取观测量的数量,如果拉出9个观测量,每个观测量大小为4个字节,每一帧可上传7个字节,因此ODTcount就为(4*9)/7=5.1,因此至少需要6个ODT. 完成之后将DAQ配置状态置为ODT状态
4)分配ODT ENTRY(D3):
这里就是给每一帧数据分配几个数据,还是接着上面的,第一帧可上传7个字节的数据,那么如果每个数据的大小均为4个字节,就只能上传1个数据加上下一个数据的前三个字节,因此ODTENTRY为2;那么第二帧接着上面的就可以上传第一帧未传完的剩余一个字节(1byte)、第三个数据(4byte)以及第四个数据的前两个字节(2byte),所以第二帧的ODTENTRY为3;以此类推。
两个DAQ list配置数据流如下:
当有两个daqlist的时候,CANape在动态配置时顺序如下:AllocDAQ(分配2个daqlist)、AllocOdt(给两个daqlist分配好odt)、AllocOdtEntry(给2个daqlist的odt分配好entry),并不是之前我理解的每一个daqlist分配好odt和entry之后再处理另一个daq,具体看如下log截图:
分配完毕之后再设置daq指针,往该地址里写相应的测量量的数据;如下
本篇内容,我们简单把DAQ的基本概念和实现方式做了初步梳理,大家要注意理解DAQ动态分配的数据流,接下来我们讲STIM\Bypassing,以及不同传输协议对应的帧结构区别