映射表可以做什么?-CSDN博客

131 阅读2分钟

目录

1、解析数据协议

2、函数调用和跳转


本篇博文整理来源:物联网IoT技术,分享使用C语言映射表可以实现很不错的嵌入式软件开发思路。

主要包含两方面:映射表解析数据协议和映射表实现函数调用和跳转。

1、解析数据协议

解析UART、SPI等通信协议我们要设计很多解析函数。通常使用if...else if...else的结构拆解协议串,映射表的方式让你大开眼界。

首先定义数据结构,如下所示:

typedef struct 
{
    char CMD[CMDLen];
    unsigned char (*cmd_operate)(char *data);
}Usart_Tab;

定义指令、函数映射表,如下所示:

static const Usart_Tab InstructionList[CMDMax]=
{
    {"PWON",PowOn},
    {"PWOFF",PowOff},
    {"HDCP",HdcpOnOff},
    {"/V",QueryKaVersion},
    {"EDIDUpgrade",UpdataEDID},
    {"Psave",Psave},
    {"Precall",Precall},
    {"Pclear",Pclear},
};

 解析函数实现,如下所示:

unsigned char DataAnalysis(char *buf)
{
  unsigned char i,Result;
  char *NEXT=NULL;
  for(i=0;i<CMDMax;i++)
  {
    NEXT=StrCmp(buf,(char*)InstructionList[i].CMD);

    if(NEXT!=NULL)
    {
      Result=InstructionList[i].cmd_operate(NEXT);
    }
  }

  return Result;
}

2、函数调用和跳转

写逻辑功能或者状态机时,通常我们直接调用函数名实现跳转,这种方式在阅读代码时,程序的可读性和关联性就没那么好理解了。可以使用映射表来定义函数的调用和跳转方式。

首先定义菜单枚举,如下所示:

typedef enum
{
  stage1=0,
  stage2,
  stage3,
  stage4,
  stage5,
  stage6,
  stage7,
  stage8,
  stage9,
}SCENE;

定义数据结构,如下所示:

typedef struct {
  void (*current_operate)(); //当前场景的处理函数
  SCENE Index;               //当前场景的标签
  SCENE Up;                  //按下Up键跳转的场景
  SCENE Down;                //按下Down键跳转的场景
  SCENE Right;               //按下Left键跳转的场景
  SCENE Left;                //按下Right键跳转的场景
}STAGE_TAB;

定义函数映射表,如下所示:

STAGE_TAB stage_tab[]={
  #.    operate       Index    Up     Down    Left   Right   
  {Stage1_Handler,  stage1,  stage4,  stage7,  stage3, stage2},
  {Stage2_Handler,  stage2,  stage5,  stage8,  stage1, stage3},
  {Stage3_Handler,  stage3,  stage6,  stage9,  stage2, stage1},
  {Stage4_Handler,  stage4,  stage7,  stage1,  stage6, stage5},
  {Stage5_Handler,  stage5,  stage8,  stage2, stage4,  stage6},
  {Stage6_Handler,  stage6,  stage9,  stage3, stage5,  stage4},
  {Stage7_Handler,  stage7,  stage1,  stage4, stage9,  stage8},
  {Stage8_Handler,  stage8,  stage2,  stage5, stage7,  stage9},
  {Stage9_Handler,  stage9,  stage3,  stage6, stage8,  stage7},
};

定义两个变量保存当前场景和上一个场景,如下所示:

char current_stage=stage1;
char prev_stage=current_stage;

按下Up按键,跳转到指定场景current_stage的值根据映射表改变,如下所示:

current_stage =stage_tab[current_stage].Up;

场景改变后,根据映射表执行相应的函数Handler,如下所示:

if(current_stage!=prev_stage)
{
  stage_tab[current_stage].current_operate();
  prev_stage=current_stage;
}