Saturday, 11 April 2020 18:25

基于CAN总线的汽车诊断协议UDS (网络层 ISO 15765) Featured

网络层的国际标准是ISO 15756-2,该标准详细规定了协议的具体细节。CAN总线是一帧8个字节,该协议可以使CAN总线高效的传输大约8个字节(up to 4095 bytes)的命令和数据。基于该标准文档,我开发出了一个独立性良好的协议栈,工作在上层诊断协议之下和下层CAN驱动之上,下面详解开发协议栈时需要实现的部分(基于 ISO 15765-2:2004(E))

网络层的国际标准是ISO 15756-2,该标准详细规定了协议的具体细节。CAN总线是一帧8个字节,该协议可以使CAN总线高效的传输大约8个字节(up to 4095 bytes)的命令和数据。基于该标准文档,我开发出了一个独立性良好的协议栈,工作在上层诊断协议之下和下层CAN驱动之上,下面详解开发协议栈时需要实现的部分(基于 ISO 15765-2:2004(E))
 
    4 Network layer overview    4.2 Services provided by network layer to higher layers    4.2小节是描述网络层协议提供给上层的服务
    (a) Communication services  (通信服务)     有四个,其中第1个是发送消息的服务,我实现为一个外部函数,提供给上层调用,第2,3,4是上层获取协议栈发送和接收状态的服务,我按照回调函数的方式实现,于是变成了上层提供给网络层的接口。如果转成C++代码,可以用虚函数来实现。
    1) N_USData.request
    是网络层提供给上层的发送消息的服务,5.2.1小节对其有详细的描述,我只实现了两个参数,msg_buf和msg_dlc,发送时根据消息长度判断是单帧发送还是多帧发送,
extern void network_send_udsmsg (uint8_t msg_buf[],uint16_t msg_dlc) { if (msg_dlc==0|| msg_dlc> UDS_FF_DL_MAX)return; if (msg_dlc= UDS_SF_DL_MAX) { send_singleframe (msg_buf, msg_dlc); } else { nwl_st = NWL_XMIT; send_multipleframe (msg_buf, msg_dlc); }}
 
    2)N_USData_FF.indication
    该服务用来通知上层,网络层收到了首帧,5.2.3小节对其有详细的描述,我实现了一个参数msg_dlc,该函数通过回调实现,具体细节在上层代码中,按下不表。
函数原型声明如下
typedef void (*ffindication_func) (uint16_t msg_dlc);
网络层接收到首帧后调用该服务。
    3)N_USData.indication
    该服务把接收到的完整消息传递给上层,5.2.4小节对其有详细的描述,我实现了3个参数,msg_buf,msg_dlc和n_result,该函数通过回调实现,具体细节在上层代码中,按下不表。
函数原型声明如下
typedef void (*indication_func) (uint8_t msg_buf[], uint16_t msg_dlc, n_result_t n_result);
该函数调用较多:
    1.接收到单帧,with N_OK
    2.接收连续帧,如果sn错误,with N_WRONG_SN
    3.接收连续帧,如果长度正确,with N_OK
    4.网络层主循环中,如果CR定时器超时,with N_TIMEOUT_Cr
    5.接收到首帧和单帧,如果网络层状态异常,with N_UNEXP_PDU
 
    4)N_USData.confirm
该服务用来通知上层,消息发送已经完成,并返回成功与否,5.2.2小节对其有详细的描述。我实现了1个参数n_result,该函数通过回调实现。具体细节在上层代码中,按下不表。
函数原型声明如下
typedef void(*confirm_func)(n_result_t n_result);
该函数调用如下:
    1.接受到流控帧,如果流状态>= FS_RESERVED, with N_INVALID_FS
    2.接收到流控帧,如果流状态== FS_OVERFLOW, with N_BUFFER_OVFLW
    3.网络层主循环中,如果BS定时器超时,with N_TIMEOUT_Bs
    b) Protocol parameter setting services (协议参数控制服务)协议参数控制服务有两个,我没有实现,具体用处我还不明白,但是不影响实现协议栈功能。
 
    6 Network layer protocol    第6节描述网络层协议内容
    6.1-6.4小节简要说明    当消息长度小于等于6(扩展地址和混合地址)或者7(普通地址)个字节时,是通过一个N_PDU(数据单元)发送完成,叫做SF(单帧)。
    当消息长度较大时,是通过多个N_PDUs(数据单元)发送完成,这种数据单元叫做FF(首帧,第一个N_PDU)和CF(连续帧,后续的N_PDUs)。
    FF(首帧)包括前面5个(扩展地址和混合地址)或者6个(普通地址)字节的内容,1个或者多个CF(连续帧),每个CF包括后续的6个(扩展地址和混合地址)或者7个(普通地址)字节的内容,当然也可以少于6个或者7个字节。消息长度信息在FF(首帧)中发送,所有的CF(连续帧)在发送端被编号,以帮助接收者按顺序重组
消息。(最后一句话没什么卵用)
    接收者通过Flow control(流控帧)的机制,告知发送者自己有多大的接收能力。(其实就是每两个FC之间允许连续发送多少个CF,每两个CF之间的时间不能过快)
Flow control 包含三个字段:
    Flow status(FS),流状态,用来控制发送方接下来的行为,总共有三个定义,分别是FC.CTS(继续发送),FC.WAIT(继续等待),FC_OVFLW(缓存溢出,此时应该终止发送)。
    Block Size (BS),每次收到流控帧之后,发送者最大可发送的连续帧的个数。
    SeparationTimeMin (STmin),两个连续帧之间的最小间隔。
    综上所述,网络层共有4中数据单元类型:SF N_PDU,FF N_PDU, CF N_PDU, FC N_PDU。详细说明在6.4节,不再赘述。
 
    Tale 2 是N_PDU format (数据单元格式),每个N_PDU由三个域组成。
 
    在使用普通地址时,地址域仅由CAN ID组成,CAN消息数据的第一个字节(或前两字节)为N_PCI Bytes。N_PCI(Protocol control information)标识了一条消息的类型和附加信息。
6.5 Protocol control information specificationTable 3描述各种类型的N_PDU 的N_PCI bytes的定义。
 
    N_PCI byte的第一个字节的高4位为N_PCItype,标识该N_PDU(数据单元)的类型。
    0,SF(单帧)
    1,FF(首帧)
    2,CF(连续帧)
    3,FC(流控帧)
    4-F,保留定义
 
我在程序中接收到一条诊断报文后,通过一条宏定义获取N_PCItype
 
#define NT_GET_PCI_TYPE(n_pci) (n_pci>>4) pci_type = NT_GET_PCI_TYPE (frame_buf[0]);
 
然后根据pci_type进行不同的处理。...

继续阅读完整内容

请查看下方广告以解锁文章剩余内容

广告加载中...
Read 24477 times Last modified on Saturday, 11 April 2020 19:22

GPS singal acquisition,replay and test equipment

Portable singal acquisition and replay

AI intelligent tongue imager

Tongue imager rafavi
 
Please support our site by viewing this advertisement.

Please support our site by viewing this advertisement

Free Content