基于状态机实现WIFI模组物联网

1.0 状态机框架原理

如果成功的话就连接热点,如果失败就返回AT通信检查,如果AT通信检查还是失败就放回硬件复位这个状态,如果热点链接成功,就连接MQTT指令,如果失败就返回AT通信检查,如果成功就连接云平台通信,如果失败就返回AT通信检查这个状态。


2.0 程序编写


在这个过程中使用的是连接固定的热点,后续会连接可变动的WIFI热点,注上面的状态图是基于固定的WIFI热点连接的状态图形。

// 创建枚举类型
typedef enum
{WIFI_COMM_WAIT,WIFI_COMM_OK,WIFI_COMM_FALL,
}WifiCommState_t;

注:WIFI_COMM_WAIT 表示的是正在处理AT指令,WIFI_COMM_OK,表示AT指令发送完成,FALL表示AT指令发送超时,


3.0 Wi-Fi模块与AT命令交互

static WifiCommState_t AtCmdHandle(char *cmd, char* rsp, uint32_t timeoutMs)
{static WifiCommState_t s_commState = WIFI_COMM_OK;static uint64_t s_sendCmdTime;char *recvStrBuf;if (s_commState != WIFI_COMM_WAIT){if (cmd != NULL){SendWifiModuleStr(cmd);}s_commState = WIFI_COMM_WAIT;s_sendCmdTime = GetSysRunTime();}else{if ((GetSysRunTime() - s_sendCmdTime) < timeoutMs){recvStrBuf = RecvWifiModuleStr();if (strstr(recvStrBuf, rsp) != NULL){s_commState = WIFI_COMM_OK;}}else{s_commState = WIFI_COMM_FALL;}}return s_commState;
}

4.0 AT 命令结构体信息

// AT命令信息
typedef struct
{char *cmd;char *rsp;uint32_t timeoutMs;
}AtCmdInfo_t;

5.0 模组初始化命令集

/*模组初始化命令集*/
static AtCmdInfo_t g_checkModuleCmdTable[] = {{.cmd = "ATE0\r\n",        // 关闭回显.rsp = "OK",.timeoutMs = 1000,},{.cmd = "AT+CWMODE=1\r\n",.rsp = "OK",.timeoutMs = 1000,	},
};

对应在AT指令说明文档中的命令是:ATE 表示的是开启和关闭回显

.cmd = "AT+CWMODE=1\r\n",

注:这个指令是用于设置WIFI的工作模式,该指令表示的原因是设置WIFI的工作指令为客户端的工作模式。

  1. .cmd = "AT+CWMODE=1\r\n":

    • 这是AT命令的字符串表示形式,用于设置Wi-Fi模块的工作模式。
    • AT+CWMODE=1 表示设置Wi-Fi模块工作在Station模式(客户端模式),即Wi-Fi模块将连接到一个现有的Wi-Fi网络。
    • \r\n 是回车换行符,通常用于表示命令的结束。
  2. .rsp = "OK":

    • 这是指令成功执行后期望从Wi-Fi模块接收到的响应字符串。
    • 在许多情况下,Wi-Fi模块会在成功执行AT命令后返回 "OK"
  3. .timeoutMs = 1000:

    • 这是一个整数,表示在等待Wi-Fi模块响应时的超时时间,单位是毫秒。
    • 在本例中,超时时间为1000毫秒(1秒)。

4.0 检查WIFI模组的工作状态

WifiCommState_t CheckWifiModuleWork(void)
{WifiCommState_t commState;static uint8_t retryCount = 0;static AtCheckModuleCmdType cmdType = AT_E0;switch (cmdType){case AT_E0:commState = AtCmdHandle(g_checkModuleCmdTable[AT_E0].cmd, g_checkModuleCmdTable[AT_E0].rsp,g_checkModuleCmdTable[AT_E0].timeoutMs);if (commState == WIFI_COMM_OK){retryCount = 0;cmdType = AT_CWMODE_1;}else if (commState == WIFI_COMM_FALL){retryCount++;if (retryCount == 3){retryCount = 0;return WIFI_COMM_FALL;}}break;case AT_CWMODE_1:commState = AtCmdHandle(g_checkModuleCmdTable[AT_CWMODE_1].cmd, g_checkModuleCmdTable[AT_CWMODE_1].rsp,g_checkModuleCmdTable[AT_CWMODE_1].timeoutMs);if (commState == WIFI_COMM_OK){cmdType = AT_E0;return WIFI_COMM_OK;}else if (commState == WIFI_COMM_FALL){return WIFI_COMM_FALL;}break;}return WIFI_COMM_WAIT;
}

5.0 创建AT指令表

static AtCmdInfo_t g_ConnectApCmdTable[] = {{.cmd = "AT+CWJAP=\"%s\",\"%s\"\r\n",   // 这里的\是给编译器用的//.cmd = "AT+CWJAP=\"HIKE_5F\\,2.4G\",\"hike666666\"\r\n",.rsp = "GOT IP",.timeoutMs = 15000,},
};

注:"AT+CWJAP=\"%s\",\"%s\"\r\n" 此处这条AT指令的格式为什么是这样,主要原因是AT手册规定的格式就是这个样子:在程序中凡是AT指令出现, " \ 都需要在前面添加\号进行转义,具体如下所示:


6.0 AT+CWJAP 命令详解

注:

  • AT+CWJAP: 这是Wi-Fi模块用于连接到无线接入点(Access Point, AP)的AT命令。
  • SSID: 服务集标识符(Service Set Identifier),它是用来唯一标识一个无线网络的名字。
  • PWD: 密码,指的是Wi-Fi网络的安全密钥或密码。
AT+CWJAP="SSID","password"
  • SSID 替换为你要连接的Wi-Fi网络的名称。
  • password 替换为对应的Wi-Fi网络密码。

7.0 检查WIFI连接函数

typedef enum 
{AT_CWJAP_SSID_PWD,
} AtConnectApCmdType;static char g_apSsid[20] = "HIKE_5F_2.4G";
static char g_apPwd[20] = "hike666666";WifiCommState_t CheckWifiConnect(void)
{WifiCommState_t commState;static AtConnectApCmdType cmdType = AT_CWJAP_SSID_PWD;static uint8_t retryCount = 0;char cmdStrBuf[256];switch (cmdType){		case AT_CWJAP_SSID_PWD:sprintf(cmdStrBuf, g_ConnectApCmdTable[AT_CWJAP_SSID_PWD].cmd, g_apSsid, g_apPwd);commState = AtCmdHandle(cmdStrBuf, g_ConnectApCmdTable[AT_CWJAP_SSID_PWD].rsp, g_ConnectApCmdTable[AT_CWJAP_SSID_PWD].timeoutMs);if (commState == WIFI_COMM_OK){retryCount = 0;return WIFI_COMM_OK;}else if (commState == WIFI_COMM_FAIL){retryCount++;if (retryCount == 3){retryCount = 0;return WIFI_COMM_FAIL;}}break;}return WIFI_COMM_WAIT;	
}

8.0 枚举WIFI工作状态

typedef enum
{CHECK_WIFI_MODULE,CHECK_WIFI_CONNECT,CONNECT_MQTT_SERVER,COMM_MQTT_SERVER,HWRESET_WIFI_MODULE,WIWI_MODULE_ERROR,
} WifiWorkState_t;

注:一以上各个枚举变量的含义:

这个枚举类型 WifiWorkState_t 定义了一系列的状态,用于描述Wi-Fi模块在执行特定任务时的不同阶段。这些状态可以帮助我们跟踪Wi-Fi模块的工作流程。下面是每个枚举成员的含义:

  1. CHECK_WIFI_MODULE:

    • 这个状态表示正在检查Wi-Fi模块的基本功能或状态。这可能是初始化过程的一部分,用于验证Wi-Fi模块是否准备好接受进一步的命令。
  2. CHECK_WIFI_CONNECT:

    • 这个状态表示正在检查Wi-Fi模块是否已成功连接到Wi-Fi网络。这通常发生在Wi-Fi模块尝试连接到一个接入点之后。
  3. CONNECT_MQTT_SERVER:

    • 这个状态表示Wi-Fi模块正在尝试连接到MQTT服务器。一旦Wi-Fi连接建立,下一步就是与MQTT服务器建立连接。
  4. COMM_MQTT_SERVER:

    • 这个状态表示Wi-Fi模块已经成功连接到了MQTT服务器,并且正在与其进行通信。这可能涉及到发布消息、订阅主题等MQTT协议的交互。
  5. HWRESET_WIFI_MODULE:

    • 这个状态表示正在对Wi-Fi模块执行硬件重置。这可能是因为遇到一些无法通过软件解决的问题,或者是为了确保Wi-Fi模块回到一个已知的初始状态。
  6. WIWI_MODULE_ERROR:

    • 这个状态表示Wi-Fi模块遇到了错误。这可能是由于硬件故障、软件错误或其他未知问题引起的。当Wi-Fi模块无法正常工作时,它可能会进入这个状态。

9.0 WIFI网络工作任务函数

void WifiNetworkTask(void)
{WifiCommState_t commState;static WifiWorkState_t workState = CHECK_WIFI_MODULE;static uint8_t hwresetCnt = 0;switch (workState){case CHECK_WIFI_MODULE:commState = CheckWifiModuleWork();if (commState == WIFI_COMM_OK){workState = CHECK_WIFI_CONNECT;}else if (commState == WIFI_COMM_FAIL){workState = HWRESET_WIFI_MODULE;}break;case CHECK_WIFI_CONNECT:commState = CheckWifiConnect();if (commState == WIFI_COMM_OK){workState = CONNECT_MQTT_SERVER;}else if (commState == WIFI_COMM_FAIL){workState = CHECK_WIFI_MODULE;}break;		case CONNECT_MQTT_SERVER:break;case COMM_MQTT_SERVER:break;case HWRESET_WIFI_MODULE:if (hwresetCnt < 1)                 // 如果AT命令不通,硬件复位1次{HwresetWifiModule();DelayNms(1000);workState = CHECK_WIFI_MODULE;hwresetCnt++;}else{printf("wifi module error!\n");workState = WIWI_MODULE_ERROR;  // 如果硬件复位1次,AT命令还是不通,就不再执行WIFI任务的业务逻辑,直接退出,避免影响其他任务}break;default:break;}
}

10.0 网络连接成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/410082.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL集群技术

一、MySQL部署 1.源码编译 实验环境为rhel7 安装依赖性 [rootmysql-node1 ~]# yum install cmake gcc-c openssl-devel \ ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 -y [rootmysql-node1 ~]# tar zxf mysql-boost-5.7.44.tar.gz 源码…

达梦数据库的系统视图v$object_usage

达梦数据库的系统视图v$object_usage 在达梦数据库&#xff08;DM Database&#xff09;中&#xff0c;V$OBJECT_USAGE 视图提供了关于数据库对象的使用情况和统计信息。这些对象可以包括表、索引、视图、存储过程等。通过 V$OBJECT_USAGE 视图&#xff0c;数据库管理员可以监…

贵金属市场展望:黄金独领风骚,钯金、铂金与白银承压

黄金新高可期&#xff0c;避险魅力不减 黄金市场持续升温&#xff0c;近期价格屡创新高。随着全球经济不确定性增加及美联储降息预期的增强&#xff0c;黄金的避险属性得到进一步凸显。市场普遍预期&#xff0c;若美联储在年内维持宽松货币政策&#xff0c;黄金价格有望继续上扬…

新迪天工®看图,专业的三维CAD看图工具

替代专业CAD软件&#xff0c;方便查看各种三维和二维CAD图纸 新迪天工看图是一款功能强大的三维模型和二维图纸查看工具&#xff0c;能帮助制造企业以较低的成本、较高的数据安全性实现产品设计数据的跨业务浏览和交互。 应用场景 1、设计图纸评审 可直接对三维模型和二维…

【数据结构】—— 树和二叉树

1、树的概念2、树的相关术语3、树的常见表示方法4、树的实际应用5、二叉树的相关概念和性质6、二叉树的顺序存储&#xff08;堆&#xff09;6.1 堆的概念6.2 堆的结构和接口6.3 堆的初始化和销毁6.4 堆的插入6.5 堆的删除6.5 取堆顶数据6.6 获取有效节点个数6.7 判空6.8 源代码…

高并发业务下的库存扣减技术方案设计

扣减库存需要查询库存是否足够: 足够就占用库存不够则返回库存不足&#xff08;这里不区分库存可用、占用、已消耗等状态&#xff0c;统一成扣减库存数量&#xff0c;简化场景&#xff09; 并发场景&#xff0c;若 查询库存和扣减库存不具备原子性&#xff0c;就可能超卖&…

动态内存管理函数malloc,calloc,realloc,free

malloc 函数原型&#xff1a;void* malloc(size_t size); 这个函数向内存申请一块连续可用的size大小的空间&#xff0c;并返回指向这快空间的指针。如果开辟成功&#xff0c;则返回一个指向开辟好空间的指针。如果开辟失败&#xff0c;则返回一个NULL指针&#xff0c;因此ma…

Facebook AI策略全解:从数据分析到智能推荐的成功秘诀

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;已成为推动科技发展的核心力量。Facebook&#xff0c;作为全球领先的社交网络平台&#xff0c;正通过先进的AI策略来优化用户体验和平台运营。从数据分析到智能推荐&#xff0c;Facebook的AI策略涵盖了多个方面&…

Git 分支操作全解析:创建、切换、合并、删除及冲突解决

“ 在现代软件开发中&#xff0c;高效的版本控制是确保项目成功的关键。Git 提供了强大的分支管理功能&#xff0c;使得开发者能够独立地进行功能开发、修复 bug 和进行紧急修补。本文将深入探讨 Git 分支的基本操作&#xff0c;包括创建、切换、合并和删除分支&#xff0c;同时…

Linux基础 - yum、rzsz、vim 使用与配置、gcc/g++的详细解说

目录 一、Linux 软件包管理器 yum A.什么是软件包&#xff1f; B.关于rzsz&#xff0c;yum的配置 1.安装 sz&#xff0c;rz 命令&#xff1a; a.执行命令sz可将linux中的文件传输到Windows中 b.执行rz命令可将Windows中的文件传输到linux 2.scp XXX.tgz 用户名另一台lin…

免费高画质提取PPT/Word/Excel中的图片工具

下载地址&#xff1a;https://pan.quark.cn/s/134ccc35b8a2 软件简介&#xff1a; 好不容易搞到一个几十上百MB的ppt&#xff0c;想导出里面的图片进行二次加工&#xff0c;却被ppt超低画质的图片另存为功能劝退&#xff0c;明知里面全是高清图片&#xff0c;走时却是两手空空…

1系-8系铝合金材料的成分特性及应用详解

1系-8系铝合金材料的成分特性及应用详解 铝合金概述 铝合金的定义铝合金是一种以铝为基体&#xff0c;通过添加一定量的其他合金化元素&#xff08;如铜、锰、硅、镁、锌等&#xff09;形成的合金材料。由于合金元素的加入&#xff0c;铝合金在保持铝的轻质、良好导电导热性等基…

langchain入门系列之六 使用langchain构建PDF解析助手

本文将介绍如何使用langchain构建一个pdf解析助手&#xff0c;在此文中你将学习到langchain如何与web应用(fastapi)相结合&#xff0c;向量持久化等知识&#xff0c;话不多说&#xff0c;现在开始。 安装环境 pip install fastapi pip install python-dotenv pip install uv…

漫步者这款耳机怎么样吗?南卡、漫步者、Cleer公认畅销款式测评!

目前市场上开放式耳机品牌众多&#xff0c;选择时需要充分了解&#xff0c;但即便如此&#xff0c;也难以完全避免购买到质量不佳的产品。作为一位专注于数码产品测评的博主&#xff0c;我对开放式耳机有深入的研究。最近&#xff0c;我收到了许多关于漫步者、南卡、Cleer等品牌…

Flutter-自适用高度PageView

需求 在 Flutter 中&#xff0c;PageView 是一个非常常用的组件&#xff0c;能够实现多个页面的滑动切换。然而&#xff0c;默认的 PageView 高度是固定的&#xff0c;这在展示不同高度的页面时&#xff0c;可能会导致不必要的空白或内容裁剪问题。为了使 PageView 能够根据每…

OpenMax算法详解:深度学习中的高效开集识别技术

OpenMax算法详解&#xff1a;深度学习中的高效开集识别技术 在深度学习领域&#xff0c;模型的识别能力往往受限于其训练数据集的范畴。传统的分类模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;或循环神经网络&#xff08;RNN&#xff09;&#xff0c;通常被设计…

第八节:Nodify 编辑器属性

引言 经过前几章的学习&#xff0c;你已经对Nodify框架有了初步的编程思路。当然只局限于这些还完全不够&#xff0c;本章节将阐述各个结构组件的一些常用属性&#xff0c;以便在日后的开发过程中更得心应手。 1、编辑器 平移 简介属性默认值平移功能 控制DisablePanningfals…

100128-批量获取视频音频时长添加到文件名中支持子孙文件夹下操作-UI

程序功使用环境▶适用的系统环境说明&#xff1a;win7以上64位win系统注意&#xff1a;win32位系统/mac系统需要额外定制▶使用期限&#xff1a;无需注册、不绑电脑、无时间限制▶如何安装&#xff1a;不需要安装程序功能说明▶子文件夹穿透&#xff1a;支持▶支持的文件格式&a…

MySQL集群技术详解

目录 一、MySQL在服务器中的部署方法 1.1 编译安装MySQL 1.2 部署MySQL 二、MySQL主从复制 2.1 配置master 2.2 配置slave 2.3 添加slave2 测试&#xff1a; 2.4 延迟复制 2.5 慢查询日志 2.6 MySQL的并行复制 2.7 MySQL主从复制原理剖析 2.8 架构缺陷 三、MySQL…

学习笔记——IP组播——IP组播基本概述

二、IP组播基本概述 IP组播技术有效地解决了单播和广播在点到多点应用中的问题。组播源只发送一份数据&#xff0c;数据在网络节点间被复制、分发&#xff08;PIM&#xff09;&#xff0c;且只发送给需要该信息的接收者。 1、前言 网络中存在各种各样的业务&#xff0c;从流…