ESP32-C3 Wi-Fi STA模式打通(2)

2024-05-07 10:12
文章标签 模式 esp32 sta c3 打通 wi fi

本文主要是介绍ESP32-C3 Wi-Fi STA模式打通(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接前一篇文章:ESP32-C3 Wi-Fi STA模式打通(1)

本文内容参考:

ESP32 (WIFI)-AP、STA模式(14)_wifi接口 wifi_ap_channel_set-CSDN博客

【ESP-IDF】ESP32利用wifi联网(STA模式)_esp32ap和sta-CSDN博客

ESP32 IDF开发 应用篇⑫Wifi STA模式和AP模式的使用_esp32 ap-CSDN博客

ESP32 非易失性存储器NVS,实现数据掉电存储(ESP-IDF)_esp32nvs-CSDN博客

特此致谢!

上一回讲到了例程最为主要的文件main\station_example_main.c。代码如下:

/* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"#include "lwip/err.h"
#include "lwip/sys.h"/* The examples use WiFi configuration that you can set via project configuration menuIf you'd rather not, just change the below entries to strings withthe config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID      CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY  CONFIG_ESP_MAXIMUM_RETRY#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;/* The event group allows multiple bits for each event, but we only care about two events:* - we are connected to the AP with an IP* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1static const char *TAG = "wifi station";static int s_retry_num = 0;static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");} else {xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);}ESP_LOGI(TAG,"connect to the AP fail");} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));s_retry_num = 0;xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);}
}void wifi_init_sta(void)
{s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));esp_event_handler_instance_t instance_any_id;esp_event_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&instance_got_ip));wifi_config_t wifi_config = {.sta = {.ssid = EXAMPLE_ESP_WIFI_SSID,.password = EXAMPLE_ESP_WIFI_PASS,/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.*/.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,.sae_pwe_h2e = ESP_WIFI_SAE_MODE,.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );ESP_ERROR_CHECK(esp_wifi_start() );ESP_LOGI(TAG, "wifi_init_sta finished.");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually* happened. */if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else {ESP_LOGE(TAG, "UNEXPECTED EVENT");}
}void app_main(void)
{//Initialize NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");wifi_init_sta();
}

本文开始对于代码进行详细解析。

(1)app_main

先来看主函数app_main。前文书已提到,一个工程有且仅有一个main目录,该目录包含了项目本身的源代码和用户程序的入口app_main,用户程序默认从此处开始执行。

app_main函数中实际上包含了两个函数,一个是nvs_flash_init(),另一个是wifi_init_sta()。一个一个来看。

1)nvs_flash_init函数

函数原型

extern "C" esp_err_t nvs_flash_init(void)

函数功能

初始化默认的NVS分区,每次操作NVS分区都需要先初始化NVS。此API初始化默认的NVS分区。默认的NVS分区是在分区表中标记为“nvs”的分区。

函数参数

无。

函数返回值

初始化成功返回 ESP_OK。

nvs_flash_init函数在C:\Espressif\frameworks\esp-idf-v5.2.1\components\nvs_flash\src\nvs_api.cpp中,代码如下:

extern "C" esp_err_t nvs_flash_init(void)
{
#ifdef CONFIG_NVS_ENCRYPTIONesp_err_t ret = ESP_FAIL;nvs_sec_cfg_t cfg = {};ret = nvs_flash_read_security_cfg_v2(&nvs_sec_default_scheme_cfg, &cfg);if (ret != ESP_OK) {ESP_LOGW(TAG, "Failed to read NVS security cfg: [0x%02X] (%s)", ret, esp_err_to_name(ret));ESP_LOGI(TAG, "Generating NVS encr-keys...");ret = nvs_flash_generate_keys_v2(&nvs_sec_default_scheme_cfg, &cfg);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to generate NVS encr-keys: [0x%02X] (%s)", ret, esp_err_to_name(ret));return ret;}}ret = nvs_flash_secure_init(&cfg);if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_LOGE(TAG, "Failed to initialize NVS partition: [0x%02X] (%s)", ret, esp_err_to_name(ret));return ret;}ESP_LOGI(TAG, "NVS partition \"%s\" is encrypted.", NVS_DEFAULT_PART_NAME);return ret;
#else // CONFIG_NVS_ENCRYPTIONreturn nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
#endif
}

这里,对于app_main函数中的代码片段来说:

    //Initialize NVSesp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);

先调用nvs_flash_init函数一次,检查其返回值。如果返回值为ESP_ERR_NVS_NO_FREE_PAGES或者ESP_ERR_NVS_NEW_VERSION_FOUND,则先调用nvs_flash_erase()擦除,之后再次调用nvs_flash_init函数;如果不是这两个返回值,则直接检查返回值即可。

2)nvs_flash_erase函数

函数原型

extern "C" esp_err_t nvs_flash_erase(void)

函数功能

擦除默认的NVS分区。擦除默认NVS 分区(标签为“nvs”的分区)的所有内容。

如果分区已初始化,则此函数首先取消初始化它。之后,必须再次初始化分区才能使用。

函数参数

无。

函数返回值

成功返回ESP_OK。

nvs_flash_erase函数在C:\Espressif\frameworks\esp-idf-v5.2.1\components\nvs_flash\src\nvs_api.cpp中,代码如下:

extern "C" esp_err_t nvs_flash_erase(void)
{return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
}

关于nvs_flash_init函数、nvs_flash_erase函数以及NVS的详细内容,笔者后续会有专门文章进行讲解。

3)wifi_init_sta函数

wifi_init_sta函数就在main\station_example_main.c中,代码如下:

void wifi_init_sta(void)
{s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));esp_event_handler_instance_t instance_any_id;esp_event_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&instance_got_ip));wifi_config_t wifi_config = {.sta = {.ssid = EXAMPLE_ESP_WIFI_SSID,.password = EXAMPLE_ESP_WIFI_PASS,/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.*/.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,.sae_pwe_h2e = ESP_WIFI_SAE_MODE,.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );ESP_ERROR_CHECK(esp_wifi_start() );ESP_LOGI(TAG, "wifi_init_sta finished.");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually* happened. */if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else {ESP_LOGE(TAG, "UNEXPECTED EVENT");}
}

对于wifi_init_sta函数的详细解析,请看下回。

这篇关于ESP32-C3 Wi-Fi STA模式打通(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967062

相关文章

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

SQL Server身份验证模式步骤和示例代码

《SQLServer身份验证模式步骤和示例代码》SQLServer是一个广泛使用的关系数据库管理系统,通常使用两种身份验证模式:Windows身份验证和SQLServer身份验证,本文将详细介绍身份... 目录身份验证方式的概念更改身份验证方式的步骤方法一:使用SQL Server Management S

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2

Nginx location匹配模式与规则详解

《Nginxlocation匹配模式与规则详解》:本文主要介绍Nginxlocation匹配模式与规则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、环境二、匹配模式1. 精准模式2. 前缀模式(不继续匹配正则)3. 前缀模式(继续匹配正则)4. 正则模式(大

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架