# COM协议构架说明

<p class="callout warning">为了简化协议和方便解析，COM协议本质上就是对CAN指令的封装，其中包含的4~12位数据为4位CAN ID和8位CAN数据。由于COM报文长度是8~16位，使用固定表头0x55，请先阅读<span style="color: rgb(53, 152, 219);">[标准CAN协议](https://odocs.hexfellow.com/books/hexmove/chapter/xstd)</span>再阅读以下内容。</p>

### <span style="color: rgb(31, 78, 121);">COM </span><span style="color: rgb(31, 78, 121);">报文设置</span>

通信波特率：<span style="color: rgb(32, 56, 100);">460800</span>

标准：<span style="color: rgb(32, 56, 100);">自定义协议串口</span>

<div id="bkmrk-com-%E6%8A%A5%E6%96%87%E7%BB%93%E6%9E%84-%E6%95%B0%E6%8D%AE%E5%AE%9A%E4%B9%89-head-l"><table style="width: 100%;"><tbody><tr><td colspan="6" style="background: rgb(189, 214, 238);">COM 报文结构

</td></tr><tr><td style="background: rgb(189, 214, 238);">数据定义

</td><td class="align-center" style="vertical-align: middle;">HEAD

</td><td class="align-center" style="vertical-align: middle;">LEN

</td><td class="align-center" style="vertical-align: middle;">DATA \[0~11\]

</td><td class="align-center" style="vertical-align: middle;">Frame ID

</td><td class="align-center" style="vertical-align: middle;">Checksum

</td></tr><tr><td style="background: rgb(189, 214, 238);">数据类型

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">4~12 x unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td></tr><tr><td style="background: rgb(189, 214, 238);">说明

</td><td class="align-center" style="vertical-align: middle;">表头固定0x55

</td><td class="align-center" style="vertical-align: middle;">COM报文长度0x08~0x10

</td><td class="align-center" style="vertical-align: middle;">4位CAN ID

0~8位CAN报文数据

</td><td class="align-center" style="vertical-align: middle;">帧ID

可固定也可累加

连贯数据的序列戳

</td><td class="align-center" style="vertical-align: middle;">前7~15位内容的累加和

再取最低位的int8反馈

</td></tr></tbody></table>

</div><table id="bkmrk-data-%5B0%7E11%5D-%E6%95%B0%E6%8D%AE%E5%AE%9A%E4%B9%89-id%5B" style="width: 100%; height: 119.188px;"><tbody><tr style="height: 29.7969px;"><td colspan="6" style="background: rgb(189, 214, 238); height: 29.7969px;">DATA \[0~11\]

</td></tr><tr style="height: 29.7969px;"><td style="background: rgb(189, 214, 238); height: 29.7969px;">数据定义

</td><td class="align-center" style="vertical-align: middle;">ID\[0\]

</td><td class="align-center" style="vertical-align: middle;">ID\[1\]

</td><td class="align-center" style="vertical-align: middle;">ID\[2\]

</td><td class="align-center" style="vertical-align: middle;">ID\[3\]

</td><td class="align-center" style="vertical-align: middle;">DATA \[0~7\]

</td></tr><tr style="height: 29.7969px;"><td style="background: rgb(189, 214, 238); height: 29.7969px;">数据类型

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">unsigned int8

</td><td class="align-center" style="vertical-align: middle;">0~8 x unsigned int8

</td></tr><tr style="height: 29.7969px;"><td style="background: rgb(189, 214, 238); height: 29.7969px;">说明

</td><td class="align-center" style="vertical-align: middle;">设备大类

</td><td class="align-center" style="vertical-align: middle;">设备型号

</td><td class="align-center" style="vertical-align: middle;">设备编号

</td><td class="align-center" style="vertical-align: middle;">设备功能

</td><td class="align-center" style="vertical-align: middle;">0~8字节数据

</td></tr></tbody></table>

### <span style="color: rgb(31, 78, 121);">报文内容解释</span>

#### <span style="color: rgb(31, 78, 121);">Frame ID</span>

- 设计上是一个序列戳，方便对连续的数据包进行校验，帮助发现掉包现象。
- 该序列从0到255，溢出后自动循环
- 对非连续指令或不需要严格防掉包指令可以固定某一数值
- 一般用于上位机校验，设备一般不使用该值

#### <span style="color: rgb(31, 78, 121);">Checksum</span>

- 对报文前7~15位（总共8~16位）的累加和，取和的最低位字节，用于简单的数据校验
- 代码案例如下：

```c
unsigned char checksum(unsigned char* data) {
    unsigned char sum = 0x00;
    for (int i = 0; i < data[1] - 1; i++) {
        sum += data[i];
    }
    return sum;
}
```