自定义AT开发指南

Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.


功能概述

AT命令(Attention Command)是一种用于控制调制解调器或通信模块的标准化指令集。每条命令以“AT”开头,用于通知设备即将发送命令,随后设备执行具体操作,如查询信号质量、发送短信、拨打电话或配置模块参数。设备执行命令后会返回响应,如 OKERROR 或状态信息,响应末尾通常带有回车换行(CR/LF)作为格式化标记。

AT命令广泛应用于GSM、3G/4G/5G模块、蓝牙和GPS设备,支持文本与数字两种响应模式,便于开发者进行设备控制、状态查询和调试。由于其简洁性、标准化和跨厂商兼容性,AT命令成为嵌入式通信和模块开发中最常用的控制接口。本文主要描述如何通过相关API实现自定义AT命令的注册与处理。

AT命令类型

标准AT命令一般有 四种基本操作类型:测试命令、查询命令、设置命令执行命令


类型


示例


说明

测试命令

AT+<cmd>=?

测试是否存在相应的命令,并返回有关其参数的类型、值或范围的信息

查询命令

AT+<cmd>?

查询相应命令的当前参数值

设置命令

AT+<cmd>=<p1>[,<p2>[,<p3>[...]]]

设置用户可定义的参数值

执行命令

AT+<cmd>

返回特定的参数信息或执行特定的操作

测试命令

  • 格式

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命令的基本流程如下:

  1. 注册自定义AT命令:
    系统在开机后的初始化阶段,通过 qosa_at_parser_add_cust_at() 添加自定义AT命令。该函数可以接收一个包含多个AT命令及其处理函数的表格。

  2. 实现处理函数:
    在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], &paramok);
            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)

  • 返回值说明

备注

  1. 该函数通常在应用初始化阶段调用。

  2. 注册的命令名称不能与系统内置的标准AT命令重名。

qosa_at_resp_cmd

  • 功能描述
    返回结果并结束AT命令。向指定的AT通道返回命令执行的最终结果,并正式结束当前AT命令的生命周期。支持返回 OKERRORCME ERRORCMS 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 ERRORCMS ERROR 时,携带具体的错误编号。report_code 的取值取决于 resultCode 的类型。详情可参考 resultCode的使用说明

rsp_buffer

输入

char *

响应内容缓冲区。仅在结果为 OK 且需要返回额外数据时有效。若无需返回数据,可设置为 QOSA_NULL

padding

输入

qosa_uint8_t

换行符(\r\n)填充模式配置,控制 rsp_buffer 内容前后是否自动添加换行。范围:0~4

  • 0: 不添加
  • 1: 自动在 rsp_buffer 前后增加换行符,如果 rsp_buffer 原始数据前后已有换行符, 则避免重复
  • 2: 强制在 rsp_buffe r前后增加换行符
  • 3: 强制在 rsp_buffer 前增加换行符
  • 4: 强制在 rsp_buffer 后增加换行符
推荐使用 1

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 为短信相关的错误码, 不推荐使用。

  • resultCodeQOSA_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);
  • resultCodeQOSA_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);
  • 返回值说明

备注

  1. 调用该函数后,当前AT命令处理流程即结束,通道重新进入待命状态。

  2. 若仅需输出中间过程信息而不结束命令,请调用 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: 不添加
  • 1: 自动在 text 前后增加换行符, 如果 text 原始数据前后已有换行符, 则避免重复
  • 2: 强制在 text 前后增加换行符
  • 3: 强制在 text 前增加换行符
  • 4: 强制在 text 后增加换行符
推荐使用 1

  • 返回值说明
    0:函数执行成功
    非0:函数执行失败

备注

  1. 该函数常用于查询命令或需要分多行输出数据的场景。

  2. 在使用 qosa_at_resp_cmd_info_text() 输出自定义响应内容后,必须调用 qosa_at_resp_cmd() 返回最终执行结果(如 OKERROR),以结束当前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

空结果类型。一般不推荐使用,实际开发中应优先使用更明确的 OKERRORCME ERRORCMS ERROR

QOSA_ATCI_RESULT_CODE_OK

命令执行成功。若同时传入 rsp_buffer,会先输出内容,再输出最终 OK

QOSA_ATCI_RESULT_CODE_ERROR

返回标准 ERROR 结果,适用于通用失败场景

QOSA_ATCI_RESULT_CODE_CME_ERROR

返回 +CME ERROR: 类型错误,适用于设备、参数、网络等ME相关错误

QOSA_ATCI_RESULT_CODE_CMS_ERROR

返回 +CMS ERROR: 类型错误,适用于短信业务相关失败场景

QOSA_ATCI_RESULT_CODE_MAX

枚举边界值,用于范围控制,不作为实际返回结果使用

应用逻辑流程图

该流程在系统启动的初始化阶段执行,目的是注册自定义AT命令:当接收到该命令字符串时,系统将调用对应的处理函数。

image

用户通过串口发送命令(如 AT+QEXAMPLEHELLO?)后,AT命令解析器框架将解析该命令并触发相应的回调函数。

image

示例代码

完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/system/at/at_demo.c