多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
![](https://img.kancloud.cn/f1/54/f154ffe7cdd2df183f3c2d20ac35a03e_832x592.png =600x) 虽然是C++,但是我们的写法是嵌入式C++的方式,非常贴近C语言,仅仅使用了C++最基础的特性,如果大家想把C++改成C语言,按照继承逻辑就可以了。 ### 接口中的commit是发送数据用的,payload是用户数据,调用该接口会自动打包成串口数据协议格式的数据。 ### 这个类里面最重要的是on\_stream和on\_packet,其它函数都是解析报文后的用户层面逻辑,on\_stream是用来解析流数据的,也就是收到串口数据后,判断是否是完整的报文,具体代码如下: ![](https://img.kancloud.cn/2e/80/2e80ff125c036494432e37a1c2c672ba_832x676.png =600x) ### 代码的逻辑就是不断地探测buffer,直到报文格式完整(注意:这里并不会判断数据是否出错,只保证是一个完整包)为止。当然还有个地方有待完善,就是不同revision的判断也是有差别的,这个大家可以进行修改。 ### 接着就是on\_packet了: ### ``` 1.void zb_msg::on_packet(const char *data, uint16_t len)   2.{   3.    if (len < 4 || !(data[0] == 0xFE && data[1] == 0x01 && data[2] == 0xA0 && data[3] == 0xBC)) return;   4.   5.    /* CRC16 */   6.    uint16_t crc16 = ((uint16_t)data[len-2] << 8) | (uint16_t)data[len-1];   7.   8.    /* Check CRC16 */   9.    if (crc16 != crc16_x25((const uint8_t *)data, len - 2)) return;   10.   11.    /* Revision */   12.    uint8_t revision = data[4];   13.   14.    /* Access control: control flag */   15.    uint8_t actrl = data[5];   16.   17.    if (actrl & ZB_MSG_ACTRL_SYNC) {   18.        if (revision > this->revision_) this->commit(NULL, 0, (uint16_t)ZB_MSG_ACTRL_SYNC << 8, 255);   19.        else this->revision_ = revision;   20.   21.        return;   22.    }   23.   24.    if (revision > this->revision_) { this->commit(NULL, 0, (uint16_t)ZB_MSG_ACTRL_REVISION_ERR << 8, 0xFF); return; }   25.   26.    if (revision == 0x00) {   27.        /* Access control: data flag */   28.        uint8_t adata = data[6];   29.   30.        /* Seq */   31.        uint8_t seq = data[7];   32.   33.        /* Payload length */   34.        uint16_t size = ((uint16_t)data[8] << 8) | (uint16_t)data[9];   35.   36.        if (actrl & ZB_MSG_ACTRL_ACK_REQ) this->commit(NULL, 0, (uint16_t)ZB_MSG_ACTRL_ACK_RSP << 8, seq);   37.   38.        this->handle((const uint8_t *)&data[10], size);   39.   40.        (void)adata;   41.    }   42.} ``` ### 代码逻辑比较简单,检测完整性,判断revision进行兼容,并处理访问控制符,最后把用户数据交给handle去处理。复杂一点我们还可以根据访问控制进行分帧处理,访问控制符的标识我们可以自己定义,比如定义同步报文,定义是否需要响应标识等。 ### 然后我们看main函数怎么进行使用: ![](https://img.kancloud.cn/b5/cb/b5cb9d7d3570ccafc245122c68e07e47_762x588.png =600x) ### 数据的处理是在zb\_msg中的handle函数,我们的用户逻辑和业务代码就在该函数中去处理即可。