从零开始学ESP32:个人笔记记录:
芯片型号: ESP32
网络环境支持:LWIP
IDF.PY-SDK: ESP-IDF v4.3
芯片功能: 支持STA/AP网络共存模式:
工程: esp-idf/examples/get-started/hello_world
例程: esp-idf/examples/wifi/getting_started/station/main
基本头文件:
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
Cmakelisys.txt配置
idf_component_register(SRCS "test_wlan.c"
INCLUDE_DIRS "."
INCLUDE_DIRS "$ENV{IDF_PATH}/components/spi_flash/include"
INCLUDE_DIRS "$ENV{IDF_PATH}/components/nvs_flash/include"
)
component.mk配置
COMPONENT_ADD_INCLUDEDIRS := .
基本实现代码和解析:
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define EXAMPLE_ESP_MAXIMUM_RETRY 10
#define AP_WIFI_SSID "ESP32-AP-MODU" //创建出来的AP模式WIFI(热点)
#define AP_WIFI_PASS "123456789" //AP模式密码
#define STA_WIFI_SSID "my_wifi" //连接路由WIFI的账号
#define STA_WIFI_PASS "123456789" //连接路由WIFI的密码
//重封装打印
#define D_BUG(frtc, frtl...) \
do{ ESP_LOGI( __FUNCTION__ , frtc,##frtl); } while(0)
static EventGroupHandle_t s_wifi_event_group; //全局事件句柄
void W_staDisConnectedEv(void)
{
if(s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
{
esp_wifi_connect();
s_retry_num++;
D_BUG("retry to connect to the AP \r\n");
}
else
{
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
D_BUG("connect to the AP fail \r\n");
return ;
}
void W_apStaConnectedEv( void* event_data )
{
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
D_BUG("station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
/* 一台设备连接到ESP32 */
}
void W_apStaDisConnectEv( void* event_data )
{
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
D_BUG("station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
/* 一台设备离开了ESP32 */
}
void W_ipGotHostAddr( void* event_data )
{
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
D_BUG("got ip:" IPSTR, IP2STR(&event->ip_info.ip) );
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
/*************************
* 函数;W_eventHandler
*
*
* 说明: 事件处理回调函数
* */
static void W_eventHandler( void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data )
{
/* 事件剥离 */
if( event_base == WIFI_EVENT )
{
switch ( event_id )
{
case WIFI_EVENT_STA_START: esp_wifi_connect(); break; // STA START
case WIFI_EVENT_STA_STOP: D_BUG("STA stop\r\n"); break; // STA STOP
case WIFI_EVENT_STA_DISCONNECTED: W_staDisConnectedEv(); break; // STA RECONECT
case WIFI_EVENT_AP_START: D_BUG("AP start\r\n"); break; // AP START
case WIFI_EVENT_AP_STOP: D_BUG("AP stop\r\n"); break; // AP STOP
case WIFI_EVENT_AP_STACONNECTED: W_apStaConnectedEv( event_data ); break; // 一台设备连接AP
case WIFI_EVENT_AP_STADISCONNECTED: W_apStaDisConnectEv(event_data ); break; // 一台设备断开AP
default: break;
}
}
else if( event_base == IP_EVENT ) // 路由事件ID 组
{
switch ( event_id )
{
case IP_EVENT_STA_GOT_IP: W_ipGotHostAddr(event_data); break; //获取到指定IP
case IP_EVENT_STA_LOST_IP: D_BUG("AP stop\r\n"); break;
case IP_EVENT_AP_STAIPASSIGNED: D_BUG("AP stop\r\n"); break;
default: break;
}
}
return ;
}
/*******************************
* 函数: WLAN_netConfDev
*
*
* 说明: WIFI - AP -STA 共存模式同时开启函数
* */
void WLAN_netConfDev(char * ssid_sta , char * pwssd_sta )
{
int STA_MAX_RETRY_NUM = 10; // sta 模式下最大连接次数
int AP_WIFI_CHANNEL = 13; // AP 模式下得通道
int AP_MAX_STA_CONN = 3; // AP支持最大STA连接数 - 允许最大连接数量
esp_event_handler_instance_t instance_any_id = {0}; //处理ID 实例句柄
esp_event_handler_instance_t instance_got_ip = {0}; //处理IP 实例句柄
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(); //创建网络配置-默认是STA
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // WIFI设备配置
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // WIFI设备初始化
/* 创建ID 事件实例回调
* WIFI_EVENT = WIFI事件
* ESP_EVENT_ANY_ID = 监听所有得ID事件
* W_eventHandler = 回调函数
* NULL
* instance_any_id = 处理ID实例句柄
* */
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&W_eventHandler,
NULL,
&instance_any_id));
/* 创建IP 事件实例回调
* WIFI_EVENT = WIFI事件
* IP_EVENT_STA_GOT_IP = STA事件
* W_eventHandler = 回调函数
* NULL
* instance_any_id = 处理IP实例句柄
* */
ESP_ERROR_CHECK( esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&W_eventHandler,
NULL,
&instance_got_ip) );
/* 创建 并 初始化STA对象 */
wifi_config_t wifi_configSta = {
.sta =
{
/*ssid 和 password 成员在结构体里面是数组,不能直接将指针丢给它
* 在外面赋值
* strcpy( (char *) wifi_configSta.sta.ssid , STA_WIFI_SSID);
* strcpy( (char *) wifi_configSta.sta.password , STA_WIFI_PASS);
*/
// .ssid = STA_WIFI_SSID;
// .password = STA_WIFI_PASS;
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {
.capable = true,
.required = false,
},
},
};
strcpy( (char *) wifi_configSta.sta.ssid , ssid_sta );
strcpy( (char *) wifi_configSta.sta.password , pwssd_sta);
/* 创建 并 初始化AP对象 */
wifi_config_t wifi_configAP = {
.ap =
{
.ssid = AP_WIFI_SSID,
.ssid_len = strlen( AP_WIFI_SSID ),
.channel = AP_WIFI_CHANNEL,
.password = AP_WIFI_PASS,
.max_connection = AP_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK,
}
};
/***
* 注意: 将两个成员合成一个结构体里面然后 进行配置的时候,是无效的
* 必须是STA 和 AP 各自一个结构体成员
* */
// 设置WIFI为 AP-STA 共存模式
ESP_ERROR_CHECK(esp_wifi_set_mode( WIFI_MODE_APSTA) );
// 设置AP模式配置
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP , &wifi_configAP) );
// 设置STA模式配置
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_configSta) );
ESP_ERROR_CHECK(esp_wifi_start() );
D_BUG("wifi_init_sta finished.\r\n");
/* 等待全局事件发生 -- 发生对应事件就等于完成一个动作 */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT)
{
D_BUG("connected to ap SSID:%s password:%s \r\n",ssid, pwssd);
}
else if (bits & WIFI_FAIL_BIT)
{
D_BUG("Failed to connect to SSID:%s, password:%s \r\n",ssid, pwssd);
}
else
{
D_BUG("UNEXPECTED EVENT \r\n");
}
/* 清除当前申请的设备句柄 */
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID , instance_any_id));
/* 删除当前事件组 */
vEventGroupDelete(s_wifi_event_group);
}
/* 主函数进行调用 */
int app_main( void )
{
WLAN_netConfDev( STA_WIFI_SSID , STA_WIFI_PASS );
}
/* 完 */
额外提及一下设置AP的地址和网关,子网掩码等等信息 参考下面
void W_setApDhcpInfo()
{
tcpip_adapter_ip_info_t apNetConfInfo = {0};
//初始化网络和DHCP有关内存,必须要提前执行这个API 不然下面操作直接让设备重启
tcpip_adapter_init();
// 将AP模式的DHCP 模式先关闭
tcpip_adapter_dhcps_stop ( TCPIP_ADAPTER_IF_AP );
//将对应的地址转成对应的字节序, 要注意apNetConfInf成员是结构体嵌套结构体,才是数组
//
IP4_ADDR( &apNetConfInfo.ip , 192 , 168 , 1 , 1); //设置IP
IP4_ADDR( &apNetConfInfo.gw , 192 , 168 , 1 , 1); //设置网关
IP4_ADDR( &apNetConfInfo.netmask , 255 , 255 , 255 , 0); //设置子网掩码
tcpip_adapter_set_ip_info( TCPIP_ADAPTER_IF_AP , &apNetConfInfo ); //设置IP信息
tcpip_adapter_dhcps_stop( TCPIP_ADAPTER_IF_AP ); //重新启动AP模式 DHCP
}
这个函数可以上面的 AP/STA 模式启动之后执行
成功之后正常情况是:
连接上当前路由的WIFI 并且打印处对应的IP
然后使用手机搜索WIFI的时候会发现多出一个$(AP_WIFI_SSID)名称的热点。
说明:笔记使用-记录(抄袭我就吊你 J J )
关注微信公众号 一起学习 ( 技术Code城 )