ESP32 IDF开发 应用篇⑫Wifi STA模式和AP模式的使用
别迷路-导航栏
快速导航找到你想要的(文章目录)
此篇文章如果对你有用,请点赞收藏,您的支持就是博主坚持的动力。
1、博主写这篇技术文章的目的:
(1)、了解 WIFI的3中工作模式;
(2)、掌握 esp32wifi的基本使用;
2、 概述
在前面章节已经为大家介绍了ESP32的基本应用,idf框架已经有了基本认识。从本章开始将带领大家一起探索esp32的核心功能wifi。
(1) Wifi的3中工作模式
•Station模式,也叫站点模式;
•AP模式,也叫Soft-AP模式,可以理解为WiFi热点模式;
•以上两种的集合模式,Station 兼Soft-AP,也是Mesh NetWork的实现基础;
任何基于ESP32的WiFi功能开发,都是基于上面其中一种工作模式来进行开发。所以,它们是我们WiFi基础学习的重点。
(2) 什么是STA模式
Station, 类似于无线终端,sta本身并不接受无线的接入,它可以连接到AP,一般无线网卡即工作在该模式。
(3) 什么是AP模式
Access Point,提供无线接入服务,允许其它无线设备接入,提供数据访问,一般的无线路由/网桥工作在该模式下。AP和AP之间允许相互连接。
简单理解AP就是路由器,STA就是手机,STA连接AP。
3、 Wifi库的介绍
有关wifi详细函数请参esp-idf\components\esp_wifi\include\esp_wifi.h
在这里我只做几个重要经常使用的API函数讲解
(1)wifi初始化,主要初始化wifi_init_config_t结构体
/**
* @brief 初始化WiFi
* WiFi驱动程序的分配内存,例如WiFi控制结构,RX / TX缓冲区,WiFi NVS结构等,此WiFi也将启动WiFi任务
* @注意1.必须先调用此API,然后才能调用所有其他WiFi API
* @注意2.始终使用WIFI_INIT_CONFIG_DEFAULT宏将配置初始化为默认值
* 当将更多字段添加到wifi_init_config_t中时,确保所有字段都具有正确的值
* 在将来的版本中。如果要设置所有者的初始值,请覆盖默认值
* 由WIFI_INIT_CONFIG_DEFAULT设置,请注意
* wifi_init_config_t应该始终为WIFI_INIT_CONFIG_MAGIC!
* @param 配置指向WiFi初始化配置结构的指针
* @return
* - ESP_OK: succeed
* - ESP_ERR_NO_MEM: 内存不足
*/
esp_err_t esp_wifi_init(const wifi_init_config_t *config);
(2)设置wifi模式
/**
* @brief 设置WiFi操作模式
*将WiFi操作模式设置为station,soft-AP或station + soft-AP,
*默认模式是软AP模式。
* @param 模式WiFi操作模式
* @return
*-ESP_OK:成功
*-ESP_ERR_WIFI_NOT_INIT:WiFi未由esp_wifi_init初始化
*-ESP_ERR_INVALID_ARG:无效的参数
*-其他:请参阅esp_err.h中的错误代码
*/
esp_err_t esp_wifi_set_mode(wifi_mode_t mode);
(3)设置wifi wifi_config_t结构体
/**
* @brief 设置ESP32 STA或AP的配置
* @注意1.仅当启用了指定的接口时,才能调用此API,否则,API将失败
* @注意2。对于工作站配置,bssid_set需要为0;否则为0。仅当用户需要检查AP的MAC地址时才需要设置为1。
* @注意3. ESP32仅限于一个通道,因此在soft-AP + station模式下,soft-AP会自动将其通道调整为与ESP32站的通道。
* @param 接口
* @param conf 工作站或soft-AP配置
*
* @return
*-ESP_OK:成功
*-ESP_ERR_WIFI_NOT_INIT:WiFi未由esp_wifi_init初始化
*-ESP_ERR_INVALID_ARG:无效的参数
*-ESP_ERR_WIFI_IF:无效的界面
*-ESP_ERR_WIFI_MODE:无效模式
*-ESP_ERR_WIFI_PASSWORD:无效的密码
*-ESP_ERR_WIFI_NVS:WiFi内部NVS错误
*-其他:请参阅esp_err.h中的错误代码
*/
esp_err_t esp_wifi_set_config(wifi_interface_t interface, wifi_config_t *conf);
(4)启动wifi
/**
* @brief 根据当前配置启动WiFi
*如果模式为WIFI_MODE_STA,则创建站点控制块并启动站点
*如果模式为WIFI_MODE_AP,则会创建soft-AP控制块并启动soft-AP
*如果模式为WIFI_MODE_APSTA,则创建soft-AP和站点控制块并启动soft-AP和站点
*
* @return
*-ESP_OK:成功
*-ESP_ERR_WIFI_NOT_INIT:WiFi未由esp_wifi_init初始化
*-ESP_ERR_INVALID_ARG:无效的参数
*-ESP_ERR_NO_MEM:内存不足
*-ESP_ERR_WIFI_CONN:WiFi内部错误,站或soft-AP控制块错误
*-ESP_FAIL:其他WiFi内部错误
*/
esp_err_t esp_wifi_start(void);
(4) wifi回调函数,具体分析参考:
【ESP32 IDF开发 应用篇⑬ 连接Wifi回调函数esp_event_handler_register专题】
/**
* @brief 将事件处理程序注册到系统事件循环。
*
*此函数可用于注册以下任一处理程序:(1)特定事件,
*(2)某个事件基础的所有事件,或(3)系统事件循环已知的所有事件。
*
*-特定事件:指定确切的event_base和event_id
*-具有特定基准的所有事件:指定确切的event_base并将ESP_EVENT_ANY_ID用作event_id
*-循环已知的所有事件:将ESP_EVENT_ANY_BASE用作event_base,将ESP_EVENT_ANY_ID用作event_id
*
*可以将多个处理程序注册到事件。将单个处理程序注册到多个事件是
*也可以。但是,将同一处理程序多次注册到同一事件将导致
*以前的注册将被覆盖。
*
* @param [in] event_base事件的基本ID,用于为其注册处理程序
* @param [in] event_id要为其注册处理程序的事件的ID
* @param [in] event_handler处理程序函数,在调度事件时将调用该函数
* @param [in] event_handler_arg数据,除事件数据外,在调用时传递给处理程序
*
* @note 事件循环库不维护event_handler_arg的副本,因此用户应
*确保在调用处理程序时event_handler_arg仍指向有效位置
*
* @返回
*-ESP_OK:成功
*-ESP_ERR_NO_MEM:无法为处理程序分配内存
*-ESP_ERR_INVALID_ARG:事件库和事件ID的无效组合
*-其他:失败
*/
esp_err_t esp_event_handler_register(esp_event_base_t event_base,
int32_t event_id,
esp_event_handler_t event_handler,
void* event_handler_arg);
4、 Wifi sta模式和ap模式的软件设计
•sta模式
(1)、创建wifi连接事件组;
(2)、初始化wifi,注册回调函数
主要对2个结构体初始化
wifi_init_config_t结构体一般使用系统默认的参数即可,使用函数WIFI_INIT_CONFIG_DEFAULT()赋值
wifi_init_config_t cfg =WIFI_INIT_CONFIG_DEFAULT();//给wifi_init_config_t结构体初始化系统默认的数据
结构体内容:
/**
* @brief WiFi stack configuration parameters passed to esp_wifi_init call.
*/
typedef struct {
system_event_handler_t event_handler; /**< WiFi event handler */
wifi_osi_funcs_t* osi_funcs; /**< WiFi OS functions */
wpa_crypto_funcs_t wpa_crypto_funcs; /**< WiFi station crypto functions when connect */
int static_rx_buf_num; /**< WiFi static RX buffer number */
int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */
int tx_buf_type; /**< WiFi TX buffer type */
int static_tx_buf_num; /**< WiFi static TX buffer number */
int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */
int csi_enable; /**< WiFi channel state information enable flag */
int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */
int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */
int nvs_enable; /**< WiFi NVS flash enable flag */
int nano_enable; /**< Nano option for printf/scan family enable flag */
int tx_ba_win; /**< WiFi Block Ack TX window size */
int rx_ba_win; /**< WiFi Block Ack RX window size */
int wifi_task_core_id; /**< WiFi Task Core ID */
int beacon_max_len; /**< WiFi softAP maximum length of the beacon */
int mgmt_sbuf_num; /**< WiFi management short buffer number, the minimum value is 6, the maximum value is 32 */
uint64_t feature_caps; /**< Enables additional WiFi features and capabilities */
int magic; /**< WiFi init magic number, it should be the last field */
} wifi_init_config_t;
wifi_config_t结构体只要是对sta和ap模式的SSID和PASSWORD进行设置
typedef union {
wifi_ap_config_t ap; /**< configuration of AP */
wifi_sta_config_t sta; /**< configuration of STA */
} wifi_config_t;
wifi_ap_config_t
/** @brief ESP32的Soft-AP配置设置 */
typedef struct {
uint8_t ssid[32]; /**< SSID 如果ssid_len字段为0,则该字符串必须为Null终止的字符串。 否则,根据ssid_len设置长度. */
uint8_t password[64]; /**< 密码.*/
uint8_t ssid_len; /**< SSID字段的可选长度. */
uint8_t channel; /**< ESP32 soft-AP通道 */
wifi_auth_mode_t authmode; /**< ESP32 soft-AP的认证方式。 在软AP模式下不支持AUTH_WEP */
uint8_t ssid_hidden; /**< 是否广播SSID,默认为0,广播SSID */
uint8_t max_connection; /**< 允许连接的最大站数,默认为4,最大为4 */
uint16_t beacon_interval; /**< 信标间隔100〜60000 ms,默认100 ms */
} wifi_ap_config_t;
wifi_sta_config_t
/** @brief ESP32的STA配置设置 */
typedef struct {
uint8_t ssid[32]; /**< 目标AP的SSID。 空终止的字符串。 */
uint8_t password[64]; /**< 目标AP的密码。 空终止的字符串。*/
wifi_scan_method_t scan_method; /**< 执行所有通道扫描或快速扫描 */
bool bssid_set; /**< 是否设置目标AP的MAC地址。 通常,station_config.bssid_set需要为0;否则为0。 仅当用户需要检查AP的MAC地址时才需要设置为1。*/
uint8_t bssid[6]; /**< 目标AP的MAC地址*/
uint8_t channel; /**< 目标AP的信道。 设置为1〜13可以在连接到AP之前从指定的通道开始扫描。 如果AP的信道未知,则将其设置为0。*/
uint16_t listen_interval; /**< 设置WIFI_PS_MAX_MODEM时ESP32站接收信标的监听间隔。 单位:AP信标间隔。 如果设置为0,则默认为3。 */
wifi_sort_method_t sort_method; /**< 按rssi或安全模式对列表中的连接AP进行排序 */
wifi_scan_threshold_t threshold; /**< 设置sort_method时,将仅使用具有比所选身份验证模式更安全的身份验证模式和比最小RSSI强的信号的AP。 */
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */
} wifi_sta_config_t;
(3)、等待wifi连接打印连接消息
5、 Wifi sta模式实例
方法1
将esp-idf\examples\wifi\getting_started\station目录下的工程复制到自己的目录下面改名字为 idf_wifi_sta即可 文件名字改为 i idf_wifi_sta.C makefile文件也改成 PROJECT_NAME := idf_wifi_sta即可,然后复制一下代码测试。
在make menuconfig 中
Example Configuration —>
WiFi SSID:设置账号
WiFi Password :设置密码
Maximum retry :重复连接次数
然后保存退出
方法2:如何在menuconfig中添加编译菜单
复制原来做的工程,改好名字
在工程的main目录下添加Kconfig.projbuild
然后在Kconfig.projbuild中添加
menu “Example Configuration”
config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config ESP_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
endmenu
这样make menuconfig时就会有Example Configuration选项
config ESP_WIFI_PASSWORD、config ESP_WIFI_PASSWORD、config ESP_MAXIMUM_RETRY就是程序中使用的宏
/**********************************************************************
* 文件名: idf_wifi_sta.c
* 创建人:
* 创建日期:
* 修改人:
* 修改日期:
* 版本号: V1.1
* 备注:
* 公司:
********************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "nvs.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "lwip/err.h"
#include "lwip/sys.h"
static const char *TAG = "WIFI_STA";
//事件标志组
static EventGroupHandle_t xCreatedEventGroup_WifiConnect = NULL;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static int retry_num = 0;
/***********************************************************************
* 函数:
* 描述: wifi 回调函数
* 参数:
* 返回: 无
* 备注:
************************************************************************/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
ESP_LOGI(TAG, "event_base: %s ; event_id : %d",event_base,event_id);
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) //wifi断开时
{
if (retry_num < CONFIG_ESP_MAXIMUM_RETRY) //重新连接次数
{
esp_wifi_connect();
retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
}
else
{
xEventGroupSetBits(xCreatedEventGroup_WifiConnect, WIFI_FAIL_BIT);
xEventGroupClearBits(xCreatedEventGroup_WifiConnect, WIFI_CONNECTED_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)//获得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));
retry_num = 0;
xEventGroupSetBits(xCreatedEventGroup_WifiConnect, WIFI_CONNECTED_BIT);
xEventGroupClearBits(xCreatedEventGroup_WifiConnect, WIFI_FAIL_BIT);
}
}
/***********************************************************************
* 函数:
* 描述: wifi sta初始化代码相对比较固定,一般不需要做修改
* 参数:
* 返回: 无
* 备注:
************************************************************************/
void wifi_init_sta(void)
{
ESP_ERROR_CHECK(esp_netif_init());//初始化TCP / IP堆栈和esp-netif
ESP_ERROR_CHECK(esp_event_loop_create_default()); //创建默认event loop
esp_netif_create_default_wifi_sta();//创建默认的WIFI STA。
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//给wifi_init_config_t结构体初始化系统默认的数据
ESP_ERROR_CHECK(esp_wifi_init(&cfg));//使用默认的参数初始化wifi
//注册wifi 连接过程中回调函数
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
//设置账户和密码,在menuconfig中设置
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_ESP_WIFI_SSID,
.password = CONFIG_ESP_WIFI_PASSWORD
//.ssid = "ssid",
//.password = "password"
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );//设置为sta模式
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );//启动
ESP_LOGI(TAG, "wifi_init_sta finished.");
}
/***********************************************************************
* 函数:
* 描述: 主函数
* 参数:
* 返回: 无
* 备注:
************************************************************************/
void app_main()
{
//初始化NVS
esp_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连接
xCreatedEventGroup_WifiConnect = xEventGroupCreate();
//WIFI sta初始化
wifi_init_sta();
//等待连接成功,或已经连接有断开连接,此函数会一直阻塞,只有有连接
EventBits_t bits = xEventGroupWaitBits(xCreatedEventGroup_WifiConnect,// 事件标志组句柄
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, // 等待bit0和bit1被设置
pdFALSE, //TRUE退出时bit0和bit1被清除,pdFALSE退出时bit0和bit1不清除
pdFALSE, //设置为pdTRUE表示等待bit1和bit0都被设置,pdFALSE表示等待bit1或bit0其中一个被设置
portMAX_DELAY); //等待延迟时间,一直等待
if (bits & WIFI_CONNECTED_BIT)
{
ESP_LOGI(TAG, "connected to ap" );
}
else if (bits & WIFI_FAIL_BIT)
{
ESP_LOGI(TAG, "Failed to connect");
}
//注销删除事件
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
vEventGroupDelete(xCreatedEventGroup_WifiConnect);
}
6、 Wifi ap模式实例
/**********************************************************************
* 文件名: idf_wifi_sta.c
* 创建人:
* 创建日期:
* 修改人:
* 修改日期:
* 版本号: V1.1
* 备注:
* 公司:
********************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "nvs.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "lwip/err.h"
#include "lwip/sys.h"
static const char *TAG = "WIFI_AP";
/***********************************************************************
* 函数:
* 描述: wifi 回调函数
* 参数:
* 返回: 无
* 备注:
************************************************************************/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
ESP_LOGI(TAG, "event_base: %s ; event_id : %d",event_base,event_id);
if (event_id == WIFI_EVENT_AP_STACONNECTED) //有STA连接
{
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
}
else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) //STA断开连接
{
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
/***********************************************************************
* 函数:
* 描述: wifi sta初始化代码相对比较固定,一般不需要做修改
* 参数:
* 返回: 无
* 备注:
************************************************************************/
void wifi_init_ap(void)
{
ESP_ERROR_CHECK(esp_netif_init());//初始化TCP / IP堆栈和esp-netif
ESP_ERROR_CHECK(esp_event_loop_create_default()); //创建默认event loop
esp_netif_create_default_wifi_ap();//创建默认的WIFI ap。
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//给wifi_init_config_t结构体初始化系统默认的数据
ESP_ERROR_CHECK(esp_wifi_init(&cfg));//使用默认的参数初始化wifi
//注册wifi 连接过程中回调函数
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
//设置账户和密码,在menuconfig中设置
wifi_config_t wifi_config = {
.ap = {
.ssid = "idf_wifi_ap",
.password = "123456789",//此处的密码长度不能小于8位
.max_connection = 1,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP) );//设置为sta模式
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );//启动
ESP_LOGI(TAG, "wifi_init_AP finished.");
}
/***********************************************************************
* 函数:
* 描述: 主函数
* 参数:
* 返回: 无
* 备注:
************************************************************************/
void app_main()
{
//初始化NVS
esp_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_AP");
//WIFI sta初始化
wifi_init_ap();
}
在启动过程中,需要注意一点密码不能小于8位,小于8位系统会一直重启。
所有文章源代码:https://download.csdn.net/download/lu330274924/88518092