OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3074|回复: 29

下位机针对命令帧查找执行函数,代码方法求助。

[复制链接]

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
发表于 2019-4-19 13:39:36 | 显示全部楼层 |阅读模式
1.问题描述:
我有这样一种想法,下位机分为很多个不同的模块,每个模块有自己的函数,如下代码数组所示,
UNIT1,UNIT2,UNIT3它们代表着不同的单元,每个单元下有不同的命令,Fun1~Fun18分别是它们的命令执行函数。
想通过上位机发送命令帧到下位机,命令帧包含了单元以及命令等信息,每个命令帧都对应一条执行函数.
调用FindExecFuncUnit去查找该条命令对应的执行函数。针对这样的情景,以下代码这是我的一种实现想法,
小伙伴们觉得这种写法怎么样,可不可取?或者有没有经验的前辈有更好的实现方式呢?
还麻烦给点建议或者有现成的框架可以参考一下,谢谢!
typedef struct _CMD_UNIT
{
   LOGIC_UNIT UNIT_NO;              
   uint8_t cmd;                           
   uint8_t subCmd;                  
   ParseRst     parseCmdFunc;      
}CMD_UNIT;

CMD_UNIT arr[][4] =
{
    {UNIT1, CMD1, SUBCMD1, Fun1},
    {UNIT1, CMD1, SUBCMD2, Fun2},
    {UNIT1, CMD1, SUBCMD3, Fun3},
    {UNIT1, CMD1, 0x00,    NULL},   //0x01主命令下没有这个命令

    {UNIT1, CMD2, SUBCMD1, Fun4},
    {UNIT1, CMD2, SUBCMD2, Fun5},
    {UNIT1, CMD2, SUBCMD3, Fun6},
    {UNIT1, CMD2, 0x00,    NULL},
    {UNIT1, 0x00, 0x00,    NULL},   //UNIT1单元下没有这个主命令
    /***********************************************/
    {UNIT2, CMD1, SUBCMD1, Fun7},
    {UNIT2, CMD1, SUBCMD2, Fun8},
    {UNIT2, CMD1, SUBCMD3, Fun9},
    {UNIT2, CMD1, 0x00,    NULL},

    {UNIT2, CMD2, SUBCMD1, Fun10},
    {UNIT2, CMD2, SUBCMD2, Fun11},
    {UNIT2, CMD2, SUBCMD3, Fun12},
    {UNIT2, CMD2, 0x00,    NULL},
    {UNIT2, 0x00, 0x00,    NULL},
    /***********************************************/
    {UNIT3, CMD1, SUBCMD1, Fun13},
    {UNIT3, CMD1, SUBCMD2, Fun14},
    {UNIT3, CMD1, SUBCMD3, Fun15},
    {UNIT3, CMD1, 0x00,    NULL},

    {UNIT3, CMD2, SUBCMD1, Fun16},
    {UNIT3, CMD2, SUBCMD2, Fun17},
    {UNIT3, CMD2, SUBCMD3, Fun18},
    {UNIT3, CMD2, 0x00,    NULL},
    {UNIT3, 0x00, 0x00,    NULL},
    /***********************************************/
    {0x00, 0x00, 0x00,     NULL} //0x00未知单元
};


ParseRst FindExecFuncUnit(PSTD_CMD pCmd)
{
    PCMD_FUNCTION_INFO pInfo = (PCMD_FUNCTION_INFO)pCmd;
    uint8_t i;

    for(i = 0; pInfo->Unit != 0x00; i++)               
    {
        if((pInfo->Cmd == arr[i][1]) && pInfo->SubCmd == arr[i][2]))
        {
            if((arr[i][1] != 0x00) && (arr[i][2] != 0x00))
                return return arr[i][3];
            else
                return NULL;
        }
    }

    return NULL;
}

没有脑袋
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-19 13:40:46 | 显示全部楼层
忘记悬赏金钱了,大家忽略这条帖子,我另开一条悬赏帖子
没有脑袋
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-4-19 15:55:11 | 显示全部楼层
正点原子的USMART不是?
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-19 16:43:48 | 显示全部楼层
nashui_sx 发表于 2019-4-19 15:55
正点原子的USMART不是?

我还不知道USMART是什么,框架吗?程序?
没有脑袋
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-4-19 16:51:45 | 显示全部楼层
美丽的时光机器 发表于 2019-4-19 16:43
我还不知道USMART是什么,框架吗?程序?

那你随便找个开发板的视频看看就知道了,典型的闭门造车你这是
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-19 17:42:37 | 显示全部楼层
nashui_sx 发表于 2019-4-19 16:51
那你随便找个开发板的视频看看就知道了,典型的闭门造车你这是

好吧  你年纪大你说什么都是对的
没有脑袋
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-4-19 17:46:37 | 显示全部楼层
美丽的时光机器 发表于 2019-4-19 17:42
好吧  你年纪大你说什么都是对的

我错了
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-19 17:47:39 | 显示全部楼层

错误无效~~~
没有脑袋
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-4-19 19:06:22 | 显示全部楼层
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-19 20:03:42 | 显示全部楼层
我觉得你把简单的问题复杂化了.....
设值 UINT1=0;UINT2=6;CMD1=0;CMD2=3;SUBCMD1=1;SUBCMD2=2;SUBCMD3=3;
将上位机发来的单元号、命令和子命令加起来....就得到了你所需要调用的函数.....(题目没看懂,程序看懂了)
我觉得楼主是一种可以靠脸吃饭,却非要靠才华的人
猪猪熊呢?
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-19 20:04:30 | 显示全部楼层
323232 发表于 2019-4-19 20:03
我觉得你把简单的问题复杂化了.....
设值 UINT1=0;UINT2=6;CMD1=0;CMD2=3;SUBCMD1=1;SUBCMD2=2;SUBCMD3=3; ...

UINT3=12;
猪猪熊呢?
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 08:27:36 | 显示全部楼层
323232 发表于 2019-4-19 20:03
我觉得你把简单的问题复杂化了.....
设值 UINT1=0;UINT2=6;CMD1=0;CMD2=3;SUBCMD1=1;SUBCMD2=2;SUBCMD3=3; ...

为啥要加起来???好像这样做这样不直观明了
没有脑袋
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 08:29:34 | 显示全部楼层
323232 发表于 2019-4-19 20:03
我觉得你把简单的问题复杂化了.....
设值 UINT1=0;UINT2=6;CMD1=0;CMD2=3;SUBCMD1=1;SUBCMD2=2;SUBCMD3=3; ...

集美貌与才华与一身的。。。媛儿~~
没有脑袋
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 10:59:03 | 显示全部楼层
美丽的时光机器 发表于 2019-4-22 08:29
集美貌与才华与一身的。。。媛儿~~

上位机应该就是发你这些单元拉 命令号 子命令号这些是么?那就按照事先定义好的这些,直接加起来不就是你要调用的任务号了么.....难道我理解错你的题目了吗
猪猪熊呢?
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 11:01:28 | 显示全部楼层
323232 发表于 2019-4-22 10:59
上位机应该就是发你这些单元拉 命令号 子命令号这些是么?那就按照事先定义好的这些,直接加起来不就是你 ...

然后写一个有任务名字的一维数组,直接把任务号当做参数输入,也能达到效果吧....我是这么想的
猪猪熊呢?
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 11:02:32 | 显示全部楼层
323232 发表于 2019-4-22 10:59
上位机应该就是发你这些单元拉 命令号 子命令号这些是么?那就按照事先定义好的这些,直接加起来不就是你 ...

感觉代码不直观~
没有脑袋
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 11:07:52 | 显示全部楼层
323232 发表于 2019-4-22 11:01
然后写一个有任务名字的一维数组,直接把任务号当做参数输入,也能达到效果吧....我是这么想的

所以总体思路上还是跟我的差不多对吧  都是下发,查找,返回函数指针
没有脑袋
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 14:44:40 | 显示全部楼层
美丽的时光机器 发表于 2019-4-22 11:07
所以总体思路上还是跟我的差不多对吧  都是下发,查找,返回函数指针

是的,但是代码量肯定少很多
猪猪熊呢?
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 14:45:45 | 显示全部楼层
323232 发表于 2019-4-22 14:44
是的,但是代码量肯定少很多

甚至不用查找,加起来就是数组的序号了
猪猪熊呢?
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 14:52:17 | 显示全部楼层
#DEFINE UINT1 0
#DEFINE UINT2 6
#DEFINE UINT3 12
#DEFINE CMD1  0
#DEFINE CMD2  3
#DEFINE SUBCMD1 1
#DEFINE SUBCMD2 2
#DEFINE SUBCMD3 3

uint8 Func_Num[18] ={func1,func2,func3,func4,func5,func6,func7,func8,func9,func10,func11,func12,func13,func14,func15,func16,func17,func18};
return Func_Num[UINT+CMD+SCMD-1];

上位机下发数据给UINT CMD SCMD附上面define的值,是这意思么?所以要是我理解错了,,那我就谢罪吧
猪猪熊呢?
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 16:04:06 | 显示全部楼层
323232 发表于 2019-4-22 14:52
#DEFINE UINT1 0
#DEFINE UINT2 6
#DEFINE UINT3 12

大同小异啦~~~还有没有其他不同的框架贡献一下呀~
没有脑袋
回复 支持 反对

使用道具 举报

15

主题

317

帖子

0

精华

高级会员

Rank: 4

积分
863
金钱
863
注册时间
2015-2-12
在线时间
354 小时
发表于 2019-4-22 16:16:11 | 显示全部楼层
我觉得,这个程序架构挺好的。
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-4-22 16:33:10 | 显示全部楼层
csmjmcc 发表于 2019-4-22 16:16
我觉得,这个程序架构挺好的。

我也觉得超棒的
猪猪熊呢?
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-22 18:45:33 | 显示全部楼层
csmjmcc 发表于 2019-4-22 16:16
我觉得,这个程序架构挺好的。

好吧好吧~~~
没有脑袋
回复 支持 反对

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-4-22 22:11:30 | 显示全部楼层
是搞复杂了,但思路是可行的,除了函数作为传送命令这一条, 不应该也可以直接把函数放在命令里的, 因为所谓函数, 它是一个地址, 这个地址是编译器在编译时动态生成的, 你让上位机把函数的地址发给下位机, 那就是说每次下位机编译后, 你都要把函数的地址抄一份给上位机。

这类结构, 通常是以enum作为函数对应的index, 而命令的函数定义成一函数数组。
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-23 08:37:01 | 显示全部楼层
edmund1234 发表于 2019-4-22 22:11
是搞复杂了,但思路是可行的,除了函数作为传送命令这一条, 不应该也可以直接把函数放在命令里的, 因为所 ...

哦哦  你是说解析函数的参数对吧ParseRst FindExecFuncUnit(PSTD_CMD pCmd),参数类型写的有问题,不应该带有函数地址信息的,正常来说命令帧信息也不应该包含地址,我要换一个参数类型。大佬一眼指出了错误,谢谢啦~
没有脑袋
回复 支持 反对

使用道具 举报

17

主题

587

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4467
金钱
4467
注册时间
2013-6-27
在线时间
565 小时
发表于 2019-4-23 09:03:16 | 显示全部楼层
本帖最后由 DongInker 于 2019-4-23 09:18 编辑

串口信息交互调试是最普遍最有效的调试方式,可用实时查看设置各种单片机函数。在调试阶段及问题出现时带来极大的便利。
之前有看到FreeRTOS CLT好像就是构建类似linux命令交互调试的
可用参考一个51单片机串口设置处理解析
1 接收串口到缓存
2 接收到回车开始处理
3 大小写转换等
4 调用各种类型解析函数
(毕竟一个已知的函数所用参数类型是已知的 可用使用scanf函数解析参数 )

       时间设置  (settime 9 12 32)
        if(strcmp(pComDbg.Revdata,"settime") == NULL)
                {
                pComDbg.Cnt = SearchChar(pComDbg.Revdata,'\0')+1;
                if(TypeU8(pComDbg.Revdata + pComDbg.Cnt,pComDbg.Param8) == FALSE)
                        return FALSE;
                if(TypeU8(pComDbg.Revdata+pComDbg.Cnt,pComDbg.Param8+1) == FALSE)
                        return FALSE;
                if(TypeU8(pComDbg.Revdata+pComDbg.Cnt,pComDbg.Param8+2) == FALSE)
                        return FALSE;
                if(EndIsEnter(pComDbg.Revdata + pComDbg.Cnt -1) == FALSE)
                        return FALSE;
       
                if(pComDbg.Param8[1] < 60 && pComDbg.Param8[2] < 59)
                        {
                        SysParam.SysHours        = pComDbg.Param8[0];
                        SysParam.SysMinutes = pComDbg.Param8[1];
                        SysParam.SysSeconds = pComDbg.Param8[2];
                        DPRINTF(("时间:%b002u:%b002u:%b002u\r\n",SysParam.SysHours,SysParam.SysMinutes,SysParam.SysSeconds));
                        return TRUE;
                        }

一个浮点参数解析( beatsfix 1.2343 )
        if(strcmp(pComDbg.Revdata,"beatsfix") == NULL)
                {
                pComDbg.Cnt = SearchChar(pComDbg.Revdata,'\0')+1;
                if(TypeFloat(pComDbg.Revdata + pComDbg.Cnt,&pComDbg.ParamF[0]) == FALSE)
                        return FALSE;
                if(EndIsEnter(pComDbg.Revdata + pComDbg.Cnt -1) == FALSE)
                        return FALSE;

                SysParam.SysBeatsFix = pComDbg.ParamF[0];
                DPRINTF(("SysBeatsFix <= %f\r\n",SysParam.SysBeatsFix));
                return TRUE;
                }




让我们的思维驾驭在电的速度之上!
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-23 11:13:08 | 显示全部楼层
DongInker 发表于 2019-4-23 09:03
串口信息交互调试是最普遍最有效的调试方式,可用实时查看设置各种单片机函数。在调试阶段及问题出现时带来 ...

嗯思路大体是一致的  参考下~
没有脑袋
回复 支持 反对

使用道具 举报

3

主题

259

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2317
金钱
2317
注册时间
2016-12-2
在线时间
354 小时
发表于 2019-4-23 11:46:48 | 显示全部楼层
这个类似SCSI Command.
可以在U盘看到类似的协定
如果说要参考, 是可以看U盘的代码
不过也不用太拘泥别人怎么实作, 可以运行的code, 就是好code, 自己写得开心就好
回复 支持 反对

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2019-4-24 08:33:42 | 显示全部楼层
sammy902583 发表于 2019-4-23 11:46
这个类似SCSI Command.
可以在U盘看到类似的协定
如果说要参考, 是可以看U盘的代码

好像U盘用的回调函数,之前有看过一点~~
没有脑袋
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-24 21:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表