产品很多配置信息需要后期进行配置,配置交互最好的方式之一是上位机通过串口与开发板进行交互来完配置。这里我准备引入AT指令来进行配置。
我采用串口中断+定时器中断来实现了串口的接收,下面进行AT指令框架的创建。
首先定义了指令结构:
- typedefenum{
- AT_CMD_TEST=0, /* 测试指令 */
- AT_CMD_SETRTC,/* 设置RTC指令 */
- AT_END
- }AT_Cmd;
- typedefunsignedchar (*pFunc)(unsignedchar*ptr, unsignedchar len);
- typedefstruct
- {
- AT_Cmdcmd; /* 指令序号 */
- unsignedchar*str; /* 指令内容 */
- pFunccb; /* 指令执行 */
- }AT_cmd_func;
- /* AT指令表 */
- constAT_cmd_funcat_cmd_func[]= {
- {AT_CMD_TEST, "AT", at_cmd_test},
- {AT_CMD_SETRTC, "AT+SETRTC=", at_cmd_setrtc},
- {AT_END, NULL, NULL}
- };
再次我定义了执行指令的函数 1个是AT测试,再有一条是设置RTC的指令(具体还没有实现,只是定义了一条打印指令);
- /* 指令执行函数 */
- unsignedcharat_cmd_test(unsignedchar*p, unsignedcharlen){
- AT_DEBUG_INFO("AT+OK\r\n");
- return0;
- }
- unsignedcharat_cmd_setrtc(unsignedchar*p, unsignedcharlen){
- AT_DEBUG_INFO("setrtc\r\n");
- return0;
- }
最后我们进行指令解析,主要有两个函数,一个是检索指令表里是否存在指令,二个是解析指令,如果成果测执行相应的指令。
/* 查找指令表中对应的指令 */
- unsignedcharAT_cmd_search(unsignedchar*p, unsignedcharlen)
- {
- unsignedcharret=0;
- unsignedchar*pstr;
- unsignedchari, n;
- for(i=1; at_cmd_func[i].cmd!=AT_END; i++)
- {
- n=mstrlen(at_cmd_func[i].str);
- if(!mstrncmp(p, at_cmd_func[i].str, n)){
- ret=i;
- break;
- }
- }
- returnret;
- }
- /* AT指令解析 */
- unsignedcharat_cmd_parse(unsignedchar*p, unsignedcharlen){
- unsignedcharret=AT_SUCCESS;
- unsignedcharindex=0;
- unsignedcharn;
- if(len<4) {
- returnAT_ERR;
- }
- if((p[0] =='A') && (p[1] =='T') && (p[len-2] ==0x0D) && (p[len-1] ==0x0A)) {
- if(len==4) { /* 测试指令 */
- if(at_cmd_func[AT_CMD_TEST].cb!=NULL) {
- at_cmd_func[AT_CMD_TEST].cb(NULL, 0); /* 执行测试指令 */
- }
- }elseif(p[2] =='+') { /* 执行指令解析 */
- index=AT_cmd_search(p, len); /* 查找匹配的执行指令, 0-已匹配, !0-未匹配*/
- if(index) {
- if(at_cmd_func[index].cb!=NULL) {
- n=mstrlen(at_cmd_func[index].str);
- ret=at_cmd_func[index].cb(p+n, len-n); /* 执行对应的指令函数, p+n:将指令参数传输执行函数,len-n-2:指令参数有效长度 */
- }else {
- ret=AT_ERR_FUN_UNUSED; /* 没有可执行函数 */
- }
- }else {
- ret=AT_ERR_UNINVAL; /* 未找到匹配的指令 */
- }
- }else { /* 格式不匹配 */
- returnAT_ERR;
- }
- returnret;
- }
- }
测试:
我在接收到指令后执行at_cmd_parse 发送AT、AT+SETRTC=成功的返回需要的信息。
- [21:24:57.274]发→◇AT
- □
- [21:24:57.286]收←◆AT+OK
- [21:25:21.874]发→◇AT+SETRTC=23,7,11,22,11,09
- □
- [21:25:21.888]收←◆setrtc
|