AT指令框架(C语言)
本文档记录设计的AT指令框架,使用时只需要简单增加修改指令和执行指令函数
一、指令结构
typedef enum{
AT_CMD_TEST = 0, /* 测试指令 */
AT_CMD_NAME, /* 设置名称 */
AT_CMD_DISA, /* 断开当前连接 */
AT_CMD_TX_POWER, /* 设置发送功率 */
AT_CMD_ADV_INTERVAL, /* 设置广播间隔 */
AT_CMD_CON_INTERVAL, /* 设置连接间隔 */
AT_CMD_ADV_ONOFF, /* 设置打开、关闭广播 */
AT_GET_VER, /* 获取版本号 */
AT_GET_CON_STATE, /* 获取连接状态 */
AT_CMD_UART_CFG, /* 配置UART参数 */
AT_END
}AT_Cmd;
typedef unsigned char (*pFunc)(unsigned char *ptr, unsigned char len);
typedef struct {
AT_Cmd cmd; /* 指令序号 */
unsigned char *str; /* 指令内容 */
pFunc cb; /* 指令执行 */
}AT_cmd_func;
/* AT指令表 */
const AT_cmd_func at_cmd_func[] = {
{AT_CMD_TEST, "AT", at_cmd_test},
{AT_CMD_NAME, "AT+NAME=", at_cmd_name},
{AT_CMD_DISA, "AT+DISC", NULL},
{AT_CMD_TX_POWER, "AT+TX=", NULL},
{AT_CMD_ADV_INTERVAL, "AT+ADV_INTERVAL=", NULL},
{AT_CMD_CON_INTERVAL, "AT+CON_INTERVAL=", NULL},
{AT_CMD_ADV_ONOFF, "AT_ADV=", NULL},
{AT_GET_VER, "AT+VERSION=", NULL},
{AT_GET_CON_STATE, "AT+STATE", NULL},
{AT_CMD_UART_CFG, "AT+UART_CFG=", NULL},
{AT_END, NULL, NULL}
};
指令执行函数
/* 指令执行函数 */
unsigned char at_cmd_test(unsigned char *p, unsigned char len){
AT_DEBUG_INFO("AT+OK\r\n");
return 0;
}
unsigned char at_cmd_name(unsigned char *p, unsigned char len){
if(*p == '?'){
AT_DEBUG_INFO("AT+OK BLE-NAME\r\n");
}else{
AT_DEBUG_INFO("AT+OK\r\n");
}
return 0;
}
二、指令解析
/* 查找指令表中对应的指令 */
unsigned char AT_cmd_search(unsigned char *p, unsigned char len){
unsigned char ret = 0;
unsigned char *pstr;
unsigned char i, 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;
}
}
return ret;
}
/* AT指令解析 */
unsigned char at_cmd_parse(unsigned char *p, unsigned char len){
unsigned char ret = AT_SUCCESS;
unsigned char index = 0;
if(len < 4) return AT_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); /* 执行测试指令 */
}else if(p[2] == '+'){ /* 执行指令解析 */
index = AT_cmd_search(p, len); /* 查找匹配的执行指令,0-已匹配,!0-未匹配 */
if(index){
if(at_cmd_func[index].cb != NULL){ /* 判断指令对应执行函数是否存在 */
unsigned char n;
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_UNINVAIL; /* 未找到匹配的指令 */
}
}
}else{/* 格式不匹配 */
return AT_ERR;
}
return ret;
}
三、指令测试
/* 测试 */
int main(void){
unsigned char ret;
unsigned char i, n, m;
#define CMD_NUM_MAX (5)
char *test_cmd[CMD_NUM_MAX]={
"AT\r\n",
"AT+NAME=BLE-TEST\r\n",
"AT+NAME=?\r\n",
"AT+DISC\r\n",
"AT+NBME=?\r\n",
};
for(i=0; i<CMD_NUM_MAX; i++){
m = mstrlen(test_cmd[i]);
ret = at_cmd_parse(test_cmd[i], m);
if(ret)
AT_DEBUG_INFO("AT ERR! = %d\r\n", ret);
}
return 0;
}
结果如下

指令解析后返回数据定义
#define AT_SUCCESS (0) /* 指令正常 */ #define AT_ERR (1) /* 指令异常 */ #define AT_ERR_UNINVAIL (2) /* 没有对应指令 */ #define AT_ERR_FUN_UNUSED (3) /* 没有可执行函数 */ /* 返回值参数内容如上, p-指向解析的指令,len-解析指令长度 */ unsigned char at_cmd_parse(unsigned char *p, unsigned char len);
注意:上面代码中使用了2个类C库函数 mstrlen, mstrncmp (与C库中strlen, strncmp功能一致),主要是为了移植是脱离平台,编译时使用代码占用空间尽量少
unsigned int mstrlen(const char *s){
const char *ss = s;
while (*ss)
ss++;
return ss - s;
}
int mstrncmp(const char *s1, const char *s2, int n){
const unsigned char *c1 = (const unsigned char *)s1;
const unsigned char *c2 = (const unsigned char *)s2;
unsigned char ch;
int d = 0;
while (n--) {
d = (int)(ch = *c1++) - (int)*c2++;
if (d || !ch)
break;
}
return d;
}


浙公网安备 33010602011771号