本文主要是介绍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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!