通过嵌入式c中的RS232处理ASCII命令

时间:2013-05-15 17:55:52

标签: c serial-port embedded

我的微控制器有一个RS232接口,带有一组预定义的命令。有几百个命令,例如PRESSURE 50可以设定压力为50; LIMIT 60可以设置为60的限制。

目前,这是使用一系列嵌套的switch语句处理的,但这似乎是一个不优雅的解决方案。

处理这些命令的建议/最有效/最可读的方法是什么? LUT会是最整洁的,但肯定会有很多空字符组合的空条目(不理想..)。

感谢任何想法..

2 个答案:

答案 0 :(得分:2)

  1. 运行时提案:

    使用排序数组struct {string,function pointer)

    我希望您的平台中提供qsort()bsearch()stdlib.h

  2. 设计时提案:

    正如评论所示,最好在设计时对数组初始化的条目进行排序。存在很多方法,从代码生成(豪华)到宏观处理(差)。

    宣言的建议,一对多:

    typedef unsigned char byte;
    
    typedef char commandId_t[40];
    
    typedef void (*commandHandler_t)( const byte * payload );
    
    typedef struct command_s {
       const commandId_t      commandId;
       const commandHandler_t handler;
    } command_t;
    
    static const command_t commands[] = {
    #include "sortedCommandInitializers"
    };
    

    文件sortedCommandInitializers{"command-name", function-name},的列表,可以按Makefile中的sort CommandInitializers.c > sortedCommandInitializers命令排序。

    对于make,它与其他任何依赖项一样:

    sortedCommandInitializers: CommandInitializers.c
        sort CommandInitializers.c > sortedCommandInitializers
    
    myProgram.o: myProgram.c myProgram.h sortedCommandInitializers
    

答案 1 :(得分:2)

曾经尝试过strnstr功能吗?它真的非常快。对于几百个单词,它可能比8或9个单独的strcmp()更快,其间有一些额外的代码来遍历一个树,并且需要更少的内存来存储。

我会尝试以下

a)建立一个命令列表并在开头放置最常见的命令,并为每个命令添加一个唯一的编号。

char command_names[] =

"PRESSURE 1"
"LIMIT 2"

;
int command_names_len = sizeof(command_names_str)

C编译器应该为您附加这些字符串,因此很容易将它们移动到另一个位置

b)添加的这些数字是函数指针数组的索引,每个函数应该具有相同的签名,当你允许某些函数有未使用的参数时,这可能是可能的吗? 即。

/* just an example */
void (command*)(int a, int b, int c, int d);

void command_pressure (int a, int b, int c, int d) { }
void command_limit(int a, int b, int c, int d) { }

command commands[] =
( /*notused*/ NULL

, /*     1 */ command_pressure
, /*     2 */ command_limit

);

这两个列表在视觉上也会相互匹配,使控制和维护变得更容易。注释中的数字仅用于帮助,并且应与大字符串构建中的数字与函数名称

匹配

然后处理传入的命令是字符串格式非常简单

char search_command[20]; /* or whatever the longest command name is */
char* position_of_command = NULL;
int number_of_command = -1;

strncpy( search_command, incomming_command, sizeof(search_command) );
strcat( search_command, " " );  /* must end with blank */

command_position = strnstr( command_names, search_command, command_names_len );
if( command_position != NULL ) {
  position_of_command += strlen(s earch_command) ; /* at beginning of number */
  number_of_command = atoi( position_of_command );
}

if( number_of_command > 0 ) {
  (*commands[number_of_command])(a,0,0,d);
} else {
  /* unknown */
}

前段时间我写过普通的旧C,所以它可能包含语法错误,但这就是想法。

优点:

a)小内存打印:没有额外的指针或其他额外的结构开销来查找命令,很少有编程行

b)维护简单:它是“桌子”组织的

c)最常用的命令处理速度最快!

缺点:

a)请记住,不允许以相同字符串结尾的命令。可以通过在名称的开头添加空格来解决,也可以在search_command处添加空格。即。

" PRESSURE 1"
" LIMIT 2"