【rtthread番外】第二篇:AT组件

一、AT组件概念

1.1 AT命令概念

AT命令是由发明拨号调制解调器modem的hayes公司为了控制modem发明的控制协议,后来移动电话厂家为GSM提供了标准的AT命令用于控制手机的GSM模块。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOX8QwTR-1621517924106)(en-resource://database/2818:1)]

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, <> 中为必选参数, [] 中为可选参数),如 =<value1>[,<value2>]
_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 命 令 列 表, 命 令 参 数 格 式 为 两 个 必 选 参 数 <value1> 和 <value2
> */
AT_CMD_EXPORT("AT+TEST", =<value1>,<value2>, 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=%d\n",
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", "\r\n", urc_conn_func},
	{
    
    "+RECV", ":", urc_recv_func},
	{
    
    "RDY", "\r\n", 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);

Guess you like

Origin blog.csdn.net/weixin_43810563/article/details/117092348