自定义AT开发指南¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
功能概述¶
AT命令(Attention Command)是一种用于控制调制解调器或通信模块的标准化指令集。每条命令以“AT”开头,用于通知设备即将发送命令,随后设备执行具体操作,如查询信号质量、发送短信、拨打电话或配置模块参数。设备执行命令后会返回响应,如 OK、ERROR 或状态信息,响应末尾通常带有回车换行(CR/LF)作为格式化标记。
AT命令广泛应用于GSM、3G/4G/5G模块、蓝牙和GPS设备,支持文本与数字两种响应模式,便于开发者进行设备控制、状态查询和调试。由于其简洁性、标准化和跨厂商兼容性,AT命令成为嵌入式通信和模块开发中最常用的控制接口。本文主要描述如何通过相关API实现自定义AT命令的注册与处理。
AT命令类型¶
标准AT命令一般有 四种基本操作类型:测试命令、查询命令、设置命令 和 执行命令。
类型 |
示例 |
说明 |
|---|---|---|
测试命令 |
AT+ |
测试是否存在相应的命令,并返回有关其参数的类型、值或范围的信息 |
查询命令 |
AT+ |
查询相应命令的当前参数值 |
设置命令 |
AT+ |
设置用户可定义的参数值 |
执行命令 |
AT+ |
返回特定的参数信息或执行特定的操作 |
测试命令¶
格式
AT+<cmd>=?
作用
测试是否存在相应的命令,并返回有关其参数的类型、值或范围的信息。示例
AT+CFUN=?
+CFUN: (0,1,4)
OK
上述示例表示该命令支持0、1和4这三种模式。
特点
以=?结尾;
查询可支持的参数范围;
常用于调试或开发阶段。
查询命令¶
格式
AT+<cmd>?
作用
查询相应命令的当前参数值。示例
AT+CFUN?
+CFUN: 1
OK
上述示例表示查询当前的CFUN模式,当前模式设置为1。
特点
以?结尾;
不修改配置;
查询当前状态。
设置命令¶
格式
AT+<cmd>=<p1>[,<p2>[,<p3>[...]]]
作用
设置用户可定义的参数值。示例
AT+CFUN=1
上述示例表明设置CFUN模式为1。
特点
带=号;
且包含配置参数;
用于修改配置。
执行命令¶
格式
AT+<cmd>
作用
返回特定的参数信息或执行特定的操作。示例
AT+CIMI
上述示例表明执行AT+CIMI(用于查询IMSI号)。
特点
不带参数;
直接执行操作。
添加自定义AT命令¶
需要使用到的接口文件:
qos_components\system\at\qosa_at_cmd.h
增加自定义AT命令的基本流程如下:
注册自定义AT命令:
系统在开机后的初始化阶段,通过 qosa_at_parser_add_cust_at() 添加自定义AT命令。该函数可以接收一个包含多个AT命令及其处理函数的表格。实现处理函数:
在AT处理函数中, 实现AT命令的功能。
以下通过一个最简单的AT处理函数,介绍如何实现自定义的AT处理函数。 该AT命令的名称为 AT+QEXAMPLEHELLO, 发送 READ命令(AT+QEXAMPLEHELLO?) 会返回"+QEXAMPLEHELLO: Hello World!"。
步骤一:注册自定义AT命令。
首先在开机初始化阶段调用 qosa_at_parser_add_cust_at() 注册AT命令 +QEXAMPLEHELLO 以及对应的处理函数。此处AT命令的字符串请勿加上AT字符。示例代码如下:
qosa_at_desc_t unir_examples_at_desc[] = {
{"+QEXAMPLEHELLO", unir_exec_example_qexamplehello_cmd, 0},
{QOSA_NULL, QOSA_NULL, 0}};
qosa_at_parser_add_cust_at((const qosa_at_desc_t *)unir_examples_at_desc, QOSA_ARRAY_SIZE(unir_examples_at_desc));
步骤二:实现处理函数。
AT命令的处理并非简单的字符串匹配,而是一套高度抽象的命令分发机制。AT命令解析器框架已完成从物理链路层到应用逻辑层的解耦,因此开发者只需关注 unir_exec_example_qexamplehello_cmd() 这一回调函数,在该函数中完成自定义AT命令的业务逻辑。示例代码如下:
void unir_exec_example_qexamplehello_cmd(qosa_at_cmd_t *cmd)
{
char resp[128] = {0}; // Response string buffer
switch (cmd->type)
{
case QOSA_AT_CMD_READ: {
// Read command processing branch, e.g. input AT+QEXAMPLEHELLO?
qosa_snprintf(resp, sizeof(resp), "%s", "+QEXAMPLEHELLO: Hello World!");
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_OK, QOSA_CMD_RC_OK, resp, 1);
}
break;
case QOSA_AT_CMD_SET: {
// Set command processing branch, e.g. input AT+QEXAMPLEHELLO="cfg",10
// Get first string parameter
test_str = (char *)qosa_at_param_string(cmd->params[0], ¶mok);
if (!paramok)
{
// Return error when parameter is invalid
qosa_at_resp_cme_error(cmd->dev_port, QOSA_ERR_AT_CME_PARAM_INVALID);
return;
}
// Construct and return set command response
qosa_snprintf(resp, sizeof(resp), "+QEXAMPLEHELLO: \"%s\"", test_str);
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_OK, QOSA_CMD_RC_OK, resp, 1);
}
break;
default:
// Unsupported command type, return operation not supported error
QOSA_RETURN_CME_ERR(cmd->dev_port, QOSA_ERR_AT_CME_OPERATION_NOT_SUPPORTED);
break;
}
}
处理函数的参数功能说明如下:
cmd->type:用于确定命令的类型
cmd->params:命令的参数集
cmd->dev_port:命令传输通道, 后续回复AT命令需要向此通道传输
命令分发
当一条AT命令到达处理器时,SDK首先将其解析并封装进 qosa_at_cmd_t 结构体中。其中cmd->type是处理流程的核心字段,它定义了当前交互的语义:
类型 (cmd->type) |
对应AT指令示例 |
说明 |
|---|---|---|
QOSA_AT_CMD_READ |
AT+QEXAMPLEHELLO? |
查询命令 |
QOSA_AT_CMD_SET |
AT+QEXAMPLEHELLO=“cfg”,1 |
设置命令 |
QOSA_AT_CMD_TEST |
AT+QEXAMPLEHELLO=? |
测试命令 |
QOSA_AT_CMD_EXE |
AT+QEXAMPLEHELLO |
执行命令 |
命令参数的解析与校验
SDK提供专用的API来解析cmd->params[]数组中的参数,并对解析结果进行校验。这些API具备自动类型转换和合法性检查功能。
解析API:
字符串解析API:qosa_at_param_string(cmd->params[index], &ok)
整型解析API:qosa_at_param_int(cmd->params[index], &ok)安全性校验:SDK引入了paramok机制,该变量可在解析过程中传递状态。解析API采用“逻辑短路”设计:一旦序列中某个参数解析失败,paramok立即被锁定为false状态,后续有效解析自动中止。开发者需在所有参数解析完成后,对paramok进行一次最终校验。
响应回复机制
发送命令执行结果时,必须关联cmd->dev_port,以确保响应能准确返回给发起请求的通道(如UART或USB)。
成功响应:使用 qosa_at_resp_cmd() 发送具体内容及OK状态。
错误响应:使用 qosa_at_resp_cmd()/qosa_at_resp_cme_error()/QOSA_RETURN_CME_ERR 返回标准错误码,便于上位机识别异常原因。
自定义AT API¶
头文件¶
qosa_at_cmd.h
函数概览¶
函数 |
描述 |
|---|---|
qosa_at_parser_add_cust_at() |
动态添加自定义AT命令 |
qosa_at_resp_cmd() |
返回结果并结束AT命令 |
qosa_at_resp_cmd_info_text() |
输出文本但不结束命令 |
qosa_at_resp_finish() |
结束AT命令并清理资源 |
函数详解¶
qosa_at_parser_add_cust_at¶
功能描述
动态添加自定义AT命令。用于应用层向系统注册自定义AT命令,用户可将命令描述符列表添加到AT解析器中,从而扩展模块的标准AT命令集。函数原型
void qosa_at_parser_add_cust_at(const qosa_at_desc_t *desc, qosa_uint32_t list_len)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
desc |
输入 |
const qosa_at_desc_t * |
指向自定义AT命令描述结构体列表的指针。有关自定义AT命令描述结构体详情,详见 qosa_at_desc_t |
list_len |
输入 |
qosa_uint32_t |
待添加的AT命令列表中的命令总数(总数需大于等于1) |
返回值说明
无
备注
该函数通常在应用初始化阶段调用。
注册的命令名称不能与系统内置的标准AT命令重名。
qosa_at_resp_cmd¶
功能描述
返回结果并结束AT命令。向指定的AT通道返回命令执行的最终结果,并正式结束当前AT命令的生命周期。支持返回 OK、ERROR、CME ERROR 及 CMS ERROR 等标准响应格式。函数原型
void qosa_at_resp_cmd(qosa_at_dev_type_e dev_port, qosa_atci_result_code_e resultCode, qosa_uint32_t report_code, char *rsp_buffer, qosa_uint8_t padding)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
dev_port |
输入 |
qosa_at_dev_type_e |
AT命令的目标通道。详情请参考 qosa_at_dev_type_e |
resultCode |
输入 |
qosa_atci_result_code_e |
返回结果类型(如 QOSA_ATCI_RESULT_CODE_OK)。详情请参考 qosa_atci_result_code_e |
report_code |
输入 |
qosa_uint32_t |
错误码。当结果为 CME ERROR 或 CMS ERROR 时,携带具体的错误编号。report_code 的取值取决于 resultCode 的类型。详情可参考 resultCode的使用说明 |
rsp_buffer |
输入 |
char * |
响应内容缓冲区。仅在结果为 OK 且需要返回额外数据时有效。若无需返回数据,可设置为 QOSA_NULL |
padding |
输入 |
qosa_uint8_t |
换行符(\r\n)填充模式配置,控制 rsp_buffer 内容前后是否自动添加换行。范围:0~4
|
resultCode的使用说明如下:
不推荐使用 QOSA_ATCI_RESULT_CODE_NULL。如需返回常规错误码, 请使用 QOSA_ATCI_RESULT_CODE_ERROR,并将 report_code 设定为 QOSA_CMD_RC_ERROR。示例代码如下:
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_ERROR, QOSA_CMD_RC_ERROR, QOSA_NULL, 1)
QOSA_ATCI_RESULT_CODE_CMS_ERROR 为短信相关的错误码, 不推荐使用。
当 resultCode 为 QOSA_ATCI_RESULT_CODE_OK 时, report_cod e应设为 QOSA_CMD_RC_OK。如果有字符串需要输出, rsp_buffer 应填入字符串地址;否则设为 QOSA_NULL。示例代码如下:
//无字符串输出
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_OK, QOSA_CMD_RC_OK, QOSA_NULL, 1);
//有字符串输出
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_OK, QOSA_CMD_RC_OK, rsp_buffer, 1);
当 resultCode 为 QOSA_ATCI_RESULT_CODE_CME_ERROR 时, report_code 可填入 QOSA_ERR_AT_CME_ 开头的CME相关错误码或者自定义错误码, rsp_buffer 需要保持为 QOSA_NULL。示例代码如下:
qosa_at_resp_cmd(cmd->dev_port, QOSA_ATCI_RESULT_CODE_CME_ERROR, QOSA_ERR_AT_CME_OPERATION_NOT_ALLOWED, QOSA_NULL, 1);
返回值说明
无
备注
调用该函数后,当前AT命令处理流程即结束,通道重新进入待命状态。
若仅需输出中间过程信息而不结束命令,请调用 qosa_at_resp_cmd_info_text()。
qosa_at_resp_cmd_info_text¶
功能描述
输出文本但不结束命令。在AT命令执行过程中输出文本信息,仅负责向指定通道发送数据,不会改变当前的AT解析状态,也不会结束正在执行的命令。函数原型
int qosa_at_resp_cmd_info_text(qosa_at_dev_type_e dev_port, const char *text, qosa_size_t length, unsigned char padding)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
dev_port |
输入 |
qosa_at_dev_type_e |
AT命令的目标通道。详情请参考 qosa_at_dev_type_e |
text |
输入 |
const char * |
响应内容缓冲区。不可为空 |
length |
输入 |
qosa_size_t |
text 的长度。单位:字节。该长度需大于等于1 |
padding |
输入 |
unsigned char |
换行符(\r\n)填充模式配置,控制 text 内容前后是否自动添加换行。范围:0~4
|
返回值说明
0:函数执行成功
非0:函数执行失败
备注
该函数常用于查询命令或需要分多行输出数据的场景。
在使用 qosa_at_resp_cmd_info_text() 输出自定义响应内容后,必须调用 qosa_at_resp_cmd() 返回最终执行结果(如 OK 或 ERROR),以结束当前AT命令流程。
qosa_at_resp_finish¶
功能描述
结束AT命令并清理资源。结束当前AT命令解析流程,清除当前状态,并向AT线程发送事件以继续读取新的输入数据。函数原型
int qosa_at_resp_finish(qosa_at_dev_type_e dev_port)
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
dev_port |
输入 |
qosa_at_dev_type_e |
AT命令的目标通道。详情请参考 qosa_at_dev_type_e |
返回值说明
0:函数执行成功
非0:函数执行失败
备注
该函数用于AT命令处理的收尾操作,清除当前解析状态。调用后,AT线程将继续读取新的输入数据。
结构体定义¶
qosa_at_desc_t¶
自定义AT命令描述结构体定义如下:
typedef struct _qosa_at_desc
{
char *name;
void (*handler)(struct _qosa_at_cmd *);
qosa_uint32_t constrains;
} qosa_at_desc_t;
参数 |
类型 |
说明 |
|---|---|---|
name |
char * |
命令名称字符串。例如 "+IPR*“、”+QEXAMPLEHELLO"*。注册时只填写命令体,不包含前缀AT |
handler |
void (*)(struct _qosa_at_cmd *) |
命令的处理回调。命令匹配成功后,AT解析器会调用此函数,并通过 qosa_at_cmd_t 向回调传入通道、命令类型、参数列表等上下文信息 |
constrains |
qosa_uint32_t |
保留参数(暂不使用,请保持为0) |
示例:
qosa_at_desc_t unir_examples_at_desc[] = {
{"+qexampleedit", unir_exec_example_qexampleedit_cmd, 0},
{"+qexamplehello", unir_exec_example_qexamplehello_cmd, 0},
{"+qexampleraw", unir_exec_example_qexampleraw_cmd, 0},
{QOSA_NULL, QOSA_NULL, 0}};
qosa_at_cmd_t¶
qosa_at_cmd_t 是AT命令解析上下文结构体。命令匹配成功后,AT解析器构造该结构体,并通过 qosa_at_desc_t 中的 handler 传递给命令处理函数。处理函数通过该结构体判断命令类型、读取参数,并通过响应接口输出执行结果。
AT命令解析上下文结构体定义如下:
typedef struct _qosa_at_cmd
{
qosa_at_dev_type_e dev_port;
qosa_uint8_t param_count;
qosa_at_cmd_type_e type;
qosa_at_desc_t *desc;
qosa_bool_t resp_flag;
qosa_bool_t err_flag;
qosa_at_param_t *params[QOSA_AT_MAX_PARAM_CNT];
} qosa_at_cmd_t;
参数 |
类型 |
说明 |
|---|---|---|
dev_port |
qosa_at_dev_type_e |
AT命令的目标通道。详情请参考 qosa_at_dev_type_e |
param_count |
qosa_uint8_t |
当前命令解析得到的参数个数。业务处理时可结合 params 数组判断可访问的参数范围 |
type |
qosa_at_cmd_type_e |
当前AT命令的执行模式,包括设置命令、测试命令、查询命令和执行命令。handler 可根据该字段区分处理逻辑 |
desc |
qosa_at_desc_t * |
匹配到的AT命令注册描述信息,包含命令名称、处理回调和约束参数 |
resp_flag |
qosa_bool_t |
响应输出控制标志,用于标记当前AT命令是否为首次输出,AT框架据此处理响应前的换行格式 |
err_flag |
qosa_bool_t |
错误状态标志,用于记录当前AT命令执行过程中是否已经发生错误 |
params |
qosa_at_param_t *[QOSA_AT_MAX_PARAM_CNT] |
参数数组,保存解析后的AT参数。业务处理函数通常配合 qosa_at_param_* 系列接口读取和校验参数 |
枚举定义¶
qosa_at_dev_type_e¶
AT命令的目标通道枚举定义如下:
typedef enum
{
QOSA_DEV_NONE = -1,
QOSA_DEV_SIOLIB_UART1_PORT,
QOSA_DEV_SIOLIB_UART2_PORT,
QOSA_DEV_SIOLIB_UART3_PORT,
QOSA_DEV_SIOLIB_USB_AT_PORT,
QOSA_DEV_SIOLIB_USB_MODEM,
QOSA_DEV_SIOLIB_USB_AT2_PORT,
QOSA_DEV_SIOLIB_USB_NMEA,
QOSA_DEV_SIOLIB_DATA_MUX_0_PORT,
QOSA_DEV_SIOLIB_DATA_MUX_1_PORT,
QOSA_DEV_SIOLIB_DATA_MUX_2_PORT,
QOSA_DEV_SIOLIB_DATA_MUX_3_PORT,
QOSA_DEV_SIOLIB_DATA_MUX_4_PORT,
QOSA_DEV_VIRT_AT_PORT,
QOSA_DEV_PORT_MAX,
} qosa_at_dev_type_e;
成员 |
说明 |
|---|---|
QOSA_DEV_NONE |
无效端口或未指定端口,通常作为默认值或特殊场景占位值使用 |
QOSA_DEV_SIOLIB_UART1_PORT |
UART1 AT通道,对应本地端口名 uart1 |
QOSA_DEV_SIOLIB_UART2_PORT |
UART2 AT通道,对应本地端口名 uart2 |
QOSA_DEV_SIOLIB_UART3_PORT |
UART3 AT通道,对应本地端口名 uart3 |
QOSA_DEV_SIOLIB_USB_AT_PORT |
主USB AT通道,对应本地端口名 usbat |
QOSA_DEV_SIOLIB_USB_MODEM |
USB Modem通道,对应调制解调器数据相关USB端口 |
QOSA_DEV_SIOLIB_USB_AT2_PORT |
第二路USB AT通道,用于多路USB AT访问场景 |
QOSA_DEV_SIOLIB_USB_NMEA |
USB NMEA通道,对应本地端口名 usbnmea |
QOSA_DEV_SIOLIB_DATA_MUX_0_PORT |
CMUX逻辑通道基准值,常用于与后续CMUX端口做偏移换算 |
QOSA_DEV_SIOLIB_DATA_MUX_1_PORT |
第1路CMUX AT/URC通道,对应本地端口名 cmux1 |
QOSA_DEV_SIOLIB_DATA_MUX_2_PORT |
第2路CMUX AT/URC通道,对应本地端口名 cmux2 |
QOSA_DEV_SIOLIB_DATA_MUX_3_PORT |
第3路CMUX AT/URC通道,对应本地端口名 cmux3 |
QOSA_DEV_SIOLIB_DATA_MUX_4_PORT |
第4路CMUX AT/URC通道,对应本地端口名 cmux4 |
QOSA_DEV_VIRT_AT_PORT |
虚拟AT通道,对应本地端口名 virtat,用于虚拟或内部转发场景 |
QOSA_DEV_PORT_MAX |
枚举边界值,表示端口类型上限,不作为实际AT端口使用 |
qosa_atci_result_code_e¶
返回结果类型枚举定义如下:
typedef enum QOSA_ATCI_RESULT_CODE
{
QOSA_ATCI_RESULT_CODE_NULL,
QOSA_ATCI_RESULT_CODE_OK,
QOSA_ATCI_RESULT_CODE_ERROR,
QOSA_ATCI_RESULT_CODE_CME_ERROR,
QOSA_ATCI_RESULT_CODE_CMS_ERROR,
QOSA_ATCI_RESULT_CODE_MAX
} qosa_atci_result_code_e;
成员 |
说明 |
|---|---|
QOSA_ATCI_RESULT_CODE_NULL |
空结果类型。一般不推荐使用,实际开发中应优先使用更明确的 OK、ERROR、CME ERROR 或 CMS ERROR |
QOSA_ATCI_RESULT_CODE_OK |
命令执行成功。若同时传入 rsp_buffer,会先输出内容,再输出最终 OK |
QOSA_ATCI_RESULT_CODE_ERROR |
返回标准 ERROR 结果,适用于通用失败场景 |
QOSA_ATCI_RESULT_CODE_CME_ERROR |
返回 +CME ERROR: |
QOSA_ATCI_RESULT_CODE_CMS_ERROR |
返回 +CMS ERROR: |
QOSA_ATCI_RESULT_CODE_MAX |
枚举边界值,用于范围控制,不作为实际返回结果使用 |
应用逻辑流程图¶
该流程在系统启动的初始化阶段执行,目的是注册自定义AT命令:当接收到该命令字符串时,系统将调用对应的处理函数。
用户通过串口发送命令(如 AT+QEXAMPLEHELLO?)后,AT命令解析器框架将解析该命令并触发相应的回调函数。
示例代码¶
完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/system/at/at_demo.c 。