cAT AT 命令解析器无端请求示例
源码位置: samples/subsys/cAT/unsolicited 查看源码
功能说明
演示 cAT 库的无端请求(Unsolicited Response)功能,即服务器主动向客户端发送未经请求的响应,用于异步事件通知和多条响应发送。
本示例模拟无线扫描操作,接收单个 AT+START 命令后,系统返回多条扫描结果,最后发送 OK。
硬件连接
UART1_TX (PB2): 传输数据,连接到 USB-UART 转接器的 RX
UART1_RX (PB3): 接收数据,连接到 USB-UART 转接器的 TX
连接到 PC 串口工具,配置为 115200, 8N1, 无流控
示例内容
本示例演示以下功能:
HOLD 状态返回: 命令处理器返回
CAT_RETURN_STATE_HOLD,暂时不发送 OK多条异步响应: 通过
cat_trigger_unsolicited_read()主动发送多条无端响应异步事件处理: 模拟后台扫描操作,逐条返回扫描结果
HOLD 状态退出: 扫描完成后调用
cat_hold_exit()发送 OK 并退出 HOLD 状态模式切换: 支持 WiFi (0) 和蓝牙 (1) 两种扫描模式
编译
重要提示:在编译前,请先确认您使用的开发板型号。SDK 目前支持以下开发板:
arcs_evb - ARCS EVB 评估板
arcs_mini - ARCS Mini 开发板
根据您的开发板型号,选择对应的编译命令:
在示例目录下执行编译:
# 使用 arcs_evb 开发板
./build.sh -C -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -DBOARD=arcs_mini
Note
如果在 SDK 根目录执行,需要指定示例路径:
# 使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_mini
Note
确保已安装对应的工具链。
烧录
编译完成后,使用 SDK tools 目录下的 cskburn 工具烧录固件:
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs
Note
烧录参数说明:
-s /dev/ttyUSB0:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是/dev/ttyUSB0或/dev/ttyACM0- 可通过ls /dev/tty*命令查看可用串口设备 - 不同开发板或 USB 转串口芯片可能使用不同的设备名-b 3000000:烧录波特率(3Mbps)0x0:烧录起始地址build/arcs.bin:编译生成的固件路径-C arcs:芯片类型
注意事项:
确保开发板已正确连接到电脑
如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口
预期输出
系统启动输出:
[I][cat_unsolicited] cAT AT Command Parser - Unsolicited Example
[I][cat_unsolicited] ============================================
[I][cat_uart] cAT UART adapter initialized on uart1 @ 115200 baud
[I][cat_unsolicited] AT command parser ready on uart1
[I][cat_unsolicited] Supported AT commands:
[I][cat_unsolicited] +START - Start scanning (0=WiFi, 1=Bluetooth)
[I][cat_unsolicited] +SCAN - Scan result record (unsolicited)
[I][cat_unsolicited] #HELP - Print command list
[I][cat_unsolicited] #QUIT - Quit the demo
[I][cat_uart] cAT UART task started
发送 AT+START=0 (WiFi 扫描) 后的输出:
[I][cat_unsolicited] Mode set to: 0 (WiFi)
[I][cat_unsolicited] Starting WiFi scan...
[I][cat_unsolicited] Sending scan result 0: RSSI=-10, SSID=wifi1
[I][cat_unsolicited] Sending scan result 1: RSSI=-50, SSID=wifi2
[I][cat_unsolicited] Sending scan result 2: RSSI=-20, SSID=wifi3
[I][cat_unsolicited] Scan complete, sent 3 results
+SCAN: -10,"wifi1"
+SCAN: -50,"wifi2"
+SCAN: -20,"wifi3"
OK
发送 AT+START=1 (蓝牙扫描) 后的输出:
[I][cat_unsolicited] Mode set to: 1 (Bluetooth)
[I][cat_unsolicited] Starting Bluetooth scan...
[I][cat_unsolicited] Sending scan result 0: RSSI=-20, SSID=bluetooth1
[I][cat_unsolicited] Scan complete, sent 1 results
+SCAN: -20,"bluetooth1"
OK
发送 AT+HELP 后的输出:
+HELP: +START(WR),+SCAN(TEST),#HELP(RUN),#QUIT(RUN)
OK
核心 API
API |
说明 |
|---|---|
|
初始化 UART 适配器 |
|
获取 IO 接口 |
|
获取互斥锁接口(支持递归锁) |
|
初始化 AT 命令解析器 |
|
触发无端响应 |
|
退出 HOLD 状态 |
|
发送无端响应(备选) |
关键代码
定义扫描结果数据:
/* 静态扫描结果 - 模拟 WiFi 和蓝牙 */
struct scan_results {
int rssi;
char ssid[16];
};
static const struct scan_results results[2][3] = {
/* WiFi 结果 */
{
{ .rssi = -10, .ssid = "wifi1" },
{ .rssi = -50, .ssid = "wifi2" },
{ .rssi = -20, .ssid = "wifi3" }
},
/* 蓝牙结果 */
{
{ .rssi = -20, .ssid = "bluetooth1" },
{ .rssi = 0, .ssid = "" },
{ .rssi = 0, .ssid = "" }
}
};
START 命令处理器(返回 HOLD 状态):
/* AT+START=<mode> - 启动扫描 */
static cat_return_state start_write(const struct cat_command *cmd, const uint8_t *data,
const size_t data_size, const size_t args_num)
{
LOGI("Starting %s scan...", (mode == 0) ? "WiFi" : "Bluetooth");
/* 重置扫描状态 */
scan_index = 0;
scan_completed = false;
/* 加载第一条扫描结果 */
load_scan_results(scan_index);
/* 触发第一条无端响应 */
cat_trigger_unsolicited_read(&at, &scan_cmd);
/* 返回 HOLD - 暂不发送 OK,等待异步操作完成 */
return CAT_RETURN_STATE_HOLD;
}
SCAN 命令读取处理器(处理无端响应):
/* 无端读取回调 - 每条扫描结果调用一次 */
static cat_return_state scan_read(const struct cat_command *cmd, uint8_t *data,
size_t *data_size, const size_t max_data_size)
{
int max = (mode == 0) ? 3 : 1;
if (scan_completed) {
return CAT_RETURN_STATE_OK;
}
LOGI("Sending scan result %d: RSSI=%d, SSID=%s", scan_index, rssi, ssid);
scan_index++;
/* 如果还有更多结果,触发下一条 */
if (scan_index < max) {
load_scan_results(scan_index);
cat_trigger_unsolicited_read(&at, &scan_cmd);
return CAT_RETURN_STATE_DATA_NEXT; /* 继续下一条 */
}
/* 最后一条结果 - 完成后退出 HOLD 状态 */
LOGI("Scan complete, sent %d results", scan_index);
scan_completed = true;
cat_hold_exit(&at, CAT_STATUS_OK); /* 发送 OK 并退出 HOLD */
return CAT_RETURN_STATE_DATA_OK; /* 最后一条数据 */
}
模式验证器:
/* MODE 变量的写入验证器 */
static int mode_write(const struct cat_variable *var, const size_t write_size)
{
if (*(int *)var->data >= 2) {
LOGE("Invalid mode: %d (must be 0 or 1)", *(int *)var->data);
return -1;
}
LOGI("Mode set to: %d (%s)", *(int *)var->data,
(*(int *)var->data == 0) ? "WiFi" : "Bluetooth");
return 0;
}
SCAN 命令定义:
/* 定义扫描结果变量 */
static struct cat_variable scan_vars[] = {
{
.type = CAT_VAR_INT_DEC,
.data = &rssi,
.data_size = sizeof(rssi),
.name = "RSSI",
.access = CAT_VAR_ACCESS_READ_ONLY,
},
{
.type = CAT_VAR_BUF_STRING,
.data = ssid,
.data_size = sizeof(ssid),
.name = "SSID",
.access = CAT_VAR_ACCESS_READ_ONLY,
}
};
/* SCAN 命令 - 仅用于无端响应,标记为 only_test */
static struct cat_command scan_cmd = {
.name = "+SCAN",
.description = "Scan result record",
.read = scan_read,
.var = scan_vars,
.var_num = sizeof(scan_vars) / sizeof(scan_vars[0])
};
注意事项
递归 Mutex: 示例使用递归互斥锁支持无端事件的触发。在 HOLD 状态的命令处理中调用
cat_trigger_unsolicited_read()时,需要重新获取锁HOLD 状态管理:
返回
CAT_RETURN_STATE_HOLD使命令进入 HOLD 状态,暂停发送 OK返回
CAT_RETURN_STATE_DATA_NEXT继续发送下一条响应返回
CAT_RETURN_STATE_DATA_OK发送最后一条响应调用
cat_hold_exit()退出 HOLD 状态并发送 OK
无端响应流程:
1. 用户发送 AT+START=0 2. start_write() 返回 HOLD,调用 cat_trigger_unsolicited_read() 3. scan_read() 被调用发送第一条 +SCAN 结果 4. 返回 DATA_NEXT,再次调用 cat_trigger_unsolicited_read() 5. 重复直到最后一条结果 6. 最后一条返回 DATA_OK 并调用 cat_hold_exit() 7. 发送 OK 并退出 HOLD 状态
线程安全: UART 任务中所有 cAT 操作都受递归互斥锁保护,可安全调用
cat_trigger_unsolicited_read()响应变量: 无端响应中的变量值必须在回调被调用前设置正确(如
rssi和ssid)错误处理: 如果参数验证失败(mode >= 2),回调返回 -1 会导致命令返回 ERROR
命令参考
命令 |
说明 |
示例 |
|---|---|---|
|
开始扫描 (0=WiFi, 1=Bluetooth) |
|
|
显示 SCAN 格式 |
|
|
列出所有命令 |
|
|
退出示例 |
|
扩展建议
实时扫描: 替换静态结果数据,接收来自实际 WiFi/蓝牙 驱动的扫描结果
扫描进度: 返回 DATA_NEXT 时可添加进度信息(如 “Scan 30% complete”)
超时处理: 在 HOLD 状态下实现扫描超时机制,防止命令无限期挂起
并发操作: 支持在扫描过程中处理其他 AT 命令(使用任务安全机制)
结果缓存: 存储扫描结果供后续查询,实现增量式结果返回
无端响应原理
无端响应是一种经典的 AT 命令扩展模式,允许设备在不进行直接查询的情况下主动通知主机事件发生。
典型应用场景:
信号强度实时通知 (Signal Strength Unsolicited Result Code)
来电提示 (Incoming Call Notification)
短信接收通知 (SMS Reception Notification)
网络状态变化 (Network Status Change)
外设事件通知 (Peripheral Events)
本示例通过模拟扫描结果演示了这一模式的完整实现。