这个页面的 最新开发版本 可能比这个发布的 2.4-rc 版本新。

AT 命令集

本章将具体介绍如何使用各类 AT 命令。

强烈建议在使用命令之前先阅读以下内容,了解 AT 命令的一些基本信息。

AT 命令默认使用 UART1 ,波特率 115200,数据位 8位,停止位 1位,无奇偶校验,无流控。 可以在 menuconfig 菜单中自行选择为其它串口,选择其它串口时建议不要和 LOG 串口混用,避免交互干扰。

当运行 AT 示例工程,发现发送 AT 命令无响应的场景,请先检查是否与上位机相连接的 W80X 开发板 UART 口是正确的。

AT命令分类

通用 AT 命令有四种类型:

类型

命令格式

说明

测试命令

AT+<命令名称>=?

查询设置命令的内部参数及其示例命令

查询命令

AT+<命令名称>?

返回当前参数值

设置命令

AT+<命令名称>=<…>

设置用户自定义的参数值,并运行命令

执行命令

AT+<命令名称>

运行无用户自定义参数的命令

  • 不是每条 AT 命令都具备上述四种类型的命令。

  • 命令里输入参数,当前只支持字符串参数和整形数字参数。

  • 尖括号 < > 内的参数不可以省略。

  • 方括号 [ ] 内的参数可以省略,省略时使用默认值。例如,运行 AT+CWJAP 命令时省略某些参数:

AT+CWJAP="WinnerMicro","12345678"
AT+CWJAP="WinnerMicro","12345678","11:22:33:44:55:66"
  • 当省略的参数后仍有参数要填写时,必须使用 ,,以示分隔,如:

AT+CWJAP="ssid","password",,1
  • 使用双引号表示字符串参数,如:

AT+CWSAP="WinnerMicro","12345678",1,4
  • 特殊字符需作转义处理,如 ,"\ 等。

    • \\:转义反斜杠。

    • \,:转义逗号,分隔参数的逗号无需转义。

    • \":转义双引号,表示字符串参数的双引号无需转义。

    • \<any>:转义 <any> 字符,即只使用 <any> 字符,不使用反斜杠。

  • 只有 AT 命令 中的特殊字符需要转义,其它地方无需转义。例如,AT 命令口打印 > 等待输入数据时,该数据不需要转义。

AT+CWJAP="comma\,backslash\\ssid","1234567890"
AT+MQTTPUB=0,"topic","\"{\"sensor\":012}\"",1,0
  • 每条 AT 命令的长度不应超过 256 字节。

  • AT 命令以新行 (CR-LF) 结束,所以串口工具应设置为“新行模式”。

参数信息保存在 flash 中的 AT 命令

以下 AT 命令的参数更改将始终保存在 flash 的 NVS 区域中,因此重启后,会直接使用。

备注

AT 命令里的参数保存,是通过 NVS 库实现的。因此,如果命令配置相同的参数值,则不会写入 flash;如果命令配置不同的参数值,flash 也不会被频繁擦除。

AT消息

从 WinnerMicro-AT 命令端口返回的 WinnerMicro-AT 消息有两种类型:WinnerMicro-AT 响应(被动)和 WinnerMicro-AT 消息报告(主动)。

  • WinnerMicro-AT 响应(被动)

    每个输入的 WinnerMicro-AT 命令都会返回响应,告诉发送者 WinnerMicro-AT 命令的执行结果。响应的最后一条消息必然是 OK 或者 ERROR

    WinnerMicro-AT 响应

    AT 响应

    说明

    OK

    AT 命令处理完毕,返回 OK

    ERROR

    AT 命令错误或执行过程中发生错误

    SEND OK

    数据已发送到协议栈(针对于 AT+CIPSENDAT+CIPSENDEX 命令),但不代表数据已经发到对端

    SEND FAIL

    向协议栈发送数据时发生错误(针对于 AT+CIPSENDAT+CIPSENDEX 命令)

    +<Command Name>:...

    详细描述 AT 命令处理结果

    CMD FORMAT ERR

    没有 该 AT 命令

    CMD PARSE ERR

    命令解析错误,一般为该 AT 的参数没有按照要求的格式输入

  • WinnerMicro-AT 消息报告(主动)

    WinnerMicro-AT 会报告系统中重要的状态变化或消息。

    WinnerMicro-AT 消息报告

    WinnerMicro-AT 消息报告

    说明

    busy …

    系统繁忙,正在处理上一条命令,无法处理新的命令

    WIFI CONNECTED

    Wi-Fi station 接口已连接到 AP

    WIFI GOT IP

    Wi-Fi station 接口已获取 IPv4 地址

    WIFI DISCONNECT

    Wi-Fi station 接口已与 AP 断开连接

    [<conn_id>,]CONNECT

    ID 为 <conn_id> 的网络连接已建立(默认情况下,ID 为 0)

    [<conn_id>,]CLOSED

    ID 为 <conn_id> 的网络连接已断开(默认情况下,ID 为 0)

    +STA_CONNECTED: <sta_mac>

    station 已连接到 WinnerMicro-AT 的 Wi-Fi softAP 接口

    +DIST_STA_IP: <sta_mac>,<sta_ip>

    WinnerMicro-AT 的 Wi-Fi softAP 接口给 station 分配 IP 地址

    +STA_DISCONNECTED: <sta_mac>

    station 与 WinnerMicro-AT 的 Wi-Fi softAP 接口的连接断开

    +IPD

    WinnerMicro-AT 在非透传模式下,已收到来自网络的数据。有以下的消息格式:

    • 如果 AT+CIPMUX=0,AT+CIPRECVMODE=1,打印:+IPD,<length>

    • 如果 AT+CIPMUX=1,AT+CIPRECVMODE=1,打印:+IPD,<link_id>,<length>

    • 如果 AT+CIPMUX=0,AT+CIPRECVMODE=0,AT+CIPDINFO=0,打印:+IPD,<length>:<data>

    • 如果 AT+CIPMUX=1,AT+CIPRECVMODE=0,AT+CIPDINFO=0,打印:+IPD,<link_id>,<length>:<data>

    • 如果 AT+CIPMUX=0,AT+CIPRECVMODE=0,AT+CIPDINFO=1,打印:+IPD,<length>,<"remote_ip">,<remote_port>:<data>

    • 如果 AT+CIPMUX=1,AT+CIPRECVMODE=0,AT+CIPDINFO=1,打印:+IPD,<link_id>,<length>,<"remote_ip">,<remote_port>:<data>

    其中的 link_id 为连接 ID,length 为数据长度,remote_ip 为远端 IP 地址,remote_port 为远端端口号,data 为数据。

    注意:当这是个 SSL 连接时,在被动接收模式下(AT+CIPRECVMODE=1),AT 命令口回复的 length 可能和实际可读的 SSL 数据长度不一致。因为 AT 会优先返回 SSL 层可读的数据长度,如果 SSL 层可读的数据长度为 0,AT 会返回套接字层可读的数据长度。

自定义 AT 命令

本章将具体介绍如何进行 AT 二次开发。

命令注册

typedef struct wm_atcmd_item {
    char *cmd_name;
    wm_atcmd_act cmd_handle;
#if CONFIG_WM_ATCMD_USAGE_ENABLE
    char *cmd_usg;
#endif /* CONFIG_WM_ATCMD_USAGE_ENABLE */
} wm_atcmd_item_t;

#define WM_ATCMD_SECTION                    ".wm_at_table"

#if CONFIG_WM_ATCMD_USAGE_ENABLE
#define WM_ATCMD_DEFINE(cmd, func, usage)                                                                  \
    static const struct wm_atcmd_item __atcmd_##func __attribute__((used, section(WM_ATCMD_SECTION))) =    \
    {                                                                                                      \
        .cmd_name  = cmd,                                                                                  \
        .cmd_handle = func,                                                                                \
        .cmd_usg = usage,                                                                                  \
    };
#else /* CONFIG_WM_ATCMD_USAGE_ENABLE */
#define WM_ATCMD_DEFINE(cmd, func, usage)                                                                  \
    static const struct wm_atcmd_item __atcmd_##func __attribute__((used, section(WM_ATCMD_SECTION))) =    \
    {                                                                                                      \
        .cmd_name  = cmd,                                                                                  \
        .cmd_handle = func,                                                                                \
    };
#endif /* CONFIG_WM_ATCMD_USAGE_ENABLE */
  • cmd_name是一个字符指针,可以用来存储命令的名称。

  • cmd_handle是一个类型为wm_atcmd_act的成员,是一个函数指针,可以用来处理特定的命令。

  • cmd_usg是一个字符指针,用来存储AT命令的help信息。

设备注册

typedef struct wm_atcmd_dev {
  wm_atcmd_dev_type_e type;
  wm_dev_ops_t ops;
} wm_atcmd_dev_t;
typedef enum wm_atcmd_dev_type {
   WM_ATCMD_DEV_TYPE_UART = 0,
   WM_ATCMD_DEV_TYPE_WIFI,
   WM_ATCMD_DEV_TYPE_BT,
   WM_ATCMD_DEV_TYPE_BLE,
   WM_ATCMD_DEV_TYPE_MAX
} wm_atcmd_dev_type_e;
  • 为了向 AT 注册不同的设备,上述结构体包括了设备类型、设备发送和接收的能力。

  • wm_atcmd_dev_type:设备的类型,用于区分不同类型的设备。

  • wm_dev_ops_t:操作接口,用于定义设备的各种操作或方法。

指令类型

AT_TYPE_QUERY = 0, //?    是询问或查询类型的AT指令 。
AT_TYPE_TEST  = 1, //=?   是测试或验证类型的AT指令。
AT_TYPE_EXEC  = 2,        是执行或操作类型的AT指令。
AT_TYPE_MAX               枚举类型的最大值

AT返回值

WM_AT_RESULT_OK = 0,              /* AT result Ok */  表示AT指令执行成功,值为0
WM_AT_RESUT_FAIL,                /* AT result have a generic error */  表示AT指令执行失败,这是一个通用错误
WM_AT_RESULT_NULL,              /* AT result no string return */   表示AT指令没有返回任何字符串结果
WM_AT_RESULT_CMD_ERR,          /* AT command can not find */     表示AT指令无法找到或不存在。
WM_AT_RESULT_PARSE_FAIL,      /* AT command parse  error */     表示AT指令解析错误。
AT_RESULT_MAX     枚举最大值

AT 命令的 meunconfig 配置

主要配置如下:

配置名称

配置描述

默认值

CONFIG_COMPONENT_WM_ATCMD_ENABLED

是否启用 AT 命令组件

N

CONFIG_WM_ATCMD_BT_ENABLE

是否启用蓝牙 AT 命令

N

CONFIG_WM_ATCMD_SYS_ENABLE

是否启用系统 AT 命令

Y

CONFIG_WM_ATCMD_TCP_ENABLE

是否启用 TCP AT 命令

Y

CONFIG_WM_ATCMD_MQTT_ENABLE

是否启用 MQTT AT 命令

N

CONFIG_WM_ATCMD_HTTP_ENABLE

是否启用 HTTP AT 命令

Y

CONFIG_WM_ATCMD_OTA_ENABLE

是否启用 OTA AT 命令

Y

CONFIG_WM_ATCMD_FS_ENABLE

是否启用文件系统 AT 命令

Y

CONFIG_WM_ATCMD_PWM_ENABLE

是否启用 PWM AT 命令

Y

CONFIG_WM_ATCMD_I2C_ENABLE

是否启用 I2C AT 命令

Y

CONFIG_WM_ATCMD_SPIM_ENABLE

是否启用 SPI Master AT 命令

Y

API介绍

1 初始化AT命令

/**
* @brief     init atcmd model
*
* @param     void
*
* @return
*    - WM_ERR_SUCCESS: succeed
*    - others: failed
*/
int wm_atcmd_init(void);

2 AT设备的注册

/**
* @brief     register atcmd dev ops
*
* @param     dev_type  device type
*            ops       device ops func
*
* @return
*    - WM_ERR_SUCCESS: succeed
*    - others: failed
*/
int wm_atcmd_dev_register(wm_atcmd_dev_type_e dev_type, wm_dev_ops_t ops);

3 AT向终端输出打印信息

 /**
 * @brief     print result
 *
 * @param     format  format str
 *
 * @return    None
 */
void wm_atcmd_print_result(char *format,...);

4 AT进入透传

 /**
 * @brief     enter passthrough mode
 *
 * @param     pt_tx_handle  passthrough tx func
 *            priv          user private data
 *            pt_exit_notify passthrough exit notify func
 *            timeout       passthrough timeout
 *
 * @return    None
 */
void wm_atcmd_enter_passthrough(wm_atcmd_tx_passthrough pt_tx_handle, wm_atcmd_tx_passthrough_exit_notify pt_exit_notify, void *priv, uint32_t timeout);

5 AT退出透传

/**
* @brief     exit passthrough mode
*
* @param     reason  exit reason
*
* @return    None
*/
void wm_atcmd_exit_passthrough(wm_atcmd_exit_passthrough_reason_e reason);

DEMON 演示

#include <stdio.h>
#include <string.h>

#include "wm_atcmd.h"
#include "wm_drv_uart.h"

void uart1_init(void)
{
    wm_drv_uart_options_s uart_option;

    memset(&uart_option, 0, sizeof(uart_option));
    uart_option.baudrate = WM_DRV_UART_BAUD_RATE_B115200;
    uart_option.data_bits = WM_DRV_UART_DATA_8BITS;
    uart_option.flow_ctrl = WM_DRV_UART_FLOW_CTRL_NONE;
    uart_option.parity_type = WM_DRV_UART_PARITY_DISABLED;
    uart_option.stop_bits = WM_DRV_UART_ONE_STOP_BITS;
    uart_option.event_callback = wm_at_uart_rx_callback;

    wm_drv_uart_init(ATCMD_UART_INDEX, &uart_option);
}

static int wm_cmd_test1(wm_at_type_e type, int argc, char **argv)
{
    if (AT_TYPE_QUERY == type)
    {
        wm_atcmd_print_result("这个用来查询用户自定义AT命令的参数,并返回当前值。\r\n");

        return WM_AT_RESULT_OK;
    }
    else if (AT_TYPE_EXEC == type)
    {
        /* do some things... */
        wm_atcmd_print_result("这个用来设置用户自定义AT命令的参数值,并运行此命令。\r\n");

        return WM_AT_RESULT_OK;
    }
    else if (AT_TYPE_TEST == type)
    {
        wm_atcmd_print_result("这个用来设置用户自定义AT命令的help信息。\r\n");

        return WM_AT_RESULT_OK;
    }
    else
    {
        return WM_AT_RESULT_FAIL;
    }
}

/* 注册AT命令的第三个参数可以填写成NULL,表示使用用户在命令中定义的help信息;也可以将第三个参数设置成help信息的字符串,表示使用参数设置的help信息。 */
WM_ATCMD_DEFINE("AT+TEST1",  wm_cmd_test1,  NULL)

int main(void)
{
    wm_dev_ops_t ops;
    int err = wm_atcmd_init();

    if (!err)
    {
        wm_log_info("atcmd init finished.");
    }
    else
    {
        wm_log_error("atcmd init failed.");
    }

    uart1_init();
    ops.atcmd_recv = atcmd_recv;
    ops.atcmd_send = atcmd_send;
    wm_atcmd_dev_register(WM_ATCMD_DEV_TYPE_UART, ops);

    return 0;
}