一、AT组件概念
1.1 AT命令概念
AT命令是由发明拨号调制解调器modem的hayes公司为了控制modem发明的控制协议,后来移动电话厂家为GSM提供了标准的AT命令用于控制 手机的GSM模块。
1.2 rtthread AT组件资源占用
AT Client 功能: 4.6K ROM 和 2.0K RAM;
AT Server 功能: 4.0K ROM 和 2.5K RAM;
AT CLI 功能: 1.5K ROM ,几乎没有使用 RAM。
1.3 AT组件功能
AT Server:
• 基础命令:实现多种通用基础命令(ATE、 ATZ 等);
• 命令兼容:命令支持忽略大小写,提高命令兼容性;
• 命令检测:命令支持自定义参数表达式,并实现对接收的命令参数自检测功能;
• 命令注册:提供简单的用户自定义命令添加方式,类似于 finsh/msh 命令添加方式;
• 调试模式:提供 AT Server CLI 命令行交互模式,主要用于设备调试。
AT Client:
• URC 数据处理:完备的 URC 数据的处理方式;
• 数据解析:支持自定义响应数据的解析方式,方便获取响应数据中相关信息;
• 调试模式:提供 AT Client CLI 命令行交互模式,主要用于设备调试。
• AT Socket:作为 AT Client 功能的延伸,使用 AT 命令收发作为基础,实现标准的 BSD Socket
API,完成数据的收发功能,使用户通过 AT 命令完成设备连网和数据通讯。
• 多客户端支持: AT 组件目前支持多客户端同时运行。
二、AT组件api
2.1 server api
2.1.1 api
//AT server初始化,如果使能了自动初始化则不需要
int at_server_init(void);
//注册自定义AT命令
/*
_name_:自定义AT命令名称,如: "AT+TEST"
_args_expr_:AT 命令参数表达式;(无参数为 NULL, <> 中为必选参数, [] 中为可选参数),如 = [,]
_test_:AT测试函数
_query_:AT查询函数
_setup_:AT设置函数
_exec_:AT执行函数
*/
AT_CMD_EXPORT(_name_, _args_expr_, _test_, _query_, _setup_, _exec_);
//发送数据到客户端
/*
format:自定义发送数据的表达式
...:发送数据列表
*/
void at_server_printf(const char *format, ...);
//带换行的发送数据到客户端
void at_server_printfln(const char *format, ...);
//向客户端发送执行结果
/*
result:执行结果,可取
AT_RESULT_OK 命令执行成功
AT_RESULT_FAILE 命令执行失败
AT_RESULT_NULL 命令无返回结果
AT_RESULT_CMD_ERR 输入命令错误
AT_RESULT_CHECK_FAILE 参数表达式匹配错误
AT_RESULT_PARSE_FAILE 参数解析错误
*/
void at_server_print_result(at_result_t result);
//解析设置命令参数
/*
req_args:设置命令输入参数字符串
req_expr:解析表达式
...:用于存放解析出的参数
*/
int at_req_parse_args(const char *req_args, const char *req_expr, ...);
2.1.2 server api示例
static at_result_t at_test_setup(const char *args)
{
int value1,value2;
/* args 的 输 入 标 准 格 式 应 为 "=1,2", "=%d,%d" 为 自 定 义 参 数 解 析 表 达 式, 解 析 得 到 结 果
存 入 value1 和 value2 变 量 */
if (at_req_parse_args(args, "=%d,%d", &value1, &value2) > 0)
{
/* 数 据 解 析 成 功, 回 显 数 据 到 AT Server 串 口 设 备 */
at_server_printfln("value1 : %d, value2 : %d", value1, value2);
/* 数 据 解 析 成 功, 解 析 参 数 的 个 数 大 于 零, 返 回 执 行 成 功 */
at_server_print_result(AT_RESULT_OK);
}
else
{
/* 数 据 解 析 失 败, 解 析 参 数 的 个 数 不 大 于 零, 返 回 解 析 失 败 结 果 类 型 */
at_server_print_result(AT_RESULT_PARSE_FAILE);
}
return 0;
}
/* 添 加 "AT+TEST" 命 令 到 AT 命 令 列 表, 命 令 参 数 格 式 为 两 个 必 选 参 数 和
> */
AT_CMD_EXPORT("AT+TEST", =,, NULL, NULL, at_test_setup, NULL);
2.2 client api
rtthread将AT的响应抽象成rt_response
struct at_response
{
/* response buffer */
char *buf;
/* the maximum response buffer size */
rt_size_t buf_size;
/* the number of setting response lines
* == 0: the response data will auto return when received 'OK' or 'ERROR'
* != 0: the response data will return when received setting lines number data
*/
rt_size_t line_num;
/* the count of received response lines */
rt_size_t line_counts;
/* the maximum response time */
rt_int32_t timeout;
};
typedef struct at_response *at_response_t;
2.2.1 client 处理响应数据api
//创建响应结构体句柄,用于接收来自AT server的响应
/*
buf_size:最大接收数据长度
line_num:接收响应的行数
timeout:接收响应的最大时间
*/
at_response_t at_create_resp(rt_size_t buf_size, rt_size_t line_num, rt_int32_t timeout);
//删除响应结构体句柄
/*
resp:响应结构体句柄
*/
void at_delete_resp(at_response_t resp);
//修改响应结构体的参数
/*
resp:响应结构体句柄
buf_size、line_num、timeout同at_create_resp
*/
at_response_t at_resp_set_info(at_response_t resp,
rt_size_t buf_size,
rt_size_t line_num,
rt_int32_t timeout);
//发送命令并接收响应
/*
resp:响应结构体句柄
cmd_expr:AT命令表达式
...:输入参数
*/
rt_err_t at_exec_cmd(at_response_t resp, const char *cmd_expr, ...);
//获取响应数据中指定行的数据
/*
resp:响应结构体句柄
resp_line:行号
*/
const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line);
//获取指定关键字的响应
/*
resp:响应结构体句柄
keyword:关键字字符串
返回:带有指定关键字的响应数据指针
*/
const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword);
//解析指定行的数据
/*
resp:响应结构体句柄
resp_line:行号
resp_expr:解析表达式
...:用于存放解析到的数据
*/
int at_resp_parse_line_args(at_response_t resp, rt_size_t resp_line, const char *resp_expr, ...);
//解析带指定关键字的响应数据
/*
resp:响应句柄
key_word:关键字字符串
resp_expr:解析表达式
...:用于存放解析到的数据
*/
int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...);
2.2.2 client 处理响应数据api示例
/* 创 建 服 务 器 响 应 结 构 体, 64 为 用 户 自 定 义 接 收 数 据 最 大 长 度 */
resp = at_create_resp(64, 0, rt_tick_from_millisecond(5000));
/* 发 送 数 据 到 服 务 器, 并 接 收 响 应 数 据 存 放 在 resp 结 构 体 中 */
at_exec_cmd(resp, "AT+UART?");
/* 解 析 获 取 串 口 配 置 信 息, 1 表 示 解 析 响 应 数 据 第 一 行, '%*[^=]'表 示 忽 略 等 号 之 前 的 数 据 */
at_resp_parse_line_args(resp, 1,"%*[^=]=%d,%d,%d,%d,%d", &baudrate, &databits, &
stopbits, &parity, &control);
printf("baudrate=%d, databits=%d, stopbits=%d, parity=%d, control=%dn",
baudrate, databits, stopbits, parity, control);
/* 删 除 服 务 器 响 应 结 构 体 */
at_delete_resp(resp);
2.2.3 client URC数据处理api
rtthread将AT的URC数据抽象成rt_urc
struct at_urc
{
const char *cmd_prefix; // URC 数 据 前 缀
const char *cmd_suffix; // URC 数 据 后 缀
void (*func)(const char *data, rt_size_t size); // URC 数 据 执 行 函 数
};
typedef struct at_urc *at_urc_t;
//设置urc数据列表
/*
table:URC句柄数组指针
size:有多少个at_urc
*/
void at_set_urc_table(const struct at_urc *table, rt_size_t size);
2.2.4 client URC数据处理api示例
static void urc_conn_func(const char *data, rt_size_t size)
{
/* WIFI 连 接 成 功 信 息 */
LOG_D("AT Server device WIFI connect success!");
}
static void urc_recv_func(const char *data, rt_size_t size)
{
/* 接 收 到 服 务 器 发 送 数 据 */
LOG_D("AT Client receive AT Server data!");
}
static void urc_func(const char *data, rt_size_t size)
{
/* 设 备 启 动 信 息 */
LOG_D("AT Server device startup!");
}
static struct at_urc urc_table[] = {
{"WIFI CONNECTED", "rn", urc_conn_func},
{"+RECV", ":", urc_recv_func},
{"RDY", "rn", urc_func},
};
int at_client_port_init(void)
{
/* 添 加 多 种 URC 数 据 至 URC 列 表 中, 当 接 收 到 同 时 匹 配 URC 前 缀 和 后 缀 的 数 据, 执 行
URC 函 数 */
at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
return RT_EOK;
}
2.2.5 client 其它api
//发送指定大小的数据
/*
buf:发送缓冲区
size:发送数据大小
*/
rt_size_t at_client_send(const char *buf, rt_size_t size);
//接收指定大小数据
/*
buf:接收缓冲区
size:接收数据大小
timeout:接收超时时间
*/
rt_size_t at_client_recv(char *buf, rt_size_t size,rt_int32_t timeout)
//设置接收数据的行结束符
/*
ch:希望的结束字符
*/
void at_set_end_sign(char ch);
//等待模块初始化完成,该函数一直发送AT命令直到模块响应
/*
timeout:等待超时时间
*/
int at_client_wait_connect(rt_uint32_t timeout);
|