前言:
前面写了篇使用STM32的USB虚拟串口的笔记,既然通信口通了下面就要有数据交互,数据交互就要用到自定的协议,用于约束设备间的控制。比如:PC发一个数据包到STM32,STM32就要解析数据包,解析后根据协议约定执行相应的动作。直接贴代码就不作说明了,因为太简单。
代码如下:
#include <string.h>
#include <stdio.h>
#include<stdint.h>
#pragma pack(1)
void app_get_version(int* idata, int ilen, int* odata, int* olen);
void app_start_read(int* idata, int ilen, int* odata, int* olen);
void app_handle_err(int* idata, int ilen, int* odata, int* olen);
typedef enum {
BOOT_CODE_OK = 0x40,
BOOT_CODE_RETURN = 0xF0,
BOOT_CODE_ERROR = 0xF4
}packet_boot_code_e;
typedef enum {
NONE = 0x00,
CMD_GET_VER = 0x02,
CMD_START_READ = 0x06
}packte_cmd_e;
typedef struct {
packet_boot_code_e boot_code;
int len;
packte_cmd_e cmd;
int data[64];
int check;
}packet_t;
typedef struct {
packte_cmd_e cmd;
void(*pcallback)(int* idata, int ilen, int* odata, int* olen);
}packet_cmd_list_t;
packet_cmd_list_t app_cmds_list[] =
{
{CMD_GET_VER, app_get_version },
{CMD_START_READ, app_start_read },
{NONE, app_handle_err }
};
void packet_cmds_parse(int* idata, int ilen, int* odata, int* olen)
{
packet_cmd_list_t* pcmd_list = app_cmds_list;
packet_t* pcmd = (packet_t*)idata;
while ((pcmd_list->cmd!= pcmd->cmd)&& (pcmd_list->cmd!=0))
{
pcmd_list++;
}
// 查表结束,执行表中对应回调函数
pcmd_list->pcallback( idata, ilen, odata, olen);
}
//packet格式={boot len cmd data[] check}
void main(void)
{
int txbuff[5] = { 0x40,0x03,0x02,0xBC,0xBD };
int rxbuff[64];
int len = 0;
packet_cmds_parse(txbuff, 5, rxbuff, &len);
printf("main\n");
}
void app_get_version(int* idata, int ilen, int* odata, int* olen)
{
printf("ver\n");
}
void app_start_read(int* idata, int ilen, int* odata, int* olen)
{
printf("read\n");
}
void app_handle_err(int* idata, int ilen, int* odata, int* olen)
{
printf("err\n");
}
结束:
上面和下面的代码都在vs2019环境测试通过。
使用了查表方式–其实就是结构体数组,这样的方式比传统方式就是逻辑更简单,是不是看不到if…else和switch…case这样的语句?
补充:
贴下传统方式的方便与查表方式作对比:
#include <string.h>
#include <stdio.h>
#include<stdint.h>
#pragma pack(1)
typedef enum {
BOOT_CODE = 0x40,
RETI_CODE = 0xF0,
ERRO_CODE = 0xF4
}packet_boot_code_t;
typedef enum {
VERSION = 0x02,
READ = 0x06
}packte_cmd_t;
typedef struct {
packet_boot_code_t boot_code;
int len;
packte_cmd_t cmd;
int data[64];
int check;
}packet_t;
void packet_parse(int *indata, int inlen,int *outdata, int *outlen)
{
packet_t* ppacket = (packet_t*)indata;
switch (ppacket->boot_code)
{
case BOOT_CODE:
if (VERSION == ppacket->cmd)
{
//根据命令 do something...
ppacket->boot_code = BOOT_CODE;
memcpy(outdata, indata, inlen*4);
*outlen = inlen;
}
default:
break;
}
}
//packet格式={boot len cmd data[] check}
void main(void)
{
int txbuff[5] = { 0x40,0x03,0x02,0xBC,0xbd };
int rxbuff[64];
int len=0;
packet_parse(txbuff, 5, rxbuff, &len);
}