精华内容
下载资源
问答
  • AT命令

    千次阅读 2019-06-04 21:28:41
    AT命令最常见的应用场景: 1、智能手机:一般智能手机都是一个主芯片控制一个通信模块,这个通信模块就是一个完整的、简单的手机,包括手机应该有的射频、基带等部分,还有GSM协议栈,完全可以独立打电话、发短信、...

    AT命令最常见的应用场景:

    1、智能手机:一般智能手机都是一个主芯片控制一个通信模块,这个通信模块就是一个完整的、简单的手机,包括手机应该有的射频、基带等部分,还有GSM协议栈,完全可以独立打电话、发短信、用GPRS上网等。主芯片实现复杂的应用软件。主芯片和通信模块之间通过AT命令,也就是做主芯片通过AT命令控制通信模块打电话,发短信等。
    2、其他通信模块。例如出租车上的车载台,通信模块可以接收控制中心发来的短信,进行车辆调度,或者利用GSM中的位置服务—— 一种补充业务,可以实现大致的定位,控制中心可以对出租车做简单的位置跟踪。

    简单的说,无线通讯中有一种产品就是把一个简单的手机做成半成品,这个半成品可以通过AT命令控制来实现发短信,打电话,gprs上网等无线通讯功能,业界把这种产品叫做模块/无线模块。然后这个半成品卖给集成商,集成商在产品中挂载一个这样的无线模块,这个无线模块受主芯片控制。集成商可以用这种方式做出不同应用的产品,例如智能手机。其中AT命令是主芯片和无线模块的协议接口,硬件接口一般使用串口。

    用户可以通过AT指令进行呼叫、短信、电话本、数据业务、传真等方面的控制。90年代初,AT指令仅被用于Modem操作。没有控制移动电话文本消息的先例,只开发了一种叫SMS BlockMode的协议,通过终端设备(TE)或电脑来完全控制SMS。

    几年后,主要的移动电话生产厂商诺基亚、爱立信、摩托罗拉和HP共同为GSM 研制了一整套AT指令,其中就包括对SMS的控制。AT指令在此基础上演化并被加入GSM 07.05标准以及现在的GSM07.07标准,完全标准化和比较健全的标准。如:对SMS的控制共有3种实现途径:

    • 最初的Block Mode;
    • 基于AT指令的Text Mode;
    • 基于AT指令的PDU Mode。

    到现在PDU Mode已经取代BlockMode,后者逐渐淡出。GSM 模块与计算机之间的通信协议是一些AT指令集,AT指令是以AT作首, 字符结束的字符串,AT指令的响应数据包在中。每个指令执行成功与否都有相应的返回。其他的一些非预期的信息(如有人拨号进来、线路无信号等),模块将有对应的一些信息提示,接收端可做相应的处理。

    示例:
    CDMA modem DTE
    AT< CR>
    < LF> OK < LF>
    ATTEST< CR>
    < CR> ERROR < LF>
    如果AT指令执行成功,“OK”字符串返回;
    如果AT 指令语法错误或AT 指令执行失败,
    “ERROR”字符串返回。

    AT命令详解版:https://blog.csdn.net/bytxl/article/details/25614491

    AT命令的使用

    microcom -s 115200 /dev/ttyUSB2

    1.准备测试

    检测Module与串口是否连通,能否接收AT命令: AT

    查看SIM卡是否到位: AT+CPIN?

    测试信号: AT+CSQ

    查看运营商: AT+COPS?

    获取模块标识: AT+CGMM

    获取模块厂商标识: AT+CGMI

    查看SIM卡是否到位: AT+CPIN?

    网络注册,获得手机的注册状态: AT+CREG?

    2.拨打电话

    拨打电话: ATD电话号码;

    来电显示: AT+CLCC(有电话打过来串口会打印RING提示。)

    接电话: ATA

    挂电话: ATH

    挂电话尚未接通的来电: AT+CHUP

    3.发短信

    短信的编码方式有两种:text模式,pdu模式。因此短信的AT指令执行格式也有两种,分别对应text模式和pdu模式。

    1 . Text模式

    纯文本模式,支持不同的字符集,从技术上说也可用于发送中文短消息,但国内手机基本上不支持,主要用于欧美地区。

    2 . Pdu模式

    这个是手机默认的编码方式,可以使用任何字符集,其包括三种编码方式:7bit编码,8bit编码,UCS2编码。

    7bit编码:ASCⅡ码就是7bit编码。

    8bit编码:ASCⅡ字符可以使用7位二进制表示,但是由于计算机的基本处理单位是字节(1byte=8bit),所以一般在高位补0,用一个字节表示一个ASCⅡ字符。这就是8bit编码。

    UCS2编码:处理Unicode字符,使用2个字节来表示一个字符,可以表示世界上所有的字符。发送中文就是使用此编码方式。

    发英文短信
    设置信息格式: AT+CMGF=1 (格式有TEXT方式和PDU方式。AT+CMGF=1时是TEXT方式,AT+CMGF=0是PDU方式)

    发送短信: AT+CMGS=“电话号码”
    下一行出现>后面跟的是发送的内容
    (以ctrl+z(0x1A)结束)

    例如:
    at+cmgs=“152XXXXXXXX”
    > ni hao
    (ctrl+z)

    设置收到短消息提示: AT+CNMI=1,1,2

    设置存储区域为SM: AT+CPMS=”SM”

    读取短信: AT+CMGR=index(index为读第几条短信)

    发中文短信:

    设置信息格式: AT+CMGF=0

    发中文短信这里暂时也不去了解,发中文短信可以参考:https://blog.csdn.net/a_tu_/article/details/47808017

    AT命令详解:https://blog.csdn.net/bytxl/article/details/25614491

    展开全文
  • AT命令工具

    2018-06-14 11:10:46
    可用于串口发送AT命令,绿色版免安装,具有命令记录功能,亲测可用
  • 常用AT命令手册 AT命令解释 ,对AT指令做了全面的解释
  • AT命令 AT命令及用法

    2009-08-24 15:19:34
    列出在指定的时间和日期在计算机上运行的已计划命令或计划命令和程序。必须正在运行“计划”服务才能使用 at 命令
  • AT命令简易解析 AT命令的应用场合很多,也是应用最为通用的命令。而AT命令并不像通信协议特定的数据帧格式,解析AT命令需要匹配每个字符。AT命令一般有三种状态:查询、执行、设置,根据这三种状态,本文将使用一种...
  • AT命令全接触_包括基本AT/高级AT/语音AT/传真ATdoc,AT命令全接触_包括基本AT/高级AT/语音AT/传真AT
  • AT命令详解

    2012-12-10 10:47:10
    1.AT命令名词解析 2.AT命令的使用和返回结果分析
  • AT编程及AT命令

    2009-12-12 18:59:00
    AT编程 AT命令AT命令 AT编程 AT命令AT命令
  • linux命令at 命令

    千次阅读 2019-01-25 11:02:23
    at命令允许指定Linux系统何时运行脚本,at命令会将作业提交到队列中,指定shell在何时运行该作业。at的守护进程atd会以后台模式运行,检查作业队列来运行作业。atd守护进程会检查系统上的一个特殊目录来获取at命令的...

    linux命令:at 命令

    at 命令简介

    at命令允许指定Linux系统何时运行脚本,at命令会将作业提交到队列中,指定shell在何时运行该作业。at的守护进程atd会以后台模式运行,检查作业队列来运行作业。atd守护进程会检查系统上的一个特殊目录来获取at命令的提交的作业。默认情况下,atd守护进程每60秒检查一次目录。有作业时,会检查作业运行时间,如果时间与当前时间匹配,则运行此作业。

    at 命令格式

    at (选项)(参数) 
    ctrl+D 结束at命令的输入
    

    在使用at命令的时候,一定要保证atd进程启动。

    ps -ef | grep atd 查看atd进程是否启动。如果没有启动使用 /etc/init.d/atd start or restart
    chkconfig atd on 设置atd开机启动
    

    命令参数

    -m 当指定的任务被完成之后,将给用户发送邮件,即使没有标准输出

    -I atq的别名. atq命令可以查看系统中等待的作业

    -d atrm的别名. atrm命令可以删除系统中的等待作业,后面加上要删除的作业id

    -v 显示任务将被执行的时间

    -c 打印任务的内容到标准输出

    -V 显示版本信息

    -q<列队> 使用指定的列队

    -f<文件> 从指定文件读入任务而不是从标准输入读入

    -t<时间参数> 以时间参数的形式提交要运行的任务

    时间设置

    at允许使用一套相当复杂的指定时间的方法。

    1. 能够接受在当天的hh:mm(小时:分钟)式的时间指定。假如该时间已过去,那么就放在第二天执行。

    2. 也能够使用midnight(深夜),noon(中午),teatime(饮茶时间,一般是下午4点)等比较模糊的 词语来指定时间。

    3. 用户还能够采用12小时计时制,即在时间后面加上AM(上午)或PM(下午)来说明是上午还是下午。

    4. 也能够指定命令执行的具体日期,指定格式为month day(月 日)或mm/dd/yy(月/日/年)或dd.mm.yy(日.月.年)。指定的日期必须跟在指定时间的后面。

    5. 上面介绍的都是绝对计时法,其实还能够使用相对计时法,这对于安排不久就要执行的命令是很有好处的。指定格式为:now + count time-units,now就是当前时间,time-units是时间单位,这里能够是minutes(分钟)、hours(小时)、days(天)、weeks(星期)。count是时间的数量,究竟是几天,还是几小时,等等。

    6. 更有一种计时方法就是直接使用today(今天)、tomorrow(明天)来指定完成命令的时间。

    示例

    1. 三天后的下午5点钟执行 /bin/ls
    at 5pm+3 days
    
    at> /bin/ls
    at> <EOT>
    
    1. 明天17点钟,输出时间到指定文件内
    ubuntu@ubuntu:~$ at 17:20 tomorrow
    warning: commands will be executed using /bin/sh
    at> date > /root/log.log
    at> <EOT>
    job 12 at Sat Jan 26 17:20:00 2019
    ubuntu@ubuntu:~$ 
    
    1. 计划任务设定后,在没有执行之前我们可以用atq命令来查看系统没有执行工作任务
    ubuntu@ubuntu:~$ atq
    12	Sat Jan 26 17:20:00 2019 a ubuntu
    ubuntu@ubuntu:~$ 
    
    1. 删除已经设置的任务
    atrm 12
    
    1. 显示已经设置的任务
    at -c 12
    

    参考文章:

    1. https://blog.csdn.net/jobschen/article/details/50673683
    2. http://www.cnblogs.com/peida/archive/2013/01/05/2846152.html
    展开全文
  • NBIOT-AT命令

    2018-11-05 17:12:23
    NBIOT的AT命令
  • CDMA at 命令

    2009-10-28 17:10:23
    CDMA at 命令介绍cdma 常用的 at命令
  • 中移M5310 AT命令

    2018-10-05 22:05:57
    中国移动M5310模组AT命令指导手册,详细介绍了每一条指令的含义以及指令的预期结果
  • ESP-AT 系列: 自定义 AT 命令

    千次阅读 2019-10-28 10:40:31
    一. 简介 虽然 ESP-AT 内部已经集成了很多指令, 比如 Wi-Fi, BT, BLE, IP 等等, 但是同时也支持客户进行二次...ESP-AT 命令包含 4 种命令格式: Test Command 示例: AT+<x>=? 用途: 查询 Set Command 的各个...

    一. 简介

    虽然 ESP-AT 内部已经集成了很多指令, 比如 Wi-Fi, BT, BLE, IP 等等, 但是同时也支持客户进行二次开发, 定义客户自己的命令.

    本文主要介绍客户如何自定义 AT 命令.

    1.1 ESP-AT 命令的四种格式

    ESP-AT 命令包含 4 种命令格式:

    • Test Command
      • 示例: AT+<x>=?
      • 用途: 查询 Set Command 的各个参数以及参数的范围
    • Query Command
      • 示例: AT+<x>?
      • 用途: 查询命令, 可以返回当前参数的值, 也可以返回其他一些想要得到的信息
    • Set Command
      • 示例: AT+<x>=<…>
      • 用途: 设置命令, 向AT输入一些参数, 执行相应的操作
    • Execute Command
      • 示例: AT+<x>
      • 用途: 执行指令, 该指令不带参数

    1.2 如何开始自定义一组 AT 命令

    首先, 我们看一下 ESP-AT 命令结构体的定义:

    typedef struct {
        char *at_cmdName;                               /*!< at command name */
        uint8_t (*at_testCmd)(uint8_t *cmd_name);       /*!< Test Command function pointer */
        uint8_t (*at_queryCmd)(uint8_t *cmd_name);      /*!< Query Command function pointer */
        uint8_t (*at_setupCmd)(uint8_t para_num);       /*!< Setup Command function pointer */
        uint8_t (*at_exeCmd)(uint8_t *cmd_name);        /*!< Execute Command function pointer */
    } esp_at_cmd_struct;
    

    这个结构体中包含 5 个元素, 第一个是个字符串指针, 是 AT 命令的名字, AT 命令的名字有一定的格式要求, 都是+开始. 后面跟着四个函数参数指针, 分别对应上面提到的四种命令.

    现在我们首先举个简单的例子, 定义一个命令, 用来输出Hello word.

    定义命令:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+EXAMPLE", NULL, NULL, NULL, NULL},
    };
    

    这样, 这条命令就定义好了, 命令的名字叫 +EXAMPLE, 实际用起来的时候,用户输入的命令就是这个样子:

    • AT+EXAMPLE=?
    • AT+EXAMPLE?
    • AT+EXAMPLE=<param_1>,<param_2>,<param_3>…
    • AT+EXAMPLE

    当然, 仅仅这样, 还是远远不够的, 要想真的用起来, 至少还少 2 个步骤, 首先就是注册这组命令, 其次就是添加命令的具体实现.

    注册命令:

    注册自定义命令数组需要用 API:

    bool esp_at_custom_cmd_array_regist(const esp_at_cmd_struct *custom_at_cmd_array, uint32_t cmd_num);
    

    注册客户自定义命令的代码需要加到 app_main() 里, 建议放在 app_main() 的最后 at_custom_init(); 之前, 参考代码如下:

    bool esp_at_example_cmd_regist(void)
    {
        return esp_at_custom_cmd_array_regist(at_example_cmd, sizeof(at_example_cmd) / sizeof(at_example_cmd[0]));
    }
    
    void app_main()
    {
        ...
        
        if(esp_at_example_cmd_regist() == false) {
            printf("regist example cmd fail\r\n");
        }
        
        at_custom_init();
    }
    

    添加命令的具体实现:

    刚次才我们定义的命令数组里, 四个回调函数都是 NULL, 其实还是什么都做不了的, 我们现在添加个实例函数, 来输出 Hello World.

    因为不需要带参数, 我们就用执行命令来实现吧, 示例代码如下:

    uint8_t at_exeCmdExample(uint8_t *cmd_name)
    {
        esp_at_port_write_data("Hello World", strlen("Hello World"));
        return ESP_AT_RESULT_CODE_OK;
    }
    

    同时修改命令数组如下:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+EXAMPLE", NULL, NULL, NULL, at_exeCmdExample},
    };
    

    如果想同时打印这条命令的名字, 可以将 cmd_name 也打印出来, 例如:

    uint8_t at_exeCmdExample(uint8_t *cmd_name)
    {
        esp_at_port_write_data((uint8_t *)cmd_name, strlen((char *)cmd_name));
        esp_at_port_write_data((uint8_t *)":Hello World\r\n",strlen(":Hello World"));
        return ESP_AT_RESULT_CODE_OK;
    }
    

    此时在终端打印信息是这样的:

    AT+EXAMPLE
    +EXAMPLE:Hello Word
    
    OK
    

    如何添加多个命令

    上面的例子只有一个命令, 如果需要多个命令, 可以依次添加, 例如:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+EXAMPLE1", NULL, NULL, NULL, NULL},
        {"+EXAMPLE2", NULL, NULL, NULL, NULL},
        {"+EXAMPLE3", NULL, NULL, NULL, NULL},
        {"+EXAMPLE4", NULL, NULL, NULL, NULL},
        {"+EXAMPLE5", NULL, NULL, NULL, NULL},
    };
    

    二. ESP-AT 自定义命令进阶

    2.1 命令实现中, 不同返回值的区别

    在上面的 Hello Word 示例中, 我们在 at_exeCmdExample() 最后返回了 ESP_AT_RESULT_CODE_OK, 这个返回值的作用就是命令执行完毕之后, 输出字符 "OK".

    ESP-AT 中, 返回值不止这一个, 而且每个效果都不同, 我们先看一下一共有哪些返回值

    /**
     * @brief the result code of AT command processing
     *
     */
    typedef enum {
        ESP_AT_RESULT_CODE_OK           = 0x00,       /*!< "OK" */
        ESP_AT_RESULT_CODE_ERROR        = 0x01,       /*!< "ERROR" */
        ESP_AT_RESULT_CODE_FAIL         = 0x02,       /*!< "ERROR" */
        ESP_AT_RESULT_CODE_SEND_OK      = 0x03,       /*!< "SEND OK" */
        ESP_AT_RESULT_CODE_SEND_FAIL    = 0x04,       /*!< "SEND FAIL" */
        ESP_AT_RESULT_CODE_IGNORE       = 0x05,       /*!< response nothing */
        ESP_AT_RESULT_CODE_PROCESS_DONE = 0x06,       /*!< response nothing */
    
        ESP_AT_RESULT_CODE_MAX
    } esp_at_result_code_string_index;
    
    

    从后面的注释能够看出, 不同的返回值可以输出 "OK", "ERROR", "SEND OK", "SEND FAIL", 或者处理结果的应答都没有.

    前面 3 个应该很好理解, 如果顺利执行完毕, 那么就返回 ESP_AT_RESULT_CODE_OK, 最终在串口上面会输出 "OK", 如果返回的是 ESP_AT_RESULT_CODE_ERROR,ESP_AT_RESULT_CODE_FAIL, 那么最终会在串口上面输出 "ERROR"

    ESP_AT_RESULT_CODE_SEND_OKESP_AT_RESULT_CODE_SEND_FAIL可以用在这样的一个场景, 比如基于TCP 连接发送一包数据, 这个时候发送失败了, 可以 return ESP_AT_RESULT_CODE_SEND_FAIL;, 如果发送成功了, 可以 return ESP_AT_RESULT_CODE_SEND_OK;

    除了通过 return 返回值的方式, 向串口输出指令执行的结果, 我们还可以用另外一种方式来做:

    /**
     * @brief response AT process result,
     *
     * @param result_code see esp_at_result_code_string_index
     *
     */
    void esp_at_response_result(uint8_t result_code);
    

    假如您现在向服务器发送了一串数据, 然后您想先打印 "SEND OK", 然后等待服务器回应, 最后再退出函数, 您可以这样做:

    uint8_t at_exeCmdExample(uint8_t *cmd_name)
    {
    	 //send data to Server
    	 Send...
    	 
    	 // 先打印 SEND OK
    	 esp_at_response_result(ESP_AT_RESULT_CODE_OK);
    	 
    	 // 等待服务器回应, 具体的阻塞实现在下面会介绍
    	 wait...
    	 
    	 //最后返回 OK 
    	 //如果您在这里不想再输出 OK 了, 可以 return ESP_AT_RESULT_CODE_PROCESS_DONE;
        return ESP_AT_RESULT_CODE_OK;
    }
    
    

    ESP_AT_RESULT_CODE_IGNOREESP_AT_RESULT_CODE_PROCESS_DONE 的区别就是:

    ESP_AT_RESULT_CODE_IGNORE 不输出命令执行结果, 也不会有状态的切换, 仍处于处理当前命令的状态. 这个时候输入下一条命令, 会返回 busy.

    ESP_AT_RESULT_CODE_PROCESS_DONE 不输出命令执行结果, 但会将当前的状态切换到空闲状态, 可以处理下一条命令

    2.2 如何获取命令的参数

    上一节提到的设置命令, 该命令是需要带一些参数的, 参数可能不止一个, 类型也不尽相同, 有的是整形, 有的是字符串, 该怎么在回调函数中处理这些参数呢?我们还是举一个例子, 假如我们现在要去连接一个 TCP Server, 那么它的参数至少有两个, IP 地址和端口号, 我们约定他的命令是这个样子的:

    AT+TCP=<IP>,<port>
    

    其中, IP 地址是字符串, port 是数字.

    我们可以定义命令数组如下:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TCP", NULL, NULL, at_setupCmdTcp, NULL},
    };
    

    设置命令的具体实现如下:

    uint8_t at_setupCmdTcp(uint8_t para_num)
    {
        int32_t cnt = 0, value = 0;
        uint8_t* s = NULL;
        
        // 首先获取ip地址, 这是一个字符串, 如果失败, 会返回 ERROR
        if (esp_at_get_para_as_str(cnt++, &s) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        // 然后获取端口号, 同理, 如果失败, 也会返回错误
        if (esp_at_get_para_as_digit(cnt++, &value) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        // 最后再检查下参数个数, para_num 是用户输入的这条命令的参数个数, 如果不等于 2, 也可以报错
        if (para_num != cnt) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        // 下面就可以加入用户自己的处理代码了
        // TODO: 
        
        return ESP_AT_RESULT_CODE_OK;
    }
    

    这里需要关注这样的几点:

    • param_num 是用户实际输入的参数个数, 每个参数之间是以,隔开
    • esp_at_para_parse_result_type esp_at_get_para_as_digit(int32_t para_index, int32_t *value);用于获取整形数据
    • esp_at_para_parse_result_type esp_at_get_para_as_str(int32_t para_index, uint8_t **result);用于获取字符串参数

    2.3 如何处理可选参数

    有的时候, 可能有些参数是可选, 也就是可变参数.

    这个时候涉及到两种情况, 一种省略的是第一个或者中间的参数, 另一种是省略最后的部分, 省略第一个参数和省略中间参数的处理方式相同.

    2.3.1 省略的是中间的参数

    这种情况, 命令的定义一般是这样的:

    AT+TESTCMD=<parm_1>[,<param_2>],<param_3>
    

    约定中间的参数 param_2 可以省略, 它的类型是整形, 另外两个参数 param_1 是整形, param_3 是字符串.

    示例代码如下:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TESTCMD", NULL, NULL, at_setupCmdTestCmd, NULL},
    };
    
    uint8_t at_setupCmdTestCmd(uint8_t para_num)
    {
        int32_t cnt = 0, value = 0;
        uint8_t* s = NULL;
        esp_at_para_parse_result_type parse_result = ESP_AT_PARA_PARSE_RESULT_FAIL;
        
        // 首先获取第一个参数 param_1,他的类型是整形
        if (esp_at_get_para_as_digit(cnt++, &value) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        // 这里需要注意, 需要把 value 的值赋值给另外一个变量, 因为下面的代码会把 value 的值重置成另一个参数的值, 或者下面再获取整形参数值的时候, 用另外定义的变量
        // param_1 = value;
        
        // 现在处理第二个可选参数, 尝试下是否能获取到
        parse_result = esp_at_get_para_as_digit(cnt++, &value);
        if (parse_result != ESP_AT_PARA_PARSE_RESULT_OMITTED) {
            // 能走到这里, 说明这个可选参数没有被省略
            // 进一步判断返回值是不是OK
            // 需要注意, 例子这里举得是整形参数, 如果是字符串的话
            // 客户输入 "" 这样的空串也是会返回OK的, 只是字符串指针是 NULL
            if (parse_result != ESP_AT_PARA_PARSE_RESULT_OK) {
                return ESP_AT_RESULT_CODE_ERROR;
            }
            // param_2 = value;
        } else {
            // 走到这里, 说明用户没有输入第二个参数
            // 是不是用默认值, 还是做别的处理, 取决于客户自己的逻辑
        }
        
        // 现在获取最后一个参数 param_3
        if (esp_at_get_para_as_str(cnt++, &s) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        // param_3 = s;
        
        
        // 最后再检查下参数个数, para_num 是用户输入的这条命令的参数个数, 如果不等于3, 报错
        if (para_num != cnt) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        // 下面就可以加入用户自己的处理代码了
        // TODO: 
        
        return ESP_AT_RESULT_CODE_OK;
    }
    

    2.3.2 省略的是最后的参数

    这种情况, 命令的定义一般是这样的:

    AT+TESTCMD=<parm_1>,<param_2>[,<param_3>]
    

    约定最后的的参数 param_3 可以省略, 它的类型是整形, 另外两个参数 param_1 是整形, param_2 是字符串.

    省略的形式有两种, 例如:

    AT+TESTCMD=123,"abc"
    AT+TESTCMD=123,"abc",
    

    示例代码如下:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TESTCMD", NULL, NULL, at_setupCmdTestCmd, NULL},
    };
    
    uint8_t at_setupCmdTestCmd(uint8_t para_num)
    {
        int32_t cnt = 0, value = 0;
        uint8_t* s = NULL;
        esp_at_para_parse_result_type parse_result = ESP_AT_PARA_PARSE_RESULT_FAIL;
        
        // 首先获取第一个参数 param_1, 他的类型是整形
        if (esp_at_get_para_as_digit(cnt++, &value) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        // 这里需要注意, 需要把 value 的值赋值给另外一个变量, 因为下面的代码会把 value 的值重置成另一个参数的值, 或者下面再获取整形参数值的时候, 用另外定义的变量
        //param_1 = value;
        
        // 现在处理第二个参数
        if (esp_at_get_para_as_str(cnt++, &s) != ESP_AT_PARA_PARSE_RESULT_OK){
            return ESP_AT_RESULT_CODE_ERROR;
           
        }
        // param_2 = s;
        
        if (para_num != cnt) {
            // 走到这里说明第三个参数可能存在, 尝试获取它, 看看是不是真的输入了
            parse_result = esp_at_get_para_as_digit(cnt++, &value);
            if (parse_result != ESP_AT_PARA_PARSE_RESULT_OMITTED) {
                if (parse_result != ESP_AT_PARA_PARSE_RESULT_OK) {
                    // 第三个参数格式错误
                    return ESP_AT_RESULT_CODE_ERROR;
                }
                // 获取到了第三个参数
                // param_3 = value;
            } else {
                // 说明参数还是被省略
                // 用户自己处理这种情况
            }
        }
        
        // 最后再检查下参数个数, para_num 是用户输入的这条命令的参数个数, 如果不等于 3, 报错
        if (para_num != cnt) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        // 下面就可以加入用户自己的处理代码了
        // TODO: 
        
        return ESP_AT_RESULT_CODE_OK;
    }
    

    2.4 如何在命令中加入定时器进入阻塞状态

    某些应用场景, 需要将命令处理过程阻塞在哪里, 然后等待结果返回, 再将命令退出, 这种情况, 我们一般可以通过信号量来处理.

    这次我们用查询指令来举例, 比如想去云端查询某个状态.

    示例代码如下:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TESTCMD", NULL, at_queryCmdTestCmd, NULL, NULL},
    };
    
    static xSemaphoreHandle at_operation_sema = NULL;
    
    uint8_t at_queryCmdTestCmd(uint8_t *cmd_name)
    {
        ...
        ...
        
        assert(!at_operation_sema);
        at_operation_sema = xSemaphoreCreateBinary();
    
        //用户代码处理, 比如向另外一个 task 发送一个 queue, 让这个 task 做一些耗时比较久的事情, 然后 AT 这里等待结果
    
        xSemaphoreTake(at_operation_sema, portMAX_DELAY);
    
        vSemaphoreDelete(at_operation_sema);
        at_operation_sema = NULL;
        
        return ESP_AT_RESULT_CODE_OK;
    }
    
    另一个 task 处理完可以这样处理: 
    
    void user_task(void)
    {
        ...
        if (at_operation_sema) {
            xSemaphoreGive(at_operation_sema);
        }
        ...
    }
    
    

    2.5 如何从 AT 命令 port 中截取数据

    一般有两个应用场景, 第一个是截取指定长度的数据, 另一个是数据长度不指定, 类似于透传

    这里需要注意这两个 API:

    /**
     * @brief Set AT core as specific status, it will call callback if receiving data.
     * @param callback
     *
     */
    void esp_at_port_enter_specific(esp_at_port_specific_callback_t callback);
    
    /**
     * @brief Exit AT core as specific status.
     * @param NONE
     *
     */
    void esp_at_port_exit_specific(void);
    

    一个用于设置回调函数, 一个用于删除回调函数, 在本小节里的这种应用场景中, 他的工作原理是这样的:

    • 首先设置回调函数
    • 如果 AT Port 收到数据, 会回调这个函数
    • 我们在回调函数里 Give 信号量
    • AT 命令处理代码一直在等这个信号量
    • Take 到这个信号量之后, 就可以获取到 AT port 的数据了
    • 退出的时候, 删除回调函数, 删除信号量

    2.5.1 数据长度不指定

    如果用户需要进入输入模式, 直接获取串口的数据, 比如进入透传状态, 我们可以这样做:

    定义命令:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TESTCMD", NULL, NULL, NULL, at_exeCmdTestCmd},
    };
    

    具体实现如下:

    static xSemaphoreHandle at_sync_sema   = NULL;
    
    static void at_wait_data_callback(void)
    {
        xSemaphoreGive(at_sync_sema);
    }
    
    #define BUFFER_LEN 2048 
    
    uint8_t at_exeCmdExample(uint8_t *cmd_name)
    {
        int32_t temp_len = 0;
        uint8_t test_buf[BUFFER_LEN] = {0};
        ...
        ...
        
        vSemaphoreCreateBinary(at_sync_sema);
        xSemaphoreTake(at_sync_sema, portMAX_DELAY);
        
        //打印输入提示符 '>'
        esp_at_port_write_data((uint8_t*)">", at_strlen(">"));
    
        esp_at_port_enter_specific(at_wait_data_callback);
    
        while (xSemaphoreTake(at_sync_sema, portMAX_DELAY)) {
            memset(test_buf, 0x0, BUFFER_LEN);
            //读取数据到buffer
            temp_len = esp_at_port_read_data(test_buf, BUFFER_LEN);
            //下面这段处理逻辑是判读是否推出透传, 这里示例代码的判断条件是 "+++" 三个字节的字符
            if ((temp_len == 3) && (memcmp((char *) test_buf, "+++", strlen("+++"))==0)) {
                esp_at_port_exit_specific();
                temp_len = esp_at_port_get_data_length();
    
                if (temp_len > 0) {
                    esp_at_port_recv_data_notify(temp_len, portMAX_DELAY);
                }
    
                break;
            } else if (temp_len > 0 ){
                // 这里就把 RAW DATA 交由用户处理了
                customer_do_something(test_buf, temp_len);
            }
        }
    
        vSemaphoreDelete(at_sync_sema);
        at_sync_sema = NULL;
        // 这里就退出透传了, 同时还会输出OK字符, 如果您不想把OK在这里输出, 而是放在 ‘>’ 之前
        // 您首先需要在打印输入提示符 '>' 之前, 调用
        // esp_at_response_result(ESP_AT_RESULT_CODE_OK);
        // 然后在最后这里 return ESP_AT_RESULT_CODE_IGNORE;
        return ESP_AT_RESULT_CODE_OK;
    }
    

    2.5.2 指定数据长度

    如果数据长度是指定, 和上面略微有些差异, 大体思路相同, 我们可以这么做:

    定义命令:

    static esp_at_cmd_struct at_example_cmd[] = {
        {"+TESTCMD", NULL, NULL, at_setupCmdTestCmd, NULL},
    };
    

    命令带一个整形参数.

    具体实现如下:

    static xSemaphoreHandle at_sync_sema   = NULL;
    
    static void at_wait_data_callback(void)
    {
        xSemaphoreGive(at_sync_sema);
    }
    
    uint8_t at_setupCmdTestCmd(uint8_t para_num)
    {
        int32_t cnt = 0 , value = 0, len = 0, temp_len = 0;
        uint8_t *test_buf = NULL;
        
        // 获取数据长度
        if (esp_at_get_para_as_digit(cnt++, &value) != ESP_AT_PARA_PARSE_RESULT_OK) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        len = value;
        
        // 检查参数个数
        if (para_num != cnt) {
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        test_buf = (uint8_t *)malloc(len * sizeof(uint8_t));
        
        if (test_buf == NULL) {
            printf("malloc fail\n");
            return ESP_AT_RESULT_CODE_ERROR;
        }
        
        vSemaphoreCreateBinary(at_sync_sema);
        xSemaphoreTake(at_sync_sema, portMAX_DELAY);
        
        //打印输入提示符 '>'
        esp_at_port_write_data((uint8_t*)">", at_strlen(">"));
    
        esp_at_port_enter_specific(at_wait_data_callback);
        
        temp_len = 0;
    
        // 开始截取指定长度的数据, 
        while (xSemaphoreTake(at_sync_sema, portMAX_DELAY)) {
            temp_len += esp_at_port_read_data(test_buf + temp_len, len - temp_len);
    
            if (temp_len == len) {
                // 走到这里, 说明已经接收到了想要的长度的数据, 但是要要注意, 如果时间输入长度超过指定想要的长度, 也会进到这里
                esp_at_port_exit_specific();
                
                // 这里就是在获取看看还有多少数据没有读取, 如果是0, 那就是正好数据长度就是指定的
                temp_len = esp_at_port_get_data_length();
    
                if (temp_len > 0) {
                    //如果实际输入的长度超过想要的长度, 会走到这里, 在这个例子中, 是直接把多余的数据打印出来, 您的应用中怎么处理取决于您
                    esp_at_port_recv_data_notify(temp_len, portMAX_DELAY);
                }
    
                break;
            }
        }
    
        vSemaphoreDelete(at_sync_sema);
        at_sync_sema = NULL;
        
        free(test_buf);
        
        ...
        
        return ESP_AT_RESULT_CODE_OK;
    }
    
    展开全文
  • android发送AT命令

    热门讨论 2013-11-15 16:38:13
    android发送AT命令代码 发送AT命令获取想要的信息,或者做一些其他事
  • AT命令发送小工具

    2013-11-26 15:54:32
    AT命令发送小工具,可以导入文件中的AT命令,也可以保存文件,逐行定时发送AT命令
  • 高通AT命令文档

    热门讨论 2013-09-26 17:49:44
    AT命令试用文档和架构 帮助你快速理解和使用 熟悉AT命令的通信方法
  • 华为V200R001 AT命令手册-标准命令部分
  • AT命令概述 GSM Rec.07.07标准AT命令 标准GPRS命令 AT扩展命令 TCPIP AT命令
  • AT命令测试工具

    2013-12-27 18:53:45
    AT命令测试工具 特别说明:发送短信格式为AT+CMGS=“+8613312345678”\r测试内容
  • AT命令简单介绍

    千次阅读 2017-11-17 08:37:00
    AT命令以AT开头,一回车符结束。一个简单命令如:AT回车符,模块对命令的响应为:回车符、换行符response回车符、换行符 AT命令大致可分为三类:  1、基本AT命令:AT或者AT&,如:ATE1(打开串口回显),AT&...
    AT命令以AT开头,一回车符结束。 一个简单命令如:AT回车符, 模块对命令的响应为:回车符、换行符response回车符、换行符
    AT命令大致可分为三类:  
    1、基本AT命令:AT<><>或者AT&<><>,如:ATE1(打开串口回显),AT&D1(开启DTR低电平切换)。
    2、S参数型AT命令:ATS<>=<>,如:ATS0=1(设置模块来电一声自动接起)。
    3、扩展型AT命令(四种):
    a)、AT+<>=?
    用于查看此命令在模块中允许设置的参数范围,如发送命令:AT+CREG=?
    正常时响应:+CREG:(0-2)
                         OK
    b)、AT+<>?
    用于查看此命令在模块中的当前设置值,如发送命令:AT+IPR?
    正常时响应:+IPR:0
                              OK
    c)、AT+<>=<>
    用于设置当前AT命令x的参数值。如发送命令:AT+CMGF=0
    正常时 响应:OK
    d)、AT+<>
    查看模块内部的一些状态值。如发送命令:AT+CSQ
    正常时响应:+CSQ:29,0
                                  OK
    展开全文
  • 移远M26 AT命令手册

    2017-09-20 15:24:30
    移远M26 AT命令手册V1.1,中文版AT命令文档,适用于大多数移远GPRS模块,比较好用,2015-08-31版本,M26 AT 命令手册,GSM/GPRS 系列
  • AT命令简易解析

    千次阅读 2019-02-02 16:56:39
    AT命令的应用场合很多,也是应用最为通用的命令。而AT命令并不像通信协议特定的数据帧格式,解析AT命令需要匹配每个字符。AT命令一般有三种状态:查询、执行、设置,根据这三种状态,本文将使用一种简易的方法解析AT...
  • Linux的at命令

    千次阅读 2016-12-18 00:08:01
    Linux的at命令
  • EC20AT命令手册合集

    2019-11-06 14:12:28
    EC20AT命令手册合集,里面有常规命令,NET,GPS,FTP等等,几乎有的都收集到了一共是8个文档
  • MTK AT命令说明文档

    2010-08-09 09:42:20
    MTK AT命令MTK AT命令MTK AT命令MTK AT命令MTK AT命令MTK AT命令MTK AT命令MTK AT命令MTK AT命令
  • at命令和crontab命令

    千次阅读 2015-04-11 21:01:11
    at命令和crontab命令
  • Neoway-N720-AT命令手册

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 466,263
精华内容 186,505
关键字:

at命令