基于UDS的DoIp实现(五) -- UDS单帧、多帧处理

发布时间 2023-04-19 10:01:34作者: 一条名叫西西的狗

  通常来讲,上位机一般只会发送8个字节数据,那么对于UDS,只需要处理这个8个字节就可以,这里也不会涉及大数据传输。但是,有些机器,比如毫米波雷达,其设计是64位,那么每次发送的数据,按照单帧的处理,是无法接收完全的,这个时候就需要进行多帧处理。

一、单帧

二、多帧

 以下列举部分帧类型,以及区分方法:

//pci type
typedef enum {
    SINGLE_FRAME = 0x00,
    FIRST_FRAME = 0x10,
    CONSECUTIVE_FRAME = 0x20,
    FLOW_CONTROL_FRAME = 0x30
} UDS_PCI_Type_T;

解释:

  SINGLE_FRAME:单帧,其第一个字节为0x00 | 数据长度(这个长度通常是不需要的);

  FIRST_FRAME:首帧,其第一个字节为0x10 | 数据长度;

  CONSECUTIVE_FRAME:连续帧,其第一个字节为0x20 | 块号(1、2、3.....);

  FLOW_CONTROL_FRAME:流控帧,这个是UDS服务向上位机发送请求数据的帧信息,其第一个字节为0x30 | 块号(也有的实现,将块号放在第二个或第三个字节发出去)。

一、单帧

s_boolean ReceiveMsg(u_uint8_t *buffer, u_uint16_t len) {
    //数据检测实现

    //获取帧类型
    UDS_PCI_Type_T type = buffer[0] & FRAME_TYPE_MASK;
    //按照不同的类型,执行不同的操作
    if (type == SINGLE_FRAME) {
        return receive_sf(buffer, len);
    } else if (type == FIRST_FRAME) {
        return receive_ff(buffer, len);
    } else if (type == CONSECUTIVE_FRAME) {
        return receive_cf(buffer, len);
    } 

    //其它操作

    return SE_LORF;
}
s_boolean receive_sf(u_uint8_t *buffer, u_uint16_t len) {
    //数据处理

    char *ptr = GetValidBuffer(len);
    memcpy(ptr, buffer, len);

    //通知UDS Server,已经获取数据

    return S_OK;
}

  单帧的实现,只是一些数据检测、拷贝数据操作,过程还是比较简单的,但是多帧的实现,就比较复杂了。

二、多帧

  多帧流程图:

    +----------------+                +----------------+
    |  Client        |                |  Server        |
    +----------------+                +----------------+
           |                                   |
           |  Send frame 1                      |
           |---------------------------------->|
           |                                   |
           |  Receive acknowledgement for frame1 |
           |<----------------------------------|
           |                                   |
           |  Send frame 2                      |
           |---------------------------------->|
           |                                   |
           |  Receive acknowledgement for frame2 |
           |<----------------------------------|
           |                                   |
           |           ...                     |
           |                                   |
           |                                   |
           |  Send frame n                      |
           |---------------------------------->|
           |                                   |
           |  Receive acknowledgement for frame n |
           |<----------------------------------|
           |                                   |
           |  Process the entire message and   |
           |  send the processing result.      |
           |---------------------------------->|
           |                                   |
           |  Receive processing result.       |
           |<----------------------------------|
           |                                   |
           |  Done.                            |
           |                                   |
    +----------------+                +----------------+
    |  Client        |                |  Server        |
    +----------------+                +----------------+

解释:(Client -上位机 Server - UDS服务)

  • 上位机先发送第一帧,逻辑判断是FF后,进行FF处理;
  • 服务向上位机发送FC,请求下一帧;
  • 上位机接收到请求后,再发送一帧(CF);
  • 后面便进入FC与CF的循环中,直到数据完全发送结束。

示例:

s_boolean receive_ff(u_uint8_t *buffer, u_uint16_t len) {
    //数据处理,获取数据长度、分块信息

    char *ptr = GetValidBuffer(len);
    memcpy(ptr, &buffer[2], len - 2);
    //发送FC
    send_fc(mFrame.current_block);

    //其它处理
}
s_boolean send_fc(int block_cnt) {
    u_uint8_t tx_buf[MSG_SEND_SIZE] = {0};
    tx_buf[0] = (FLOW_CONTROL_FRAME | block_cnt);
        //发送tx_buf到上位机
}
s_boolean receive_cf(u_uint8_t *buffer, u_uint16_t len) {
    //数据检测、保存
    if (判断数据是否接收完成) {            
        //接收完成处理
    } else {
      //未接收完成,继续请求数据
        send_fc(++mFrame.current_block);
    }        

    //其它处理
}