玩转ESP32(2):WIFI的代码实现
来源:互联网 发布:天堂2单机版java下载 编辑:程序博客网 时间:2024/06/05 16:34
玩转ESP32(2):WIFI的代码实现
ESP32作为一款WIFI+蓝牙芯片,WIFI的实现是其最基本的功能,而在ESP32中,利用WIFI可以实现STA、AP、STA+AP这三种方式。
STA代码实现
首先来看一个最简单的实现WIFI sta的例子。
#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "freertos/event_groups.h"#include "esp_system.h"#include "esp_wifi.h"#include "esp_event_loop.h"#include "esp_log.h"#include "nvs_flash.h"#define EXAMPLE_WIFI_SSID "HUAWEI001"#define EXAMPLE_WIFI_PASS "12345678"static const char *TAG = "espressif";/* FreeRTOS event group to signal when we are connected & ready to make a request */static EventGroupHandle_t wifi_event_group;/* The event group allows multiple bits for each event, but we only care about one event - are we connected to the AP with an IP? */const int CONNECTED_BIT = BIT0;static esp_err_t event_handler(void *ctx, system_event_t *event){ switch (event->event_id) { case SYSTEM_EVENT_STA_START: esp_wifi_connect(); break; case SYSTEM_EVENT_STA_GOT_IP: xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); break; case SYSTEM_EVENT_STA_DISCONNECTED: /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); break; default: break; } return ESP_OK;}static void initialise_wifi(void){ tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID, .password = EXAMPLE_WIFI_PASS, }, }; ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); ESP_ERROR_CHECK( esp_wifi_start() );}void app_main(){ ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi();}
上述例子主要实现连接SSID为espressif的路由器,并获得相应的IP。SSID和PASSWORD可以根据自己的路由信息进行更改,在拿到IP之后我们就可以进行相应的网络操作(TCP/UDP)。
其中:
STA代码详解
现在,开始对上面的代码进行详细分析。
#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "freertos/event_groups.h"#include "esp_system.h"#include "esp_wifi.h"#include "esp_event_loop.h"#include "esp_log.h"#include "nvs_flash.h"
上面是在实现WIFI sta所需要的头文件,其中前三个是freertos相关的头文件,后面几个都是espressif所定义的头文件,其中esp_system.h是系统相关头文件;esp_wifi.h是WIFI相关头文件;esp_event_loop.h是事件相关头文件。esp_log.h是espressif格式化输出的头文件。
#define EXAMPLE_WIFI_SSID "HUAWEI001"#define EXAMPLE_WIFI_PASS "12345678"static const char *TAG = "espressif";/* FreeRTOS event group to signal when we are connected & ready to make a request */static EventGroupHandle_t wifi_event_group;/* The event group allows multiple bits for each event, but we only care about one event - are we connected to the AP with an IP? */const int CONNECTED_BIT = BIT0;
上面是一些参数的定义,前面两个为ssid和密码,需要根据自己的路由器和密码进行更改。第3个是格式化输出的前缀,可以自由更改。wifi_event_group是我们定义的事件组,事件组主要是考虑到很多网络操作需要在我们连接到路由器并拿到IP之后才能进行。CONNECTED_BIT是我们定义的事件组Bit位,在此DEMO种只需要WIFI连接这一种事件。
*
Note.
事件组标志位和WIFI的事件组并不是一个东西,事件组标志位类似于原子操作,防止因为顺序错乱而导致程序问题。而WIFI事件组只是WIFI在连接过程中的某种状态。
*
static esp_err_t event_handler(void *ctx, system_event_t *event){ switch (event->event_id) { case SYSTEM_EVENT_STA_START: esp_wifi_connect(); break; case SYSTEM_EVENT_STA_GOT_IP: xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); break; case SYSTEM_EVENT_STA_DISCONNECTED: /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); break; default: break; } return ESP_OK;}
WIFI在esp32中的连接是通过几组不同的事件处理来实现的,上述代码就是在作为STA连接WIFI中需要进行处理的事件。其中SYSTEM_EVENT_STA_START为初始事件状态,在此事情状态中,调用esp_wifi_connect()操作会连接到路由器(AP)上,连接成功后,事件状态位会变为SYSTEM_EVENT_STA_CONNECTED,此时会调用DHCP进行请求IP,在拿到IP之后事件状态会变更为SYSTEM_EVENT_STA_GOT_IP。在这里我们使用了xEventGroupSetBits,设置事件组标志,后续如果有需要在拿到IP后才进行的操作只需要调用xEventGroupWaitBits就可以避免在没有拿到IP之前进行网络交互操作。
在WIFI因为某些原因断开后,事件标志位变为SYSTEM_EVENT_STA_DISCONNECTED,此时需要调用esp_wifi_connect()重新连接,并清除事件组标志位。
static void initialise_wifi(void){ tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID, .password = EXAMPLE_WIFI_PASS, }, }; ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); ESP_ERROR_CHECK( esp_wifi_start() );}
上述代码是实现初始化WIFI的核心代码,其中tcpip_adapter_init()用来初始化TCP/IP协议栈,xEventGroupCreate()用来创建事件组标志。esp_event_loop_init(event_handler, NULL)用来初始化事件event_handler,回调event_handler即我们刚刚处理的各种WIFI事件。ESP_ERROR_CHECK用来检查返回值是否为ESP_OK。WIFI_INIT_CONFIG_DEFAULT()指定需要初始化底层的参数信息,esp_wifi_init用上述信息来初始化WIFI硬件。esp_wifi_set_storage设置连接的WIFI信息(SSID和PASSWORD)保存在哪里,可选的有RAM和FLASH。wifi_config是WIFI连接时的配置信息,作为STA时只需要考虑sta的参数信息,上述代码只是制定了最基本的ssid和password信息,除此之外,还可以指定bssid和channel等相关信息。ESP_LOGI是espressif的格式化输出信息,其他还包括ESP_LOGE(错误信息)、ESP_LOGD(调试信息)。esp_wifi_set_mode设置WIFI模式,除了WIFI_MODE_STA以外还包括WIFI_MODE_AP,WIFI_MODE_APSTA。esp_wifi_set_config设置STA模式的配置信息。esp_wifi_start()根据当前配置信息开启WIFI。
void app_main(){ ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi();}
void app_main()是espressif工程的入口,类似与C语言中的main,nvs_flash_init是初始化NVS存储,initialise_wifi即初始化WIFI。在程序的后面,当需要实现其他功能时,使用vTaskCreate来创建即可。
至此,WIFI的整个连接过程结束,
AP实现
AP的实现与STA的实现很类似,只需要更改一些配置信息即可。
#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "freertos/event_groups.h"#include "esp_system.h"#include "esp_wifi.h"#include "esp_event_loop.h"#include "esp_log.h"#include "nvs_flash.h"const static char *TAG = "espressif";static void initialise_wifi(void){ tcpip_adapter_init(); ESP_ERROR_CHECK( esp_event_loop_init(NULL, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); wifi_config_t wifi_config = { .ap = { .ssid = "TestAp", .authmode = WIFI_AUTH_OPEN, .max_connection = 3, .channel = 12, }, }; ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.ap.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &wifi_config) ); ESP_ERROR_CHECK( esp_wifi_start() );}void app_main(void){ ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi();}
在设置AP时,相对STA,大体相似,只有一小部分需要更改为AP信息。
ESP_ERROR_CHECK( esp_event_loop_init(NULL, NULL) );
在AP模式下,可以不需要回调函数,当然也可以写回调来获取更多信息,可以参考esp_event.h中的定义。
wifi_config_t wifi_config = { .ap = { .ssid = "TestAp", .authmode = WIFI_AUTH_OPEN, .max_connection = 3, .channel = 12, }, };
在此DEMO中,我设置的SSID为TestAp,authmode是open,即不加密,如果设置成加密,还需要添加.password。max_connection为支持的最大连接数。channel即信道为12。其他参数可以参考esp_wifi_types.h中的wifi_ap_config_t定义。
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.ap.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &wifi_config) );
wifi_config.ap.ssid打印当前配置的AP的SSID信息, esp_wifi_set_mode(WIFI_MODE_AP)设置为AP模式,esp_wifi_set_config(WIFI_IF_AP, &wifi_config)按照当前的配置信息来设置AP。
运行之后,用手机连接测试SSID:TestAp,会出现如下界面:
AP模式也设置成功。
- 玩转ESP32(2):WIFI的代码实现
- ESP32 应用实践:ethernet 转 WiFi 实现
- 玩转ESP32(1):运行Hello World
- 深入分析 ESP32 的 WiFi 状态机
- wifi 玩转 wifi
- ESP32 WIFI透传固件
- 让 ESP32 连接到你的 WiFi 热点
- VC++玩转Native Wifi API 2---Wifi on与wifi off
- ESP32 入门试玩之前言
- 玩转WiFi共享精灵
- ESP32的资料下载页面
- 有关ESP32的部分问题
- WIFI和移动数据(2G/3G)的打开和关闭的代码实现
- 玩转免费wifi上网软件之WiFi共享精灵
- VC++玩转Native Wifi API
- Android代码实现WiFi连接
- android线程实现:实时显示所连接的wifi信号强度(代码带注释)
- Android打开WIFI或者移动网络的代码实现
- Spark函数详解系列之RDD基本转换
- program received signal SIGSEGV, Segmentation fault
- SpringBoot 配置图片虚拟路径
- HTTP接口不同项目网页之间数据交互跨域以及打开的窗口无法跳出关掉的问题
- eclipse集成插件报错
- 玩转ESP32(2):WIFI的代码实现
- 概率图模型周边
- Linux 配置用户级 的JDK
- iOS修改工程名
- Xcode9启动图及icon分辨率、尺寸、大小
- 信息系统项目管理师
- 快排两种方法
- ajaxfileuploady移动端兼容问题
- 无法保存更改Xshell会话,需要这样做!