m0_64190710 2024-03-28 10:53 采纳率: 0%
浏览 13

发生AT指令,为什么接收的时候出问题了

佬,能不能救一下 我想用单片机发生AT指令(一共9条指令)给ESP8266,用来连接阿里云,用DMA+IDLE中断接收数据,数据存在buf2一个数组里面,然后我调试看buf2里面的数据,是这样的(文本里列出来了)这是什么情况,怎么解决

img

  • 写回答

3条回答 默认 最新

  • 专家-皆知 2024-03-28 10:53
    关注

    引自免费微信小程序:皆我百晓生

    在AT指令中,"OK"、"WIFI GOT IP"和"SERCFG..."等关键字常用于完成一些基本的通信功能,如路由器设置、物联网设备连接等。下面是根据您的描述以及AT指令的基本概念,对可能出现的问题进行详细的解答,并给出对应的解决步骤:

    1. 接收数据不符合要求

      • 您在串行收到来自esp8266的消息后,将这些数据放入名为buf2的字符串数组。
      • 您在串行处理收到的这些数据时,可以检查这些字符串是否符合AT指令的格式和预期。在AT指令中,有四个重要部分组成:字符 CWMODE、字符 RST、字符 CWJAP 和字符 COMMA-separated-value
      • 根据您提供的信息,可能存在问题的部分包括: a. 第 1 步:AT+CWMODE=1
        • 如果 AT 指令开始之前没有正确配置了模式,那么此步骤可能不会被执行,导致接收失败。
        • 单片机内部的AT指令解释器可能存在错误判断或解析错误导致此步骤未执行。

      解决方案:确保在 AT+CWMODE=1 的开头,系统已经正确设置了模式,通常设置为无线网络模式(例如,关闭无线功能)。如果是手动设置,可以调用相应的系统函数或命令实现相关设置,例如 AT几步模式(M2)AT+CWMODE(M2)。确认 AT 指令成功启动并对应于正确的无线模式后,通过 buf2 数组的相应位置检查数据是否包含 OKWIFI GOT IPSERCFG... 字符串。

      #include <WiFi.h>
      #include <Arduino.h>
      
      const int WiFi_BSSID = 'your-Wifi-BSSID';
      const char* WiFi_PASSWORD = 'your-Wifi-password';
      
      void setup() {
         Serial.begin(9600);
         WiFi.begin(Wifi_BSSID, WiFi_PASSWORD);
      
         if (!WiFi_connect()) {
            // 判断消息是否在 AT 指令中
            // 在此处使用 `AT(CWMODE=1)` 来匹配AT 指令
      
            // 若消息未包含预定义的值,则表示该模式未被正确启用
            // 例如,如果没有 `CWJAP` 子句,则AT 指令也无法正常工作
      
            // 确保 AT 指令已经被正确识别并遵循预期的模式设置
            // 例如,如果是无线网络模式,应该在模式名前面加上 `CWMODE=1` 来实现设置
      
            return;
         }
      }
      
      void loop() {
         if (WiFi.status() != WL_CONNECTED) {
            // 检查是否已经连接到 Wi-Fi 设备
            if (!WiFi_connect()) {
               // 若仍未连接,重新初始化串口和无线网卡
               // 使用 `setup()` 函数再次配置串口并重置 Wi-Fi 设备
               Serial.println("Resetting WiFi connection...");
               WiFi.reinit();
               return;
            }
      
            // 接收 AT 指令并进行相应的处理
            // 这里使用 `AT+CWMODE=1` 搜索并执行 AT 指令
            if (is_AT_command(WiFi_address())) {
               AT焯N(`AT+CWMODE=1`, true); // 发送模式设置
               AT焯N(`AT+RST`, true); // 网络断开
               AT焯N(`AT+CWJAP='OI',`348895++`, true); // 路由器IP地址及域名配置
               AT焯N(`AT+CIPSNTPCFG=1,8,'ntpl.aliyun.com'`, true); // MQTT客户端标识
               AT焯N(`AT+MQTTCLIENTID=0,"koyjtXDw570.XPNO1|securemode=2",1883,1`, true); // IoT设备名称和ID
               AT焯N(`AT+MQTTCONN=0,"iot-06z00ek70ctufuz.mgtt.iothub.aliyuncs.com"', 1883, 1); // MQTT连接地址
               AT焯N(`AT+MQTTSUB=0,《/sys/koyjtxDw570/XPNO1/thing/service/property/set》,1`, true); // MQTT订阅属性设置
               AT焯N(`AT+MQTTPUB=0,《/sys/k0yjtxDw570/XPNO1/thing/property/post》,(params:(\"Currenture\":0)),1`, true); // MQTT发布属性设置
               AT焯N(`AT+MQTTCLEAN=0`, true); // Mqtt清理操作
               AT焯N(`AT+MQTTPUB=0,《/sys/k0yjtxDw570/XPNO1/thing/property/post》,(params:(\"Currenture\":0)),1`, true); // MQTT同步属性设置
               AT焯N(`AT+MQTTCLEAN=0`, true); // Mqtt清理操作
               AT焯N(`AT+MQTTPUB=0,《/sys/k0yjtxDw570/XPNO1/thing/property/post》,(params:(\"Currenture\":0)),1`, true); // MQTT同步属性设置
            } else {
               // 非AT指令操作
               Serial.print("Unsupported AT command received.\n");
            }
         } else {
            // 进入监听模式,接收从 ESP8266 发送的数据
            while (true) {
               const char* data = esp8266_receive_data();
      
               // 检查字符串长度是否符合 AT 指令要求
               if (data && strlen(data) == 3 + 1) { // 4个字节
                  const char* expected_data = "OK";
                  if (strcmp(expected_data, data) == 0) {
                     break;
                  }
               }
      
               // 对接收到的数据进行处理(此处示例省略)
               // ...
      
               // 检查处理后的数据是否满足 AT 指令规范
               if (strstr(data, expected_data)) {
                  Serial.println("AT command recognized and executed successfully.");
                  break;
               }
            }
         }
      }
      
      bool is_AT_command(const char* cmd) {
         // 判断当前字符串中是否包含特定的 AT 指令
         for (size_t i = 0; i < strlen(cmd); i++) {
            if (cmd[i] == '\0') {
               return false;
            }
         }
      
         return true;
      }
      
      void esp8266_receive_data(char buffer[]) {
         // 处理从 ESP8266 发送的 AT 数据
         // 通常会在 ATMega 应用程序的输入处理函数中实现
         // 如在 `readSerial()` 或者 `handle_input()` 中查找 `buffer` 作为输入数据
         // 操作逻辑与从串口接收数据类似
         // ...
      
         // 将处理后的数据存储到 buf2 数组中
         memcpy(buf2, buffer, strlen(buffer));
      }
      
    
    2. **WiFi GOT IP**:
       - 如果 AT 指令后面的字符串 `"WIFI GOT IP"` 是用来获取设备的 IP 地址,那么 `buf2` 数组中的第一个元素可能会为空,因为 ESP8266 不会将其默认保存为空字符串。为了找到这个地址,可以使用以下步骤:
       - 检查与 WiFi 地址关联的默认路由器 ID(例如,在 `WiFi.config()` 函数中获得)。
       - 对于 WPA/WPA2 状态的路由器,应查看每个 AP 的 SSID 以及对应 TCP 访问列表中的 IP 地址。
       - 查找每个 AP 的 TCP 访问列表中的对应 IP 右边界(通常是子网掩码 `255.255.255.0`),即相应路由器 ID 打头的最后一个 IP 地址。
       - 从这个地址的尾部开始依次遍历后续的 IP 域,直到找到一个具有匹配状态的 IPv4 或 IPv6 地址。
       - 若找到对应的 IP 地址,`buf2` 数组的第一个元素就是实际设备的 IP 地址。
    
    对于 WPA/WPA2 状态的路由器,需要提供当前所选 WiFi 功能模式(如“Wi-Fi ONLY”、“Secure mode”等)、接入点地址以及对应的认证方式(如 WPA2+PSK 或 WPA2+TKIP 等),才能确定如何获取与之关联的默认路由器 IP 地址。
    
    解决方法:
       - 在 `setup()` 函数中添加新的变量 `WIFI_config`,并初始化它为包含所有路由器信息的 JSON 对象,如:
       ```c
       WiFi_config wifi_config = WiFi.config();
       // ...
       // 设置 Wi-Fi 功能模式(Wi-Fi ONLY)
       wifi_config.mode = WiFi_MODE_WPA2;
       // 设置接入点地址
       wifi_config.host_name = WiFi_BSSID;
       // 设置认证方式(WPA2+PSK 或 WPA2+TKIP)
       wifi_config.password = WiFi_PASSWORD;
       // ...
       WiFi.begin
    
    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 3月28日

悬赏问题

  • ¥15 校内二手商品转让网站
  • ¥20 高德地图聚合图层MarkerCluster聚合多个点,但是ClusterData只有其中部分数据,原因应该是有经纬度重合的地方点,现在我想让ClusterData显示所有点的信息,如何实现?
  • ¥100 求Web版SPC控制图程序包调式
  • ¥20 指导如何跑通以下两个Github代码
  • ¥15 大家知道这个后备文件怎么删吗,为啥这些文件我只看到一份,没有后备呀
  • ¥15 C++为什么这个代码没报错运行不出来啊
  • ¥15 一道ban了很多东西的pyjail题
  • ¥15 关于#r语言#的问题:如何将生成的四幅图排在一起,且对变量的赋值进行更改,让组合的图漂亮、美观@(相关搜索:森林图)
  • ¥15 C++识别堆叠物体异常
  • ¥15 微软硬件驱动认证账号申请