该部分主要实现命令解释器,该解释器读取串口交互中的命令输入,解析,然后调用相应的操作。
主要内容
命令解释器的实现较为简单,流程简单归纳为:
- 打印命令提示符
- 读取一行字符串
- 解析命令,执行操作,必要时打印结果
重点难点
该设计中使用了两个C库函数:strstr, strtok,这两个函数的说明如下。
strtok说明
从串口中读取的是一行字符串,借助该函数中可以命令行进行解析,分割出命令、参数1、参数2等。
函数原型为:char * strtok ( char * str, const char * delimiters );
该函数会对字符串进行逐个扫描,然后分解为一个个子串。分解的依据为任何包含在delimiters字符数组中的字符。以” ab cd e “为例,可以看到字符串中空白符为” “,所以只需要对delimiters设置为仅包含’ ‘的数组。
- 第一次调用时,向str传递一个字符串,函数会进行扫描,扫描到第一个不在delimiters中的字符。具体来说,对” ab cd e “扫描,开头有几个’ ‘,该字符在delimiters数组中,所以会扫描到’a’开头,然后将’a’处地址返回。
- 之后的每次调用, str传递NULL进去,无需再传递原字符串,因为该函数内部会自动记录上次扫描的位置和状态。扫描时,则会继续从上次获得的位置,’a’处开始继续扫,当遇到一个在delimiters的字符串后(如’ ‘),认为上一个字符串结束。然后再继续往下扫,扫描到一个不在delimiters的字符(’c’),认为一个新字符串开始,然后将’c’的地址返回。
这样通过连续不断地调用,就能将字符串分解为一个个小的子串,” ab cd e “分解为”ab”, “cd”, “e”。
注意:
- 每次调用该函数都会对原始字符串str进行修改,所以这个被字符串不能位于不可写的存储区,如flash
- 该函数非线程安全。由于函数内部有记录上次扫描的结果,所以多个任务同时调用该函数时,该内部状态就可能被多个任务同时修改,造成冲突。如果有多个任务调用,需要使用strtok_r,由任务自行提供状态记录变量。
提供一个简单的示例strtok,也可直接看课程的使用示例:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
输出:
Splitting string "- This, a sample string." into tokens:
This
a
sample
string
strstr说明
在使用strtok解析命令串后,有时需要判断命令是什么,这时就需要使用到比较字符串。字符串的比较,可以使用的strcmp/strncmp,不过课程中所用的是strstr。
函数原型:const char * strstr ( const char * str1, const char * str2 );
功能:在str1中查找子串str2,并返回其起始位置;如果str2不在str1中,返回NULL
该函数区别于strcmp之处在于:strcmp仅能从字符串开始处比较,判断是是否相同。strstr不限定起始位置查找,返回出现的起始位置。
可见在这门课程中的应用,如果使用strcmp,比较更严格些,只能从开始处比较;使用strstr则不那么严格。
应用示例,来源strstr:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
strncpy (pch,"sample",6);
puts (str);
return 0;
}
输出:This is a sample string