一、目的
在上一篇《ESP32系列--第四篇 WiFi概述》我们已经将ESP32 WiFi的基本框图、功能以及API做了简单介绍,本篇我们以源代码的形式来讲讲如何使用WiFi Station功能进行联网。
二、准备
首先我们从esp-idf里面拷贝一份官方的示例代码
1、首先初始化esp-idf开发环境,命令行输入以下命令(不清楚去看《ESP32系列--第二篇 开发环境搭建-Ubuntu系统》)
get_idf
2、拷贝工程并进入到station目录中
cp -r ~/workspace/third/esp32/esp-idf/examples/wifi/getting_started/station ~/workspace/work/esp32/
cd workspace/work/esp32/station/
3、设置芯片平台并进入配置菜单设置WiFi相关信息
idf.py set-target esp32
idf.py menuconfig
根据自己的ESP32模组选择合适的Flash大小
如果不知道自己的模组的Flash大小,请查看此链接
4、设置你自己的WiFi名称和密码并保存
5、编译并烧写
idf.py build flash monitor
正常编译成功如下图
三、实战
我们打开main/station_example_main.c文件定位到app_main函数
注意此处的app_main是在线程环境中执行,是用户代码的入口(后面会专门写一篇博文介绍esp32的启动过程)
首先调用nvs_flash_init()函数进行nvs flash分区的初始化,此分区用于存储一些K-V对信息;由于WiFi驱动里面有些信息需要存储,故在使用WiFi之前需要先初始化nvs分区;然后我们就看到wifi_init_sta函数
在wifi_init_sta函数先创建了一个FreeRTOS事件组(FreeRTOS事件组一般用于多个线程间同步),然后调用esp_netif_init初始化TCP/IP协议栈,调用esp_netif_create_default_wifi_sta初始化默认的sta接口,然后通过esp_wifi_init接口初始化了WiFi(我们在前一篇博文中介绍过此函数)。
在上一篇中我们讲到WiFi功能框图,每个方框可以认为一个模块(模块内高度聚合,有的模块可能是单个线程,有的可能是多个线程),用户任务(application task)要与event task这个任务做一些同步,所以我们此处使用FreeRTOS event group来实现(什么是FreeRTOS事件组?又是知识点,先自行查资料理解一下,本篇暂不扩展)。
event task使用esp_event_loop_create_default()来初始化,并注册了WIFI_EVENT相关的所有事件和IP_EVENT相关的所有事件,这样当对应的事件发生时,就会调用我们注册的回调,当前我们注册的回调为event_handler;
WIFI_EVENT那肯定是跟WiFi Driver相关的
/** WiFi event declarations */
typedef enum {
WIFI_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
WIFI_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
WIFI_EVENT_STA_START, /**< ESP32 station start */
WIFI_EVENT_STA_STOP, /**< ESP32 station stop */
WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
WIFI_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
WIFI_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, /**< ESP32 station wps overlap in enrollee mode */
WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */
WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
WIFI_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
WIFI_EVENT_FTM_REPORT, /**< Receive report of FTM procedure */
/* Add next events after this only */
WIFI_EVENT_STA_BSS_RSSI_LOW, /**< AP's RSSI crossed configured threshold */
WIFI_EVENT_ACTION_TX_STATUS, /**< Status indication of Action Tx operation */
WIFI_EVENT_ROC_DONE, /**< Remain-on-Channel operation complete */
WIFI_EVENT_STA_BEACON_TIMEOUT, /**< ESP32 station beacon timeout */
WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
} wifi_event_t;
IP_EVENT那肯定是跟TCP/IP协议栈相关的
/** IP event declarations */
typedef enum {
IP_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */
IP_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */
IP_EVENT_AP_STAIPASSIGNED, /*!< soft-AP assign an IP to a connected station */
IP_EVENT_GOT_IP6, /*!< station or ap or ethernet interface v6IP addr is preferred */
IP_EVENT_ETH_GOT_IP, /*!< ethernet got IP from connected AP */
IP_EVENT_ETH_LOST_IP, /*!< ethernet lost IP and the IP is reset to 0 */
IP_EVENT_PPP_GOT_IP, /*!< PPP interface got IP */
IP_EVENT_PPP_LOST_IP, /*!< PPP interface lost IP */
} ip_event_t;
wifi初始化后需要设置wifi模式为WIFI_MODE_STA ,然后我们设置了我们需要连接的WiFi信息(通过wifi_config_t这个结构体),这些都完成后,我们通过esp_wifi_start启动了WiFi功能。(那什么时候WiFi算正常启动呢?请看下面的分析)
xEventGroupWaitBits用于等待事件的发生,此处我们只等待两个事件,一个是WiFi连接成功事件,一个是WiFi连接失败事件,也就是说任务阻塞在此处等待事件的发生。
那初学的小伙伴要问了,谁会触发这些事件呢?
下面进入到本篇最重要的环节,事件回调函数event_handler
调用esp_wifi_start接口后,WiFi驱动开始工作,并通过event_task告知用户WiFi正常启动,此时我们调用了esp_wifi_connect接口去主动连接我们已经配置好WiFi。
注意event_base用于区分不同模块的事件的,如果能够正常连接我们自己配置好的wifi,在调用了esp_wifi_connect接口后就会触发IP_EVENT事件,我们通过IP_EVENT_STA_GOT_IP这个子事件就可以知道是否已经正常联网,在这个子事件中我们通过xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);告知用户线程联网完成。
上图显示的是由于配置的WiFi信息错误为能成功联网
上图是正常连接上WiFi的情况
关于esp_event_group的更多介绍请查看
好了,以上就是ESP32联网的最基本实现。