从零开始学ESP32:(二) 开启ESP32WIFI -STA和AP模式共存

2023-05-16

从零开始学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城 )

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从零开始学ESP32:(二) 开启ESP32WIFI -STA和AP模式共存 的相关文章

  • ESP32 上快捷部署 Tensorflow lite 机器学习(TinyML)

    在这篇文章中 我将向您展示使用 Arduino IDE 将 TensorFlow Lite 模型部署到 ESP32 的最简单方法 无需任何编译内容 Arduino 库 这个 Arduino 库是为了简化使用 Arduino IDE 将用于微
  • 【低功耗蓝牙】① 蓝牙广播数据格式分析

    摘要 本文章主要讲解了蓝牙的发展史 蓝牙信号 蓝牙广播数据的格式 最后使用ESP32芯片MicroPython固件给出了蓝牙广播的具体代码 是蓝牙初学者很好的参考资料 也可以参考下我在B站的蓝牙视频教程 ESP32教程 第二章 低功耗蓝牙B
  • ESP32s3 MSC/U盘 虚拟串口

    ESP32s3 MSC U盘 虚拟串口 开发环境是 IDF4 4 芯片 esp32s3 在项目中想要用到把内部的FLASH做成U盘 但是在idf4 4中没有找到MSC相关例程 如图 1 我在网上只找到esp32s2的例程 https git
  • Arduino IDE编译烧写ESP32 CAM

    一 安装Arduino IED 到官网下载IDE 二 安装ESP32 工具 打开菜单 文件 首选项 在设置页 附加开发板管理器网址 添加 https dl espressif com dl package esp32 index json
  • ESP32 ADC –使用Arduino IDE读取模拟值

    本文介绍了如何使用Arduino IDE通过ESP32读取模拟输入 模拟读取对于从电位计或模拟传感器等可变电阻读取值非常有用 模拟输入 ADC ADC是非线性的 analogRead 函数 其他有用的功能 使用ESP32从电位计读取模拟值
  • ESP32 SIM800L:发送带有传感器读数的文本消息(SMS警报)

    在这个项目中 我们将使用T Call ESP32 SIM800L模块创建一个SMS通知系统 当传感器读数高于或低于特定阈值时 该模块会发送SMS 在此示例中 我们将使用DS18B20温度传感器 并在温度高于28 C时发送短信 一旦温度降低到
  • 单片机开发---ESP32S3移植lvgl+触摸屏

    书接上文 单片机开发 ESP32 S3模块上手 本章内容 熟悉一下ESP32S3的开发 修改范例程序的lvgl 使之能够匹配现在的显示屏 具体工作大概为通过SPI接口连接一块SPI串口屏幕 并且适配lvgl 最后加上触摸屏作为输入 屏幕 用
  • esp32-S3专题二:内存2之RTC内存、FLASH使用

    承接上文 讲一下esp32上剩下的几个存储空间的用途 目录 一 RTC存储器 一 RTC 快速存储器 二 RTC 慢速存储器 二 Flash 一 NVS 表 二 程序和OTA分区 三 SPIFFS 文件系统 三 总结 一 RTC存储器 es
  • 启明云端分享

    提示 启明云端从2013年起就作为Espressif 乐鑫科技 大中华区合作伙伴 我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程 同时也用心推出了基于乐鑫的相关应用方案 希望你能第一时间了解并快速用上好的方案和产品
  • arduino+ESP32 web配网演示代码

    include
  • ESP32(Micro Python) LVGL 传感器数值显示

    本程序用于显示SR04超声波传感器和BMP280气压温度传感器的读数 由于高度数值类型不符合要求 BMP280改为显示气压和温度值 气压值分两部分显示 分别为千帕值 100 避免超出表盘显示范围 和千帕值的两位小数 由于标签不能显示动态数值
  • ESP32 的esp_http_client详解

    说明 我使用的是esp idf V3 1 3 官方给我们封装好了 HTTP 使用起来还是很方便 一 wifi连接 在main函数里面主要是做了wifi连接的初始化和HTTP任务的创建 如下是main的全部内容 void app main e
  • ESP32-cam 初体验 从esp32-cam的购买到局域网监控的实现

    ESP32 cam小项目 helloworld项目 前言 手头有一块esp32 cam闲置很久了 因为比赛和找工作的事情导致许欸小延期了很久 还是因为懒 最近从小仓库把板子捞出来了 上手玩一玩 本次学习参考了B站up 小铭同学 的教程 教程
  • 还是 “月饼” 后续,玩转炫彩 “月饼” 之 问题说明

    画一个 月饼 陪我过中秋 开发板后续问题跟进说明 目录 前言 一 出现问题 二 寻求办法 三 若有所思 四 问题测试 结语 悬赏送开发板 前言 本文有纯理论玩家是永远不会经历的实际问题 嵌入式工程师不动手永远出不了作品 本文最后有送开发板的
  • 解决VSCode中查看ESP32日志乱码

    问题现象 在VSCode的Monitor中查看ESP32输出的日志乱码 如下图 原因 在VSCode中IDF默认的Monitor串口波特率为460800 然而ESP32输出Log的串口波特率默认为115200 因串口波特率不匹配导致Moni
  • ASIC中带有MUX的时钟路径时序约束

    链接 https pan baidu com s 1BrAsabLYLGbvdXJB2LQwiA 提取码 mgrn
  • ESP32-CAM配置开发环境并烧录程序运行

    环境准备 ESP32 CAM开发板 烧录器 摄像头和一根USB线束连接电脑即可 Arduino下载完成后打开 不同版本的菜单栏可能稍微不同 仔细找即可 选择下面的选项 联网自动下载ESP32 CAM的 环境 端口和当前的一致即可 正常连接应
  • 有没有办法在 python/opencv 中从单摄像头视频生成实时深度图?

    我试图将单个图像转换为其深度图 但我找不到任何有用的教程或文档 我想使用 opencv 但是如果您知道使用张量流等获取深度图的方法 我很高兴听到它 有很多关于立体视觉的教程 但我想让它更便宜 因为它是一个帮助盲人的项目 我目前正在使用 es
  • ESP32:dsb1820 温度传感器给出恒定的负 127 读数

    我正在尝试使用连接到 esp32 微控制器的单个 dsb1820 温度传感器来获取温度读数 传感器连接到 esp32 的 GPIO 4 我打算将温度读数发送到云端 我面临的问题是温度读数总是给出值 127 我在网上某处读到 当 dsb182
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce

随机推荐

  • MySQL常见用法

    文章目录 一 时间类1 1 DATE SUB 函数1 2 NOW CURDATE CURTIME DATE 函数1 3 实战 二 统计类三 字符类3 1 LOCATE 函数3 2 concat 函数3 3 concat ws 函数3 4 g
  • 牢记公式,ardupilot EKF2就是纸老虎(四)!

    版权声明 xff1a 本文为博主原创文章 xff0c 转载请附上博文链接 xff01 四 一睹EKF2芳容 因为篇幅过长 xff0c 写的一些公式会乱码 xff0c 没办法只能把 牢记公式 xff0c ardupilot EKF2就是纸老虎
  • Java Optional使用

    文章目录 Optional一 Optional 简介二 创建 Optional 实例2 1 empty 方法2 2 of 方法2 3 ofNullable 方法 三 Optional的使用3 1 访问 Optional 对象的值3 1 1
  • 正则表达式:基础详解以及在Java中的使用

    文章目录 一 正则表达式1 1 正则表达式中的特殊字符1 2 正则表达式所支持的合法字符1 3 方括号表达式1 4 边界匹配符1 5 三种模式的数量表示符 二 应用2 1 String 类2 2 Pattern 类和 Matcher 类 一
  • Python学习:关键字global和nonlocal的用法说明

    一 global global关键字用来在函数或其他局部作用域中使用全局变量 1 1 如果局部要对全局变量修改 xff0c 而不使用global关键字 count 61 0 def global test count 43 61 1 pri
  • Python:flask框架下前后端的数据交互

    文章目录 前提 一 前端发送数据 xff0c 后端接受数据1 1 路由传参数 数据 1 2 表单提交 二 后端发送数据 xff0c 前端接受数据 前提 后端 xff1a python 的 flask 框架 前端 xff1a html css
  • Python关于None的报错:'NoneType' object is not iterable和cannot unpack non-iterable NoneType object

    文章目录 一 TypeError 39 NoneType 39 object is not iterable xff08 类型错误 xff1a 39 NoneType 39 对象不是可迭代的 xff09 二 TypeError cannot
  • Git:合并分支----git merge命令应用的三种情景

    文章目录 一 git merge 命令应用的三种情景1 1 快进 无冲突 1 2 非 快进 xff0c 修改不同文件 无冲突 1 3 非 快进 xff0c 修改相同文件 有冲突 一 git merge 命令应用的三种情景 1 1 快进 无冲
  • Git:远程分支----git fetch命令的使用

    git fetch 命令的使用 从远程主机克隆 Git 的 clone 命令会为你自动将远程主机命名为 origin xff0c 拉取它的所有数据 xff0c 创建一个指向它的 master 分支的指针 xff0c 并且在本地将其命名为 o
  • Git:移除文件----git rm命令的使用

    文章目录 一 git rm 命令使用1 1 rm 命令1 2 git rm 命令1 3 git rm f 命令1 4 git rm cached 命令 一 git rm 命令使用 Git 本地数据管理 xff0c 大概可以分为三个区 xff
  • 【OpenMv小车】OpenMv追小球的小车之pid调用

    pid py gt gt https github com wagnerc4 flight controller blob master pid py openmv 官网 xff1a http book openmv cc project
  • 【深入理解C++】函数模板作为成员函数

    文章目录 1 普通类的成员函数模板2 类模板的成员函数模板 1 普通类的成员函数模板 不管是普通类还是类模板 xff0c 它们的成员函数都可以是函数模板 xff0c 称为成员函数模板 xff0c 但不可以是虚函数 xff0c 否则编译器报错
  • QGroundControl开发之使用自定义mavlink

    工具 对QGC进行二次开发时 xff0c 常常会遇到想使用自定义mavlink的情况 xff0c 但不像APM那样编译命令会根据xml文件自动生成mavlink协议 QGC似乎不能自动生成mavlink协议 xff08 之前试过似乎不能自动
  • 字符串连接 (c语言)

    题目描述 将给定的字符串连接起来 书中的算法描述如下 xff1a 图 xff1a 字符串连接算法 输入描述 三对字符串 xff0c 每对字符串占一行 xff0c 用空格隔开 每个字符串只包含数字和英文字母大小写且长度不超过100 输出描述
  • STM32—UART中断收发 Day4

    软件 xff1a STM32CubeMX xff0c MDK ARM 硬件 xff1a 蓝桥杯物联网Lora开发板 xff0c 板载芯片STM32L071 一 STM32CubeMX配置 1 先在连接 xff08 Connectivity
  • 虚拟机出现command XXX is available in /bin/ls问题

    问题 xff1a 使用本地的shell命令时候 The command could not be located because 39 usr bin bin 39 is not included in the PATH environme
  • 全志lichee的pack命令

    全志lichee目录打包命令流程 pack 将打包命令传进去build sh脚本里面 查看buildsh里面的脚本命令 其实里面的脚本还是较为简单地的 xff0c 仅仅是作为一个过渡 xff0c 然后就跑进去buildroot script
  • Linux_kernel驱动之GPIO子系统

    前言 xff1a gpio子系统的内容在drivers gpio文件夹下 xff0c 主要文件有 xff1a devres c xff1a devres c是针对gpio api增加的devres机制的支持gpiolib c xff1a g
  • 转载:全志问题解决方法

    版权声明 xff1a 本文为博主原创文章 xff0c 遵循 CC 4 0 BY SA 版权协议 xff0c 转载请附上原文出处链接和本声明 本文链接 xff1a https blog csdn net yanzheng1113 articl
  • 从零开始学ESP32:(二) 开启ESP32WIFI -STA和AP模式共存

    从零开始学ESP32 xff1a 个人笔记记录 xff1a 芯片型号 ESP32 网络环境支持 LWIP IDF PY SDK ESP IDF v4 3 芯片功能 xff1a 支持STA AP网络共存模式 xff1a 工程 xff1a es