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的工作指令为客户端的工作模式。
-
.cmd = "AT+CWMODE=1\r\n"
:- 这是AT命令的字符串表示形式,用于设置Wi-Fi模块的工作模式。
AT+CWMODE=1
表示设置Wi-Fi模块工作在Station模式(客户端模式),即Wi-Fi模块将连接到一个现有的Wi-Fi网络。\r\n
是回车换行符,通常用于表示命令的结束。
-
.rsp = "OK"
:- 这是指令成功执行后期望从Wi-Fi模块接收到的响应字符串。
- 在许多情况下,Wi-Fi模块会在成功执行AT命令后返回
"OK"
。
-
.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模块的工作流程。下面是每个枚举成员的含义:
-
CHECK_WIFI_MODULE
:- 这个状态表示正在检查Wi-Fi模块的基本功能或状态。这可能是初始化过程的一部分,用于验证Wi-Fi模块是否准备好接受进一步的命令。
-
CHECK_WIFI_CONNECT
:- 这个状态表示正在检查Wi-Fi模块是否已成功连接到Wi-Fi网络。这通常发生在Wi-Fi模块尝试连接到一个接入点之后。
-
CONNECT_MQTT_SERVER
:- 这个状态表示Wi-Fi模块正在尝试连接到MQTT服务器。一旦Wi-Fi连接建立,下一步就是与MQTT服务器建立连接。
-
COMM_MQTT_SERVER
:- 这个状态表示Wi-Fi模块已经成功连接到了MQTT服务器,并且正在与其进行通信。这可能涉及到发布消息、订阅主题等MQTT协议的交互。
-
HWRESET_WIFI_MODULE
:- 这个状态表示正在对Wi-Fi模块执行硬件重置。这可能是因为遇到一些无法通过软件解决的问题,或者是为了确保Wi-Fi模块回到一个已知的初始状态。
-
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;}
}