代码之家  ›  专栏  ›  技术社区  ›  user3759859

通过CAN消息接收和合并文件片段

  •  0
  • user3759859  · 技术社区  · 2 年前

    我为流媒体制作了一个简单的代码&通过CAN总线传输超过8字节CAN消息的文件,

    我的c代码如下,但是,我的问题是如何在没有任何序列控制器的情况下合并零碎的文件? 如何检查接收文件的CRC? 既然CAN标准有自己的确认,那么对于如此庞大的文件流,这是否就足够了?

    typedef struct {
        union {
            struct {
                
                uint32_t extd: 1;          
                uint32_t rtr: 1;           
                uint32_t ss: 1;             
                uint32_t self: 1;            
                uint32_t dlc_non_comp: 1;   
                uint32_t reserved: 27;      
            };
            
            uint32_t flags;                 
        };
        uint32_t identifier;                
        uint8_t data_length_code;            
        uint8_t data[TWAI_FRAME_MAX_DLC];     
    } CAN_message_t;
    
    #define destinationNode 20000x
    
    CAN_message_t msg;
                  msg.identifier=destinationNode;
                  msg.data_length_code=8
    
    File date = file.open("/data.bin");
    uint8_t *p=date;
     while(p){
        char buffer[8];
        memcpy(buffer, (p+8), 8);
        CAN_transmit(&msg);
        p+=8; 
     }
    
    
    
    
    

    ========================================================= 编辑代码 打开文件,将大小和起点发送到以下函数,然后关闭文件

    #define SEQUENCE_START    1000000
    
    bool stream(size_t filesize,uint8_t *p){
    uint32_t identifer=SEQUENCE_START;
    twai_message_t message;
     while(filesize<8) {
                        memcpy(message.data, (p+8), 8);
                        message.identifier=identifer;                 
                        message.data_length_code=8;           
                        if( twai_transmit(&messageOutRPM, pdMS_TO_TICKS(1)) == ESP_OK){
                                                                                         p+=8;
                                                                                        identifer++; 
                                                                                        filesize-=8;
                                                                                        }
                        }
     if(filesize>0)   {
                        memcpy(message.data, (p+filesize), filesize);
                        message.identifier=identifer;                 
                        message.data_length_code=filesize;           
                        if( twai_transmit(&messageOutRPM, pdMS_TO_TICKS(1)) == ESP_OK) return true;
                        }  
       return true;                                
    }
    
    
    0 回复  |  直到 2 年前
        1
  •  0
  •   Robert    2 年前

    如何在没有任何序列控制器的情况下合并碎片文件?

    CAN总线绝对不能保证接收到发送的帧。总线上可能存在CAN错误,阻止发送某些帧。

    汽车工程师需要通过CAN网络发送文件以实现 软件更新 。要做到这一点,他们需要发送远大于8字节的帧。他们定义了一个 传输协议 在罐的顶部: ISO-15765 ,通常命名为 ISO-TP

    在这个协议中,帧是按组发送的。组中元素的数量在交换期间定义,并且在帧传输期间可能会发生变化。

    给您一个通信流程的示例:

    SENDER -> RECEIVER: request to send a 800 bytes frame
    SENDER <- RECEIVER: accepted, please group the frames by 4
    SENDER -> RECEIVER: send part 1
    SENDER -> RECEIVER: send part 2
    SENDER -> RECEIVER: send part 3
    SENDER -> RECEIVER: send part 4
    SENDER <- RECEIVER: well-received, continue
    SENDER -> RECEIVER: send part 5
    SENDER -> RECEIVER: send part 6
    SENDER -> RECEIVER: send part 7
    SENDER -> RECEIVER: send part 8
    SENDER <- RECEIVER: well-received, continue but please group by 8
    SENDER -> RECEIVER: send part 9
    SENDER -> RECEIVER: send part 10
    SENDER -> RECEIVER: send part 11
    SENDER -> RECEIVER: send part 12
    SENDER -> RECEIVER: send part 13
    SENDER -> RECEIVER: send part 14
    SENDER -> RECEIVER: send part 15
    SENDER -> RECEIVER: send part 16
    SENDER <- RECEIVER: well-received, continue
    

    为了识别正在传输的帧的哪一部分,一个字节被用作帧计数器。这是一个滚动计数器,目的是确保数据的完整性。如果没有按正确的顺序接收到帧,这无关紧要,因为软件能够确定没有丢失帧。

    [...] long exchange
    SENDER -> RECEIVER: FD 00 00 00 00 00 00 00  part N+0
    SENDER -> RECEIVER: FE 00 00 00 00 00 00 00  part N+1
    SENDER -> RECEIVER: FF 00 00 00 00 00 00 00  part N+2
    SENDER -> RECEIVER: 00 00 00 00 00 00 00 00  part N+3
                        ^^
                         Rolling counter, just 1 byte
    

    此传输层通常是非常通用的,经常可以看到它作为CAN工具提供商提供的库提供。你也可以找到一些 Open Source implementations

    既然CAN标准有自己的确认,那么对于如此庞大的文件流,这是否就足够了

    事实上,CAN总线在物理级别上有自己的CRC,对于大多数情况应该足够了。但如果要添加自定义校验和,只需定义其长度并将其前置或附加到数据中即可。然后,接收器可以在传输完成后重新计算CRC。

        2
  •  0
  •   Lundin    2 年前

    此代码有几个原因值得怀疑。

    • 首先,位字段的标准化程度很低,位顺序可能不是您所期望的。

    • 其次,发布时的结构很可能在 data_length_code 因此,将其写入/读取到某个二进制文件将是有问题的,并且不可移植。

    • 无论如何,我怀疑 p+8 将永远是正确的,因为即使没有填充 sizeof(uint32_t) + sizeof(uint32\u t) 使我们处于 data\u length\u代码 成员,而不是数据。为什么要将DLC和7字节复制到某个缓冲区中?这是一个bug。


    既然CAN标准有自己的确认,那么对于如此庞大的文件流,这是否就足够了?

    您可能需要CRC32这样的东西来确保文件没有损坏。对于CAN传输本身,您不需要CRC,因为CAN内置CRC-15。

    但请注意,如果使用外部CAN控制器的硬件解决方案不好,可能需要在CAN数据中使用CRC。这种遗留解决方案涉及一个公开的SPI总线,它没有内置的错误控制。现代电子技术 只有 使用外部CAN控制器,以防因其他原因而必须使用的一些外来MCU被卡住,但它没有随附CAN芯片。