一个简单的通用命令工具(可以使用串口或其它的任意通信接口)
时间:2019-07-10 11:10:01
手机看文章
扫描二维码
随时随地手机看文章
[导读]一直以来都是使用串口进行调试,非常方便,最近将命令工具进行了重新,将支持的命令与通信接口,处理等进行了分离,可移植性更强,并且不依赖通信接口,可以使用串口,网口,433等等通信接口,只需要实现一个pr
一直以来都是使用串口进行调试,非常方便,最近将命令工具进行了重新,将支持的命令与通信接口,处理等进行了分离,可移植性更强,并且不依赖通信接口,可以使用串口,网口,433等等通信接口,只需要实现一个printf类似的函数即可,因为串口是字符流,不像其它通信接口,一次传输一个块,因此在使用非串口的时候,建议发送的时候将数据用sprntf缓存到一个buff中,一次传输。
//sys_cmd.c
/*************************************************************************************************************
* 文件名: sys_cmd.c
* 功能: 自定义的系统命令接口
* 作者: cp1300@139.com
* 创建时间: 2014-06-07
* 最后修改时间: 2018-01-14
* 详细: 分离底层,将命令缓冲区与接口句柄进行分离,并且命令可以自行控制添加,增加命令是否显示状态
*************************************************************************************************************/
#include "SYSTEM.H"
#include "sys_cmd.h"
#include "string.h"
//命令缓冲区是否初始化ID
#define SYS_CMD_BUFF_INIT_ID 0x86877F9D
//管理密码状态
#define PASSWORD_STR "123456"
static u32 sg_PASSWORD_HASH=0;
u32 BKDRHash(const char *str); //BKDR 哈希算法
void SYS_CMD_Help(SYS_CMD_HANDLE *pHandle, char *pStr); //帮助命令
void SYS_CMD_Exit(SYS_CMD_HANDLE *pHandle, char *pStr); //退出命令
//支持的命令定义
const SYS_CMD_TYPE CMD_GET_HELP = {"?", SYS_CMD_Help, "tt帮助", TRUE}; //帮助
const SYS_CMD_TYPE CMD_EXIT = {"EXIT", SYS_CMD_Exit, "tt退出,再次输入需要密码", TRUE}; //退出登录
/*************************************************************************************************************************
*函数 : void SYS_CMD_Init(SYS_CMD_BUFF_TYPE *pCmdBuff)
*功能 : 初始化系统命令(会初始化系统命令缓冲区,并添加帮助命令)
*参数 : pCmdBuff:系统命令缓冲区
*返回 : 无
*依赖 : 无
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 :
*************************************************************************************************************************/
void SYS_CMD_Init(SYS_CMD_BUFF_TYPE *pCmdBuff)
{
if(sg_PASSWORD_HASH == 0) sg_PASSWORD_HASH = BKDRHash(PASSWORD_STR); //初始化密码的哈希值
pCmdBuff->CmdCount = 0; //清空命令
pCmdBuff->InitId = 0; //初始化为无效状态
SYS_CMD_Add(pCmdBuff, &CMD_GET_HELP); //添加帮助命令
SYS_CMD_Add(pCmdBuff, &CMD_EXIT); //添加退出命令
}
/*************************************************************************************************************************
*函数 : bool SYS_CMD_Add(SYS_CMD_BUFF_TYPE *pCmdBuff, const SYS_CMD_TYPE *pCmd)
*功能 : 添加一个命令到命令缓冲区中
*参数 : pCmdBuff:当前使用的命令缓冲区指针;pCmd:当前要添加的命令
*返回 : TRUE:添加成功;FALSE:添加失败
*依赖 : 无
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 : 用于添加并初始化命令缓冲区
*************************************************************************************************************************/
bool SYS_CMD_Add(SYS_CMD_BUFF_TYPE *pCmdBuff, const SYS_CMD_TYPE *pCmd)
{
if(pCmdBuff->InitId != SYS_CMD_BUFF_INIT_ID) //没有被初始化过
{
pCmdBuff->CmdCount = 0; //命令数量清零
pCmdBuff->InitId = SYS_CMD_BUFF_INIT_ID; //初始化ID有效
}
if(pCmdBuff->CmdCount >= SYS_MAX_CMD_COUNT) return FALSE; //命令已经满了,无法添加了
pCmdBuff->CmdPointerBuff[pCmdBuff->CmdCount] = pCmd; //添加命令到命令缓冲区中
pCmdBuff->CmdBKDHashBuff[pCmdBuff->CmdCount] = BKDRHash(pCmd->pCmdStr); //计算当前命令的哈希值
pCmdBuff->CmdCount ++; //命令数量增加
return TRUE;
}
/*************************************************************************************************************************
*函数 : void SYS_CMD_InterfaceInit(SYS_CMD_HANDLE *pHandle, int (*DataPrintf)(const char * format, ...))
*功能 : 初始化通讯句柄
*参数 : pHandle:句柄;DataPrintf:字符串打印接口
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 : 用于初始化底层通讯接口
*************************************************************************************************************************/
void SYS_CMD_InterfaceInit(SYS_CMD_HANDLE *pHandle, int (*DataPrintf)(const char * format, ...))
{
pHandle->pCmdBuff = NULL; //初始化命令缓冲区为无效状态
pHandle->DataPrintf = DataPrintf; //初始化通讯接口
pHandle->isInputPassword = FALSE; //密码输入状态无效
}
/*************************************************************************************************************************
*函数 : void SYS_CMD_Help(SYS_CMD_HANDLE *pHandle,char *pStr)
*功能 : 帮助命令
*参数 : pHandle:句柄;pStr:当前输入的命令字符串
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 : 用于初始化底层通讯接口
*************************************************************************************************************************/
void SYS_CMD_Help(SYS_CMD_HANDLE *pHandle,char *pStr)
{
u16 i;
u16 cnt = 0;
if(pHandle->pCmdBuff == NULL) return;
pHandle->DataPrintf("rnrn=============================命令列表=============================rn");
pHandle->DataPrintf("[编号]t[命令]ttt[功能]rnrn");
for(i = 0;i < ((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdCount;i ++)
{
if(((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdPointerBuff[i]->isShow == TRUE) //需要显示才进行打印
{
cnt ++;
pHandle->DataPrintf(" %02dt%st%srn",cnt,((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdPointerBuff[i]->pCmdStr,((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdPointerBuff[i]->pFunExp);
}
}
pHandle->DataPrintf("===================================================================rn");
pHandle->DataPrintf("rn");
}
/*************************************************************************************************************************
*函数 : void SYS_CMD_Exit(SYS_CMD_HANDLE *pHandle,char *pStr)
*功能 : 退出命令
*参数 : pHandle:句柄;pStr:当前输入的命令字符串
*返回 : 无
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 : 用于退出命令,退出后下次必须输入密码才能使用
*************************************************************************************************************************/
void SYS_CMD_Exit(SYS_CMD_HANDLE *pHandle,char *pStr)
{
pHandle->isInputPassword = FALSE; //输入密码无效
pHandle->DataPrintf("[退出登录成功]:下次需要输入密码才能操作!rn");
}
/*************************************************************************************************************************
*函数 : bool SYS_CMD_Handle(SYS_CMD_HANDLE *pHandle, SYS_CMD_BUFF_TYPE *pCmdBuff, char *pStr)
*功能 : 系统命令处理
*参数 : pHandle:句柄;pCmdBuff:当前所使用的命令缓冲区;pStr:当前输入的命令字符串
*返回 : TRUE:命令有效;FALSE:无效的命令
*依赖 : 底层
*作者 : cp1300@139.com
*时间 : 2018-01-14
*最后修改时间 : 2018-01-14
*说明 : 用于核心的命令处理函数
*************************************************************************************************************************/
bool SYS_CMD_Handle(SYS_CMD_HANDLE *pHandle, SYS_CMD_BUFF_TYPE *pCmdBuff, char *pStr)
{
u8 len;
u8 i;
u32 CmdHash;
char *p;
if(pHandle == NULL || pCmdBuff == NULL || pStr == NULL) return FALSE;
pHandle->pCmdBuff = pCmdBuff; //记录当前的命令缓冲区指针
len = strlen(pStr);
//检测是否输入过密码
if(pHandle->isInputPassword==FALSE) //没有输入过密码
{
for(i = 0;i < len;i ++)
{
if((pStr[i]>='a') && (pStr[i]isInputPassword = TRUE; //密码输入成功
pHandle->DataPrintf("[密码正确]:可以继续操作!rn>");
return TRUE;
}
pHandle->DataPrintf("[密码错误]:请输入管理密码!rn>");
return FALSE;
}
pHandle->DataPrintf("%srn", pStr);
if(len > 200) //检测参数的长度
{
pHandle->DataPrintf("[错误]:命令超出长度(>(%d))!rn>",200);
return FALSE;
}
//检查命令的结束符-rn
for(i = 0;i < len;i ++)
{
if((pStr[i] == 'r')||((pStr[i] == 'n')))
{
pStr[i] = 0;
len = i;
if(len == 0)
{
pHandle->DataPrintf("rn>");
return FALSE;
}
break;
}
}
//检测是否含有非法字符
for(i = 0;i < len;i ++)
{
if((pStr[i] < 32) || (pStr[i] > 126))
{
pHandle->DataPrintf("[错误]:含有非法字符!rn>");
return FALSE;
}
if((pStr[i]>='a') && (pStr[i] CMD_PARAMETER_STR_LEN) //检测参数的长度
{
pHandle->DataPrintf("[错误]:命令参数超出长度(>(%d))!rn>",CMD_PARAMETER_STR_LEN);
return FALSE;
}
strcpy(pHandle->CmdPara,p); //复制参数
p[0] = ' '; //截断命令
}
else
{
pHandle->CmdPara[0] = 0; //命令没有参数
}
CmdHash = BKDRHash(pStr); //计算命令的哈希值
//uart_printf("[调试]:%s(0x%X)rn",pStr, CmdHash);
//循环查找命令
for(i = 0;i < ((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdCount;i ++)
{
if(CmdHash == ((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdBKDHashBuff[i]) //判断哈希值是否一样
{
//cmd_printf("[解析成功]:!rn>");
((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdPointerBuff[i]->CmdExe(pHandle, pHandle->CmdPara); //执行命令
break;
}
}
if(i == ((SYS_CMD_BUFF_TYPE *)pHandle->pCmdBuff)->CmdCount)
{
pHandle->DataPrintf("[错误]:不支持的命令!rn>");
return FALSE;
}
pHandle->DataPrintf(">");
return TRUE;
}
/*************************************************************************************************************************
*函数 : u32 SYS_CMD_StringToDec(char *pStr, u8 NumDigits)
*功能 : 将10进制样式字符串转换为整型数(必须保证完全为数字字符)
*参数 : pStr:字符串起始指针
* NumDigits:数字位数,10进制数字位数
*返回 : 转换后的数字
*依赖 : 无
*作者 : cp1300@139.com
*时间 : 2013-04-30
*最后修改时间 : 2018-01-14
*说明 : 比如字符串"1865"转换后为1865,位数为4位
必须保证完全为数字字符
*************************************************************************************************************************/
u32 SYS_CMD_StringToDec(char *pStr, u8 NumDigits)
{
u32 temp;
u32 DEC = 0;
u8 i;
u8 j;
NumDigits = (NumDigits > 10) ? 10 : NumDigits; //最大支持10位10进制数
for(i = 0;i < NumDigits;i ++)
{
temp = pStr[i] - '0';
if(temp > 9) //只能是数字范围
return 0;
for(j = 1;j < (NumDigits - i);j ++)
{
temp *= 10;
}
DEC += temp;
}
return DEC;
}
// BKDR Hash Function
//BKDR 哈希算法
u32 BKDRHash(const char *str)
{
u32 seed = 131; // 31 131 1313 13131 131313 etc..
u32 hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
//return (hash & 0x7FFFFFFF);
return hash;
}
//测试数据是否全部为数字以及空格
bool isStrNumAndSpc(char *pStr, u8 len,u8 SpcNum)
{
u8 i;
u8 n = 0;
for(i = 0;i < len;i ++)
{
if((pStr[i] < '0')||(pStr[i] > '9'))
{
if(pStr[i] == ' ')
{
n ++;
if(n > SpcNum) return FALSE; //空格过多
}
else
return FALSE;
}
}
return TRUE;
}
//测试数据是否全部为数字
bool isStrNum(char *pStr, u8 len)
{
u8 i;
for(i = 0;i < len;i ++)
{
if((pStr[i] < '0')||(pStr[i] > '9'))
{
return FALSE;
}
}
return TRUE;
}
//测试数据是否全部为字母,数字,'.'
bool isStrAndNum(char *pStr, u8 len)
{
u8 i;
for(i = 0;i < len;i ++)
{
if(((pStr[i] >= '0')&&(pStr[i] = 'A')&&(pStr[i] = 'a')&&(pStr[i] <= 'z'))||(pStr[i] == '.'))
{
}
else
{
return FALSE;
}
}
return TRUE;
}/*************************************************************************************************************
* 文件名: sys_cmd.h
* 功能: 自定义的系统命令接口
* 作者: cp1300@139.com
* 创建时间: 2014-06-07
* 最后修改时间: 2018-01-14
* 详细: 分离底层,将命令缓冲区与接口句柄进行分离,并且命令可以自行控制添加,增加命令是否显示状态
*************************************************************************************************************/
#ifndef __SYS_CMD_H_
#define __SYS_CMD_H_
#include "system.h"
#define CMD_PARAMETER_STR_LEN 24 //限制命令的参数长度,过长会占用过多的内存,请按照实际设置
#define CMD_DEFAULT_COUNT 10 //默认的支持的命令数量,实际数量由SYS_CMD_COUNT决定
#ifndef SYS_CMD_COUNT //系统文件中定义了数量
#define SYS_MAX_CMD_COUNT SYS_CMD_COUNT //最大支持的命令数量
#else
#define SYS_MAX_CMD_COUNT CMD_DEFAULT_COUNT //最大支持的命令数量
#endif //SYS_CMD_COUNT
//通信句柄
typedef struct
{
int (*DataPrintf)(const char * format, ...); //数据打印接口-尽可能将数据集中到一起进行打印输出
void *pCmdBuff; //当前使用的命令缓冲区指针-由于互相包含,因此这个地方将指针声明为空指针
char CmdPara[CMD_PARAMETER_STR_LEN+4]; //命令参数缓冲区
bool isInputPassword; //用于指示是否输入密码
}SYS_CMD_HANDLE;
//系统命令结构
typedef struct
{
const char *pCmdStr; //命令字符串
void(*CmdExe)(SYS_CMD_HANDLE *pHandle, char *); //命令执行函数
const char *pFunExp; //功能说明
bool isShow; //是否显示(可以影藏一些特殊命令)
}SYS_CMD_TYPE;
//系统命令集合定义
typedef struct
{
u32 InitId; //用于指示是否进行了初始化
const SYS_CMD_TYPE *CmdPointerBuff[SYS_MAX_CMD_COUNT]; //系统命令指针集合
u32 CmdBKDHashBuff[SYS_MAX_CMD_COUNT]; //系统命令的哈希值
u8 CmdCount; //当前支持的系统命令数量
}SYS_CMD_BUFF_TYPE;
//相关命令接口
void SYS_CMD_Init(SYS_CMD_BUFF_TYPE *pCmdBuff); //初始化系统命令(会初始化系统命令缓冲区,并添加帮助命令)
bool SYS_CMD_Add(SYS_CMD_BUFF_TYPE *pCmdBuff, const SYS_CMD_TYPE *pCmd);//添加一个命令到命令缓冲区中
void SYS_CMD_InterfaceInit(SYS_CMD_HANDLE *pHandle, int (*DataPrintf)(const char * format, ...)); //初始化通讯句柄
bool SYS_CMD_Handle(SYS_CMD_HANDLE *pHandle, SYS_CMD_BUFF_TYPE *pCmdBuff, char *pStr); //系统命令处理
//工具命令接口
u32 SYS_CMD_StringToDec(char *pStr, u8 NumDigits); //字符串转换为整形数
bool isStrNumAndSpc(char *pStr, u8 len,u8 SpcNum); //测试数据是否全部为数字以及空格
bool isStrAndNum(char *pStr, u8 len); //测试数据是否全部为字母,数字,'.'
bool isStrNum(char *pStr, u8 len); //测试数据是否全部为数字
#endif //__SYS_CMD_H_
//命令的实现,以RTC为例
//使能系统命令行
#if SYS_CMD_EN_
#include "sys_cmd.h"
#include "string.h"
const SYS_CMD_TYPE CMD_GET_TIME = {"TIME?", CMD_GetTime, "tt获取系统时间", TRUE};
const SYS_CMD_TYPE CMD_GET_DATE = {"DATE?", CMD_GetDate, "tt获取系统日期", TRUE};
const SYS_CMD_TYPE CMD_SET_TIME = {"TIME=", CMD_SetTime, "tt设置系统时间 如(12:32:54):TIME=12 32 54", TRUE};
const SYS_CMD_TYPE CMD_SET_DATE = {"DATE=", CMD_SetDate, "tt设置系统日期 如(2014 6 8):TIME=2014 6 8", TRUE};
//获取时间
void CMD_GetTime(SYS_CMD_HANDLE *pHandle,char *pStr)
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[获取时间成功]:%02d:%02d:%02drn",g_timer.hour, g_timer.min, g_timer.sec);
}
//获取日期
void CMD_GetDate(SYS_CMD_HANDLE *pHandle,char *pStr)
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[获取日期成功]:%04d-%02d-%02drn",g_timer.year, g_timer.month, g_timer.date);
}
//设置时间
void CMD_SetTime(SYS_CMD_HANDLE *pHandle,char *pStr)
{
u8 hour,min,sec;
u8 len;
char *p;
u8 num;
len = strlen(pStr); //获取长度
if(isStrNumAndSpc(pStr, len, 2) == FALSE)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
//小时
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
num = p - pStr;
if((num > 2) || (num == 0))
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
hour = SYS_CMD_StringToDec(pStr, num);
if(hour>23)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
//分钟
pStr = p+1;
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
num = p - pStr;
if((num > 2) || (num == 0))
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
min = SYS_CMD_StringToDec(pStr, num);
if(min>59)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
//秒钟
pStr = p+1;
num = strlen(pStr);
if((num > 2) || (num == 0))
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
sec = SYS_CMD_StringToDec(pStr, num);
if(sec>59)
{
pHandle->DataPrintf("[时间设置错误]:格式不对或非法参数!rn");
return;
}
if(RTC_SetTime(hour, min, sec) == FALSE)
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[时间设置失败]:%02d:%02d:%02drn",g_timer.hour, g_timer.min, g_timer.sec);
}
else
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[时间设置成功]:%02d:%02d:%02drn",g_timer.hour, g_timer.min, g_timer.sec);
}
}
//设置日期
void CMD_SetDate(SYS_CMD_HANDLE *pHandle,char *pStr)
{
u16 year;
u8 month, date;
u8 len;
char *p;
u8 num;
len = strlen(pStr); //获取长度
if(isStrNumAndSpc(pStr, len, 2) == FALSE)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
//年
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
num = p - pStr;
if((num > 4) || (num == 0))
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
year = SYS_CMD_StringToDec(pStr, num);
if(year>9999)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
//月
pStr = p+1;
p = strstr(pStr," "); //搜索空格
if(p == NULL)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
num = p - pStr;
if((num > 2) || (num == 0))
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
month = SYS_CMD_StringToDec(pStr, num);
if(month>12)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
//日
pStr = p+1;
num = strlen(pStr);
if((num > 2) || (num == 0))
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
date = SYS_CMD_StringToDec(pStr, num);
if(date>31)
{
pHandle->DataPrintf("[日期设置错误]:格式不对或非法参数!rn");
return;
}
if(RTC_SetDate(year, month, date) == FALSE)
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[日期设置失败]:%04d-%02d-%02drn",g_timer.year, g_timer.month, g_timer.date);
}
else
{
RTC_Get(); //更新时间
pHandle->DataPrintf("[日期设置成功]:%04d-%02d-%02drn",g_timer.year, g_timer.month, g_timer.date);
}
}
#endif //SYS_CMD_EN_//命令的声明
//使能系统命令行 #if SYS_CMD_EN_ #include "sys_cmd.h" #include "string.h" extern const SYS_CMD_TYPE CMD_GET_TIME; extern const SYS_CMD_TYPE CMD_GET_DATE; extern const SYS_CMD_TYPE CMD_SET_TIME; extern const SYS_CMD_TYPE CMD_SET_DATE; //获取时间 void CMD_GetTime(SYS_CMD_HANDLE *pHandle,char *pStr); //获取日期 void CMD_GetDate(SYS_CMD_HANDLE *pHandle,char *pStr); //设置时间 void CMD_SetTime(SYS_CMD_HANDLE *pHandle,char *pStr); //设置日期 void CMD_SetDate(SYS_CMD_HANDLE *pHandle,char *pStr); #endif //SYS_CMD_EN_
//需要实现的一个通信接口,我直接使用了printf,如果需要使用其它接口,需要自己实现一个 int DataPrintf(const char * format, ...) 函数,结构与printf一样,可以网上找找-下面是一个例子
//调试信息输出-注意单次长度不要超过5K
int Printf(const char * format, ...)
{
DWORD len;
va_list ap;
va_start(ap, format);
len = vsnprintf(buff, format, ap);
va_end(ap);
SendData((BYTE *)buff, len);
return len;
}//命令的初始化与添加命令
//初始化系统命令
SYS_CMD_HANDLE g_SysCmdHandle; //系统命令句柄 SYS_CMD_BUFF_TYPE g_SysCmdBuff; //系统命令缓冲区
SYS_CMD_Init(&g_SysCmdBuff);//初始化系统命令(会初始化系统命令缓冲区,并添加帮助命令) SYS_CMD_InterfaceInit(&g_SysCmdHandle, printf);//初始化通讯句柄 //添加RTC相关的命令支持 SYS_CMD_Add(&g_SysCmdBuff, &CMD_GET_TIME); SYS_CMD_Add(&g_SysCmdBuff, &CMD_GET_DATE); SYS_CMD_Add(&g_SysCmdBuff, &CMD_SET_TIME); SYS_CMD_Add(&g_SysCmdBuff, &CMD_SET_DATE);
//命令的处理,收到数据后调用SYS_CMD_Handle
cnt1 = UARTx_GetRxCnt(UART_PRINTF_CH);
OSTimeDlyHMSM(0,0,0,20);
cnt2 = UARTx_GetRxCnt(UART_PRINTF_CH);
if((cnt1 > 0) && (cnt1 == cnt2))
{
buff[cnt1] = 0;
SYS_CMD_Handle(&g_SysCmdHandle, &g_SysCmdBuff, (char *)buff); //命令处理
UARTx_ClearRxCnt(UART_PRINTF_CH);
}
else
{
OSTimeDlyHMSM(0,0,0,100);;
}在测试时使用起来会非常方便,无需上位机支持,比如设置一些参数,调用xmodem下载升级等操作会非常方便,如下图所示





