协议规范
端到端
分为PC端和设备端
- PC端运行调试程序
- 设备端实现自己的业务
设备端向PC端发送数据,称之为PUSH
设备端获取PC端数据,称之为PULL
PUSH 协议规范
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | |
|---|---|---|---|---|---|---|
| 字节数 | 1 | 1 | 1 | n | 1 | 1 |
| 默认值 | 0x7a | 待定 | 待定 | 待定 | 待定 | 0x7b |
命令位: 表示命令类型
数据位的n值,由数据长度位的值决定
校验位:(命令位 + 数据长度位 + 数据位)的结果取高位
PULL 协议规范
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | |
|---|---|---|---|---|---|---|
| 字节数 | 1 | 1 | 1 | n | 1 | 1 |
| 默认值 | 0x7b | 待定 | 待定 | 待定 | 待定 | 0x7a |
命令位: 表示命令类型
数据位的n值,由数据长度位的值决定
校验位:(命令位 + 数据长度位 + 数据位)的结果取高位
已实现协议
| 命令 | 方向 | 说明 | 示例 |
|---|---|---|---|
| 0x00 | 接收 | 速度 | 0x7a 0x00 11 2 2 2 1 0x7b |
| 0x01 | 接收 | 直立环PID | 0x7a 0x01 17 4 4 4 1 0x7b |
| 0x02 | 接收 | 速度环PID | 0x7a 0x02 17 4 4 4 1 0x7b |
| 0x03 | 接收 | 转向环PID | 0x7a 0x03 17 4 4 4 1 0x7b |
PUSH协议
通道消息
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | ||
|---|---|---|---|---|---|---|---|
| 字节数 | 1 | 1 | 1 | 4 | …… | 1 | 1 |
| 默认值 | 0x7a | 0x01 | 待定 | 计算获得 | 0x7b |
- 数据位长度为4的倍数
- 每4位表示一个通道
- 每4位表示一个float类型数据
速度消息
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| x | y | z | ax | ay | az | gx | gy | gz | v | ||||||
| 字节数 | 1 | 1 | 1 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 1 | 1 |
| 默认值 | 0x7a | 0x01 | 待定 | 待定 | 0x7b |
- x:4个字节,float类型。x轴速度
- y: 4个字节,float类型。y轴速度
- z: 4个字节,float类型。z轴速度
- ax:4个字节,float类型。x轴加速度
- ay: 4个字节,float类型。y轴加速度
- az: 4个字节,float类型。z轴加速度
- gx:4个字节,float类型。x轴角速度
- gy: 4个字节,float类型。y轴角速度
- gz: 4个字节,float类型。z轴角速度
- v: 4个字节,float类型。电压值
PULL协议
配置PID
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | ||||
|---|---|---|---|---|---|---|---|---|---|
| 类 | P | i | d | ||||||
| 字节数 | 1 | 1 | 1 | 1 | 4 | 4 | 4 | 1 | 1 |
| 默认值 | 0x7b | 0x01 | 待定 | 待定 | 0x7a |
数据位包含了
- id: 第几组pid
- p:4个字节,float类型
- i: 4个字节,float类型
- d: 4个字节,float类型
设置速度
| 帧头 | 命令位 | 数据长度 | 数据位 | 校验位 | 帧尾 | |||
|---|---|---|---|---|---|---|---|---|
| x | y | z | ||||||
| 字节数 | 1 | 1 | 1 | 4 | 4 | 4 | 1 | 1 |
| 默认值 | 0x7b | 0x02 | 待定 | 待定 | 0x7a |
数据位包含了
- x:4个字节,float类型。x轴速度
- y: 4个字节,float类型。y轴速度
- z: 4个字节,float类型。z轴速度
库使用说明
库文件
#ifndef __PID_H__#define __PID_H__void PID_init();void PID_push(float *chns, int chn_cnt);void PID_pull(unsigned char dat);void PID_parse();extern void PID_on_config_pid(unsigned char id, float kp, float ki, float kd);#endif
#include "PID.h"#include "Bluetooth.h"//////////// PUSH ///////////////#define TX_FRAME_HEAD 0x7a#define TX_FRAME_END 0x7b#define TX_CMD_CHN 0x01//////////// PULL //////////////#define RX_FRAME_HEAD 0x7b#define RX_FRAME_END 0x7a#define RX_CMD_PID 0x01#define MAX_BUF 64static unsigned char buf[MAX_BUF];static unsigned char buf_idx = 0;static unsigned char buf_len = 0;//////////////////////////// 根据实际情况修改以下代码调用方式////////////////static void PID_send(unsigned char dat) {BT_send(dat);}//////////////////////////////////////////////////////////////////////////////////////////////////////// 数据转换:不同平台可能存在大小端问题 /////////////////////////////// 当前是大端,修改顺序即可改为小端 ///////////////////typedef union {float f;unsigned char b[4];} FloatBytes;static void floatToBytes(float value, unsigned char *bytes) {FloatBytes fb;fb.f = value;bytes[0] = fb.b[3];bytes[1] = fb.b[2];bytes[2] = fb.b[1];bytes[3] = fb.b[0];}static float bytesToFloat(unsigned char *bytes) {FloatBytes fb;fb.b[0] = bytes[3];fb.b[1] = bytes[2];fb.b[2] = bytes[1];fb.b[3] = bytes[0];return fb.f;}///////////////////////////////////////////////////////////////void PID_init() {}void PID_push(float *chns, int chn_cnt) {//帧头 | 命令 | 数据长度 | 数据 | 校验码 | 帧尾//1字节 | 1字节 | 1字节 | n字节 | 1字节 | 1字节//命令: 请求类型的标识//数据长度: 表示后面 数据 的字节个数//校验码: 命令 + 数据长度 + 数据, 取高位unsigned char i;float chn;unsigned char tmp[4];unsigned short sum = 0;PID_send(TX_FRAME_HEAD);PID_send(TX_CMD_CHN);PID_send(chn_cnt * 4);sum += TX_CMD_CHN;sum += chn_cnt * 4;for(i = 0; i < chn_cnt; i++) {floatToBytes(chns[i], tmp);PID_send(tmp[0]);sum += tmp[0];PID_send(tmp[1]);sum += tmp[1];PID_send(tmp[2]);sum += tmp[2];PID_send(tmp[3]);sum += tmp[3];}PID_send((sum >> 8) & 0xFF);PID_send(TX_FRAME_END);}static void parse_config_pid() {float kp, ki, kd;kp = bytesToFloat(&buf[(buf_idx + 4) % MAX_BUF]);ki = bytesToFloat(&buf[(buf_idx + 8) % MAX_BUF]);kd = bytesToFloat(&buf[(buf_idx + 12) % MAX_BUF]);PID_on_config_pid(buf[buf[(buf_idx + 3) % MAX_BUF], kp, ki, kd);}//////////////////// 如果要去增加其他命令的解析,可以修改这个函数 ////////////static void on_cmd() {unsigned char cmd;cmd = buf[(buf_idx + 1) % MAX_BUF];if(cmd == RX_CMD_PID) {parse_config_pid();}}//////////////////////////////////////////////////////////////////////////////void PID_parse() {unsigned char dat_len, i;unsigned short sum = 0;//////////////// check cmdif(buf_len < 3) return;// 消息组成// 帧头 | 命令 | 数据长度 | 数据 | 校验码 | 帧尾// 1字节 | 1字节 | 1字节 | n字节 | 1字节 | 1字节// 命令: 请求类型的标识// 数据长度: 表示后面 数据 的字节个数// 校验码: 命令 + 数据长度 + 数据, 取高位// check frame headif(buf[buf_idx] != RX_FRAME_HEAD) {// drop onebuf_idx++;buf_idx %= MAX_BUF;if(buf_len != 0) buf_len--;PID_parse();return;}// check dat lendat_len = buf[(buf_idx + 2) % MAX_BUF];// check cmd total lenif(buf_len < dat_len + 5) return;// check sumsum += buf[(buf_idx + 1) % MAX_BUF];sum += buf[(buf_idx + 2) % MAX_BUF];for(i = 0; i < dat_len; i++) {sum += buf[(buf_idx + 3 + i) % MAX_BUF];}if(((sum >> 8) & 0xFF) != buf[(buf_idx + dat_len + 3) % MAX_BUF]) {// dropbuf_idx++;buf_idx %= MAX_BUF;if(buf_len != 0) buf_len--;PID_parse();return;}// check frame endif(buf[(buf_idx + dat_len + 4) % MAX_BUF] != RX_FRAME_END) {// dropbuf_idx++;buf_idx %= MAX_BUF;if(buf_len != 0) buf_len--;PID_parse();return;}// parse success/**if(buf[(buf_idx + 1) % MAX_BUF] == RX_CMD_PID) {// config pidparse_config_pid();}**/on_cmd();// dropbuf_idx += dat_len + 5;buf_idx %= MAX_BUF;if(buf_len >= dat_len + 5) {buf_len -= dat_len + 5;} else {buf_len = 0;}PID_parse();}void PID_pull(unsigned char dat) {unsigned char idx = buf_idx + buf_len;idx %= MAX_BUF;// config datbuf[idx] = dat;buf_len ++;if(buf_len > MAX_BUF) {buf_idx = 0;buf_len = 0;}}
使用步骤
- 拷贝都文件和c文件到项目种
修改c文件中PID__send函数实现
#include "Bluetooth.h"....static void PID_send(unsigned char dat) {BT_send(dat);}
修改为自己的实现,以上是蓝牙的实现,发送的是单个byte
调用
PID_init()初始化在需要的地方调用
PID_pushvoid PID_push(float *chns, int chn_cnt);
| 命令 | 方向 | 说明 | 示例 |
|---|---|---|---|
| 0x00 | 接收 | 速度 | 0x7a 0x00 11 2 2 2 1 0x7b |
| 0x01 | 接收 | 直立环PID | 0x7a 0x01 17 4 4 4 1 0x7b |
| 0x02 | 接收 | 速度环PID | 0x7a 0x02 17 4 4 4 1 0x7b |
| 0x03 | 接收 | 转向换 | 0x7a 0x03 17 4 4 4 1 0x7b |
协议文档
/*接收的数据:帧头 标志位 长度 X速度 Y速度 Z速度 校验位 帧尾0x7a 0x00 11 2 2 2 1 0x7b 11位帧头 标志位 长度 kp ki kd 校验位1 帧尾 直立环0x7a 0x01 17 4 4 4 1 0x7b帧头 标志位 长度 kp ki kd 校验位1 帧尾 速度环0x7a 0x02 17 4 4 4 1 0x7b帧头 标志位 长度 kp ki kd 校验位1 帧尾 转向换0x7a 0x03 17 4 4 4 1 0x7b浮点数据,放大100倍,转为整数发送0x7a 0x00 0x00 0x11 0x11 0x11 0x11 0x12 0x13 0x12 0x7b发出去的数据:帧头 停止位 X速度 Y速度 Z速度 X加速度 Y加速度 Z加速度 X角速度 Y角速度 Z角速度 电压 校验位 帧尾0x7b 1 2 2 2 2 2 2 2 2 2 2 1 0x7ashort 是2个字节,范围-32768~32767*/
