AT 命令参考
本文档是 AW33N BLE SDK 中 AT 命令体系(at_char_com 示例应用)的完整参考,涵盖命令解析框架、命令分类、参数格式、响应协议、底层通道与扩展方式。
Purpose and Scope
本页面向需要基于 AT 命令调试、测试或二次开发 AW33N BLE 产品的开发者,完整说明:
- AT 命令的框架设计:命令头(
AT+/AT>)、操作符(=设置、?查询)、参数解析与响应(OK/ERR)协议; - 命令字符串表与字符串 ID 枚举的映射关系;
- 全部内置命令的分类说明(系统查询、广播、扫描连接、传输、电源管理);
- 核心数据结构(
at_param_t、str_info_t、target_uuid_info_t)与解析缓冲区的内存布局; - 与 UART 通道、BLE 服务端/客户端之间的数据流;
- 配置项、错误码、边界情况与扩展新命令的方法。
本页不包含:BLE 广播参数细节、GATT Profile 具体实现、UART 驱动寄存器级配置——这些属于 ble_at_char 与 at_char_uart 相关主题,建议参见同目录下源码。本页聚焦命令层(at_char_cmds.*)与命令触发入口(app_at_char_com.c、ble_at_char_client.c)。
概述
at_char_com 是 SDK 中一个"AT 命令透传"参考应用:设备通过 UART 接收符合 AT 语法的人机指令,解析后驱动 BLE 协议栈完成广播、扫描、连接、数据传输、OTA 升级、开关机等操作,并将结果以文本形式返回。它同时承担两类角色:
- 从机(Server):广播自身、接受主机连接;
- 主机(Client):主动扫描并连接外设,读写对端 GATT 特征。
AT 指令通道在所有 BLE 连接通道中拥有独立的通道号,代码注释明确划分了通道资源:
0-7:主机通道(主动连出通道);8:从机通道;9:AT 指令通道
(来源:at_char_cmds.c)
命令层与通道层解耦:at_char_cmds.c 只负责"字符串 → 命令 ID → 处理函数"的解析分发,实际行为通过 at_cmd_send()、at_send_rx_cid_data() 等接口下发到 BLE 栈或 UART,因此同样的命令框架可复用于不同的底层传输。
架构
flowchart TD
subgraph sg_Input["输入层"]
UART["at_char_uart.c<br/>UART 接收/发送"]
BLE_C["ble_at_char_client.c<br/>BLE 客户端回调"]
end
subgraph sg_Cmd["命令层 (at_char_cmds.c)"]
PARSE["parse_buffer[256]<br/>输入缓冲 + 参数解析"]
TABLE["at_cmd_str_table<br/>命令字符串表"]
DISPATCH["命令分发<br/>STR_ID → handler"]
RESP["响应生成<br/>OK / ERR / 数据上报"]
end
subgraph sg_Action["动作层"]
ADV["广播控制<br/>ADV / ADVPARAM / ADVDATA"]
SCANCONN["扫描连接<br/>SCAN / CONN / DISC / OTA"]
SYS["系统管理<br/>GVER / NAME / BAUD / POWEROFF"]
end
subgraph sg_Out["输出层"]
BLE_S["ble_at_char_server.c<br/>BLE 服务端特征"]
UART_OUT["UART TX"]
end
UART -->|"AT 字符串"| PARSE
BLE_C -->|"事件上报"| RESP
PARSE -->|"逐段匹配"| TABLE
TABLE --> DISPATCH
DISPATCH --> ADV
DISPATCH --> SCANCONN
DISPATCH --> SYS
ADV --> BLE_S
SCANCONN --> BLE_S
SYS --> RESP
RESP --> UART_OUT
RESP --> BLE_S
各层职责
- 输入层:UART 中断/轮询将字符写入解析缓冲区;BLE 客户端在扫描到设备、连接状态变化时调用
at_cmd_send()或at_send_connected()/at_send_disconnect()将事件文本注入 AT 输出流(例如 ble_at_char_client.c 中扫描结果经at_cmd_send()上报)。 - 命令层:先匹配命令头(
AT+/AT>),再按分隔符切分命令名与参数,用at_cmd_str_table把字符串映射为STR_ID_*枚举,最后调用对应处理分支。 - 动作层:每个命令 ID 对应一段处理逻辑,直接调用 BLE 协议栈 API 或系统电源管理 API。
- 输出层:所有响应统一以
\r\n结尾;既可通过 UART TX 输出,也可封装后写入 BLE 从机特征,实现"远端设备经 BLE 链路收发 AT 指令"。
命令协议格式
命令层定义了两类命令头与一组特殊字符,作为解析的分隔依据:
static const char at_head_at_cmd[] = "AT+";
static const char at_head_at_chl[] = "AT>";
static const char at_str_enter[] = "\r\n";
static const char at_str_ok[] = "OK";
static const char at_str_err[] = "ERR";
static const char specialchar[] = {'+', '>', '=', '?', '\r', ','};
(来源:at_char_cmds.c)
协议约定:
AT+<CMD>[=<参数1>,<参数2>...]:标准命令头,命令名与参数以=分隔,参数之间以,分隔;AT><CMD>:AT 指令通道专用头(与AT+走同一解析流程,但用于区分来源通道语义);?作为查询操作符,对应AT_CMD_OPT_GET;- 无
?的赋值形式对应AT_CMD_OPT_SET; - 每条命令以
\r\n结束;执行结果以OK/ERR响应,错误时携带err_id。
命令分类与详解
命令字符串表把命令名映射到 STR_ID_* 枚举,枚举在 at_char_cmds.h 中按功能分区编号:
enum {
STR_ID_NULL = 0,
STR_ID_HEAD_AT_CMD,
STR_ID_HEAD_AT_CHL,
STR_ID_OK = 0x10,
STR_ID_ERROR,
STR_ID_GVER = 0x20,
STR_ID_GCFGVER,
STR_ID_NAME,
STR_ID_LBDADDR,
STR_ID_BAUD,
STR_ID_ADV,
STR_ID_ADVPARAM,
STR_ID_ADVDATA,
STR_ID_SRDATA,
STR_ID_CONNPARAM,
STR_ID_SCAN,
STR_ID_TARGETUUID,
STR_ID_CONN,
STR_ID_DISC,
STR_ID_OTA,
STR_ID_CONN_CANNEL,
STR_ID_POWER_OFF,
STR_ID_LOW_POWER,
};
(来源:at_char_cmds.h)
命令字符串表通过宏 INPUT_STR_INFO 批量注册(str_len 用 sizeof(string)-1 自动计算,避免手工数长度):
#define INPUT_STR_INFO(id,string) {.str_id = id, .str = string, .str_len = sizeof(string)-1,}
static const str_info_t at_cmd_str_table[] = {
INPUT_STR_INFO(STR_ID_GVER, at_str_gver),
INPUT_STR_INFO(STR_ID_GCFGVER, at_str_gcfgver),
INPUT_STR_INFO(STR_ID_NAME, at_str_name),
INPUT_STR_INFO(STR_ID_LBDADDR, at_str_lbdaddr),
INPUT_STR_INFO(STR_ID_BAUD, at_str_baud),
INPUT_STR_INFO(STR_ID_ADV, at_str_adv),
INPUT_STR_INFO(STR_ID_ADVPARAM, at_str_advparam),
INPUT_STR_INFO(STR_ID_ADVDATA, at_str_advdata),
INPUT_STR_INFO(STR_ID_SRDATA, at_str_srdata),
INPUT_STR_INFO(STR_ID_CONNPARAM, at_str_connparam),
INPUT_STR_INFO(STR_ID_SCAN, at_str_scan),
INPUT_STR_INFO(STR_ID_TARGETUUID, at_str_targetuuid),
INPUT_STR_INFO(STR_ID_CONN, at_str_conn),
INPUT_STR_INFO(STR_ID_DISC, at_str_disc),
INPUT_STR_INFO(STR_ID_OTA, at_str_ota),
INPUT_STR_INFO(STR_ID_CONN_CANNEL, at_str_conn_cannel),
INPUT_STR_INFO(STR_ID_POWER_OFF, at_str_power_off),
INPUT_STR_INFO(STR_ID_LOWPOWER, at_str_lowpower),
};
(来源:at_char_cmds.c)
命令总览表
| 命令 | 功能分组 | 说明 |
|---|---|---|
AT+GVER | 系统查询 | 查询固件版本(G_VERSION) |
AT+GCFGVER | 系统查询 | 查询配置版本(CONFIG_VERSION) |
AT+NAME | 系统查询/设置 | 查询或设置设备名 |
AT+LBDADDR | 系统查询 | 查询本地蓝牙地址 |
AT+BAUD | 系统设置 | 查询或修改 AT UART 波特率(默认 TCFG_AT_UART_BAUDRATE) |
AT+ADV | 广播控制 | 启动/停止广播 |
AT+ADVPARAM | 广播控制 | 设置广播参数(间隔等,默认 ADV_INTERVAL_DEFAULT = 2048) |
AT+ADVDATA | 广播控制 | 设置广播数据 |
AT+SRDATA | 广播控制 | 设置扫描响应数据 |
AT+CONNPARAM | 连接控制 | 设置连接参数 |
AT+SCAN | 扫描连接 | 启动/停止扫描;扫描结果经 at_cmd_send() 上报 |
AT+TARGETUUID | 扫描连接 | 设置目标服务/特征 UUID(target_uuid_info_t) |
AT+CONN | 扫描连接 | 发起连接 |
AT+DISC | 扫描连接 | 断开连接 |
AT+OTA | 升级 | 触发 OTA 升级流程 |
AT+CONN_CANNEL | 连接控制 | 取消连接(拼写保留源码原样) |
AT+POWEROFF | 电源管理 | 关机 |
AT+LOWPOWER | 电源管理 | 低功耗模式开关(at_set_low_power_mode) |
操作类型(OPT)
解析器用操作类型区分"查询"与"设置":
enum {
AT_CMD_OPT_NULL = 0,
AT_CMD_OPT_SET, //设置
AT_CMD_OPT_GET, //查询
};
(来源:at_char_cmds.h)
核心解析流程
sequenceDiagram
participant U as UART / BLE 输入
participant P as 解析器 (parse_buffer)
participant T as at_cmd_str_table
participant H as 命令处理分支
participant R as 响应输出 (at_cmd_send)
U->>P: "AT+ADV=1\r\n"
P->>P: 匹配命令头 "AT+" (STR_ID_HEAD_AT_CMD)
P->>T: 按 specialchar 切分, 匹配 "ADV"
T-->>P: STR_ID_ADV
P->>H: 参数 "1" → AT_CMD_OPT_SET, 执行广播开
H->>R: 成功 → "OK\r\n" / 失败 → "ERR,err_id\r\n"
R-->>U: 文本响应
解析器先做头部匹配(AT+ / AT>),再做命令名匹配,最后按 , 切分参数链表。每个参数是一个 at_param_t 节点,next_offset 指向下一参数在 parse_buffer 中的偏移,形成单向链表:
typedef struct {
volatile uint8_t len;//长度不包含结束符
uint8_t next_offset;
uint8_t data[0]; //带结束符0
} at_param_t;
(来源:at_char_cmds.h)
宏 AT_PARAM_NEXT_P(a) 用于遍历参数链表:
#define AT_PARAM_NEXT_P(a) (at_param_t*)&parse_buffer[a->next_offset]
(来源:at_char_cmds.c)
len 标记为 volatile,说明解析缓冲区会被中断/UART 接收路径异步写入,主处理路径读取时需要关注数据一致性——这是嵌入式单缓冲区解析的典型做法:牺牲并发写保护换取零拷贝与低内存占用。
使用示例
示例 1:应用初始化时启动 AT 命令层
app_at_char_com.c 在应用启动流程中调用 at_cmd_init(),完成解析缓冲区与通道状态初始化:
at_cmd_init();
(来源:app_at_char_com.c)
示例 2:文本发送与十六进制转换
命令层对外提供统一的文本发送宏,以及 BLE 数据展示常用的 hex/字符串互转接口:
#define AT_STRING_SEND(a) at_cmd_send((uint8_t *)a,strlen(a))
(来源:at_char_cmds.c)
uint32_t hex_2_str(uint8_t *hex, uint32_t hex_len, uint8_t *str);
uint32_t str_2_hex(uint8_t *str, uint32_t str_len, uint8_t *hex);
(来源:at_char_cmds.h)
示例 3:BLE 扫描结果经 AT 通道上报
主机扫描到外设后,客户端模块把广播数据格式化到发送缓冲区,再调用 at_cmd_send() 推送给 AT 输出流(UART 或 BLE 特征):
at_cmd_send(at_send_adv_buf, ret);
(来源:ble_at_char_client.c)
上报前会先把原始广播数据用 hex_2_str() 转为可读的十六进制文本:
ret = hex_2_str(adv_data_pt, lenght - 1, &at_send_adv_buf[5]);
at_cmd_send(at_send_adv_buf, ret + 5);
(来源:ble_at_char_client.c)
配置选项
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_APP_AT_CHAR_COM | 宏开关 | 由应用配置决定 | 编译开关;整个命令层代码以 #if CONFIG_APP_AT_CHAR_COM 包裹 |
G_VERSION | 字符串 | "JL_test" | AT+GVER 返回的固件版本号 |
CONFIG_VERSION | 字符串 | "2021_02_04" | AT+GCFGVER 返回的配置版本号 |
ADV_INTERVAL_DEFAULT | 数值 | 2048 | 默认广播间隔(单位:0.625ms 的倍数) |
PARSE_BUFFER_SIZE | 数值 | 256 | 解析缓冲区大小,限制单条 AT 命令总长 |
BT_UART_FIFIO_BUFFER_SIZE | 数值 | 0x100 | UART FIFO 缓冲区大小 |
TCFG_AT_UART_BAUDRATE | 数值 | 由板级配置决定 | AT UART 默认波特率,AT+BAUD 可查询/修改 |
cur_atcom_cid | 通道号 | 9 | AT 指令通道 ID(0-7 主机、8 从机、9 AT 指令) |
(配置默认值来源:at_char_cmds.h 与 at_char_cmds.c)
API 参考
以下接口声明均来自 at_char_cmds.h。
void at_cmd_init(void)
初始化 AT 命令层:清空解析缓冲区、复位通道状态。必须在应用启动早期调用一次(见 app_at_char_com.c 的调用点)。
void at_cmd_send(uint8_t *packet, int size)
向 AT 输出通道发送一段原始数据(通常为文本)。
参数:
packet(uint8_t*):待发送数据指针size(int):数据长度
说明: 这是所有响应与事件上报的统一出口,UART 与 BLE 特征两条输出路径都经过它。
void at_send_string(char *str)
以 C 字符串形式发送响应文本(内部按 strlen 计算长度)。
void at_send_connected(uint8_t cid) / void at_send_disconnect(uint8_t cid)
连接建立/断开事件上报;cid 为连接通道号,用于区分事件来自哪条 BLE 连接。
void at_send_rx_cid_data(uint8_t cid, uint8_t *packet, uint16_t size)
上报指定通道 cid 收到的数据,用于 BLE 数据透传场景。
void at_respond_send_err(int err_id)
发送错误响应(ERR,<err_id>)。错误码枚举:
enum {
ERR_AT_CMD = 1,
//add here
};
(来源:at_char_cmds.h)
uint32_t hex_2_str(uint8_t *hex, uint32_t hex_len, uint8_t *str) / uint32_t str_2_hex(uint8_t *str, uint32_t str_len, uint8_t *hex)
二进制与十六进制文本互转,返回转换后的字节数;用于广播数据、特征值的可读展示与反向解析。
uint8_t at_get_low_power_mode(void) / void at_set_low_power_mode(uint8_t enable)
低功耗模式查询/设置,供 AT+LOWPOWER 命令调用(声明见 at_char_cmds.c)。
失败模式、边界情况与并发
命令解析失败
- 未知命令名:命令名匹配
at_cmd_str_table失败时,进入错误分支并通过at_respond_send_err(ERR_AT_CMD)返回ERR,1;ERR_AT_CMD = 1是当前唯一的错误码,新增错误码应在枚举中"add here"处追加。 - 超长命令:
parse_buffer固定为PARSE_BUFFER_SIZE = 256字节,超过该长度的单条命令会被截断或解析失败。设计上通过限制缓冲区大小换取确定性的内存占用(该缓冲以NOT_KEEP_RAM+ 4 字节对齐声明,见 at_char_cmds.c),适合资源受限的嵌入式环境;如需更长的命令,需同步增大缓冲区并评估 RAM 余量。 - 参数数量/格式错误:参数以
,分隔并以at_param_t链表组织;处理分支需自行校验参数个数与取值范围(如AT+ADV=1的开关值)。错误参数通常落入 ERR 响应。
并发与数据一致性
at_param_t.len声明为volatile uint8_t,表明接收路径(UART 中断/轮询)与解析路径运行在不同上下文;解析期间应避免被新的接收数据覆盖parse_buffer,否则会产生半条命令解析。这是单缓冲区设计的固有权衡。- AT 指令通道号
cur_atcom_cid = 9与 BLE 数据通道(0-7 主机、8 从机)严格隔离,避免 AT 文本流与业务数据流互相污染;at_send_rx_cid_data()通过cid参数区分数据归属。
电源与连接边界
AT+POWEROFF直接触发关机流程,属于不可逆操作,应在固件中确认参数后才执行(源码中由处理分支调用电源管理接口)。AT+OTA会中断当前连接进入升级流程,升级期间 AT 命令层仍应保持响应能力,具体行为取决于ota处理分支与升级模块(testbox_uart_update.c/testbox_update.c)的配合。
性能与运维提示
- 输出热点:
at_cmd_send()是扫描结果、连接事件、数据透传的公共出口,高频事件(如持续扫描)会产生大量文本输出,建议结合 UART FIFO(BT_UART_FIFIO_BUFFER_SIZE = 0x100)与流控策略,避免丢字符。 - 十六进制转换开销:
hex_2_str/str_2_hex在每条广播/特征数据上报时都会执行,属 O(n) 线性转换;对大批量数据建议在采集端先压缩或仅上报摘要。 - 调试通道:
AT_CHAR_CMD日志标签已按 verbose/info/debug/warn/error 分级开放(见 log_config.c),排查命令未响应问题时优先打开该标签的d/e级日志。
扩展点
新增一条 AT 命令只需四步,全部集中在命令层:
- 在 at_char_cmds.h 的
STR_ID_*枚举中追加新 ID(建议延续0x20起的功能分区编号); - 在
at_char_cmds.c中定义命令字符串常量,如static const char at_str_xxx[] = "XXX";; - 在
at_cmd_str_table[]中以INPUT_STR_INFO(STR_ID_XXX, at_str_xxx)注册; - 在命令分发处新增
case STR_ID_XXX:处理分支,按AT_CMD_OPT_GET/SET区分查询与设置,成功返回OK,失败调用at_respond_send_err()。
由于输入(UART/BLE)与输出(at_cmd_send)均与命令表解耦,新增命令不触碰底层传输代码;若需要新增命令头(如第三个 AT# 前缀),则需同步扩展 at_head_str_table 与 specialchar[]。