對於ESP32,其做爲一款集成了2.4GHz WiFi和藍牙雙模塊的單芯片,全部基於wifi和藍牙開發是學習esp32的重要一環,今天WiFi原理和網絡結構 能夠點擊連接進行詳細的瞭解,這裏就不作詳細的敘述了,本文重點講解省電模式下的WiFi是如何鏈接上路由器的,重點是相關API接口和編程方法的介紹。本文源碼地址在:esp-idf/examples/wifi/power_save裏。源碼完成了對ESP32的低功耗模式的設置,並經過menuconfig將接入點AP的名稱和密碼賦值給ESP32,使ESP32做爲一個站點STA接入到接入點AP(即路由器)中。
html
/*set the ssid and password via "make menuconfig"*/ #define DEFAULT_SSID CONFIG_WIFI_SSID #define DEFAULT_PWD CONFIG_WIFI_PASSWORD #if CONFIG_POWER_SAVE_MODEM #define DEFAULT_PS_MODE WIFI_PS_MODEM #elif CONFIG_POWER_SAVE_NONE #define DEFAULT_PS_MODE WIFI_PS_NONE #else #define DEFAULT_PS_MODE WIFI_PS_NONE #endif /*CONFIG_POWER_SAVE_MODEM*/
這裏首先將AP端的名稱和密碼賦值給ESP32,使ESP32能夠鏈接上接入點AP,這裏的CONFIG_WIFI_SSID和CONFIG_WIFI_PASSWORD即爲路由器端的名稱和密碼,他們在源碼中是看不到的,它們的定義是在Kconfig.projbuild中定義的,咱們能夠經過make menconfig對其進行賦值。具體操做以下:編程
選擇Example Configuration後windows
在WIFI SSID和WIFI Password中分別將路由器的名稱和密碼賦值給ESP32。api
(固然,你也能夠不經過menucofig而對ESP32直接進行賦值)緩存
緊隨其後的即是對ESP32工做模式的設置,一樣,其也能夠經過menuconfig進行設置。服務器
static const char *TAG = "power_save"; static esp_err_t event_handler(void *ctx, system_event_t *event) { switch(event->event_id) { case SYSTEM_EVENT_STA_START: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); ESP_ERROR_CHECK(esp_wifi_connect()); break; case SYSTEM_EVENT_STA_GOT_IP: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); ESP_LOGI(TAG, "got ip:%s\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); break; case SYSTEM_EVENT_STA_DISCONNECTED: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); ESP_ERROR_CHECK(esp_wifi_connect()); break; default: break; } return ESP_OK; }
本部分主要是將ESP32的工做信息,打印出來,對返回的任務通知進行switch分析,若是鏈接上了,就打印sta_start消息,並再次執行esp_err_t esp_wifi_connect
( void )將ESP32 WiFi站鏈接到AP,第二次獲得返回任務通知SYSTEM_EVENT_STA_GOT_IP,並調用 ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));將數字IP地址轉換爲十進制點ASCII表示法。,此時顯示鏈接到的AP的IP和MAC地址。網絡
若是沒有鏈接上AP,一樣會一直執行esp_err_t esp_wifi_connect
( void ),直到將ESP32 WiFi站鏈接到AP爲止。app
/*init wifi as sta and set power save mode*/ static void wifi_power_save(void) { tcpip_adapter_init(); 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)); wifi_config_t wifi_config = { .sta = { .ssid = DEFAULT_SSID, .password = DEFAULT_PWD }, }; 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()); ESP_LOGI(TAG, "esp_wifi_set_ps()."); esp_wifi_set_ps(DEFAULT_PS_MODE); }
wifi_power_save首先調用 tcpip_adapter_init();函數對底層庫的TCP/IP協議進行調用,而後檢測esp_event_loop_init是否初始化完成。socket
以後即是進行wifi的設置,首先用esp_wifi_init(&cfg)對WIFI的內存空間進行設置,初始化WiFi Alloc資源爲WiFi驅動,如WiFi控制結構,RX / TX緩衝區,WiFi NVS結構等,此WiFi也啓動WiFi任務。(注意;在調用全部其餘WiFi API以前,必須先調用此API)tcp
而後設置ESP32 STA或AP的配置。
wifi_config_t wifi_config = { .sta = { .ssid = DEFAULT_SSID, //設置要鏈接的AP的接入點名稱和密碼 .password = DEFAULT_PWD }, };
經過esp_wifi_set_mode(WIFI_MODE_STA)將WiFi操做模式設置爲站,軟AP或站+軟AP,默認模式爲軟AP模式。
esp_wifi_set_config設置ESP32 STA或AP的配置。
最後經過esp_wifi_start()根據當前配置啓動WiFi,
並經過 esp_wifi_set_ps(DEFAULT_PS_MODE);設置當前節電類型。
void app_main() { // Initialize NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK( ret ); wifi_power_save(); }
app_main函數主要是對NVS完成基本的初始化操做(關於NVS,能夠在ESP32彙總中進行詳細瞭解),保證數據的緩存空間,而後調用 wifi_power_save();函數完成WIFI設置。
程序燒寫完成後,打開minicom,能夠看到以下的打印信息
打開windows的cmd(這裏筆記本和ESP32接入的是同一個AP),對AP分配的ESP32的IP進行ping操做,觀察可否PING通。操做結果以下:
至此,基於省電模式的WIFI連接就設計完成了。
一旦ESP32已經設置了站點配置細節,其中包括SSID和password,咱們準備好鏈接到目標訪問點後。 功能 esp_wifi_connect() 將造成的鏈接。你鏈接了後ESP32中的任何內容都不會阻塞,一樣也不會影響到這個功能。
在一段時間之後,當其實際的鏈接起來後,咱們會看到兩個回調事件發生, 首先是 SYSTEM_EVENT_STA_CONNECTED 代表咱們有鏈接到接入點。 第二個事件是 SYSTEM_EVENT_STA_GOT_IP 其表示咱們已經被DHCP服務器分配了一個IP地址。只有這樣咱們才能真正參與通信。若是咱們正在使用靜態IP地址,那麼咱們只會看到鏈接的事件。
咱們從接入點斷開鏈接時,咱們將看到一個SYSTEM_EVENT_STA_DISCONNECTED 事件。從先前鏈接的 斷開接入點咱們調用esp_wifi_disconnect()完成,
關於與接入點鏈接的進一步考慮是自動鏈接的想法。 有一個布爾標誌存儲在閃存中指示ESP32是否應嘗試自動鏈接到最後一個使用的接入點。 若是設置爲true,那麼以後在設備啓動後,你無需調用任何API函數,它將嘗試鏈接到最後使用的接入點。 這是一個
方便選項,可是我更喜歡關閉。 一般我想在個人設備中進行控制來肯定是否自動鏈接,是否自動鏈接,咱們能夠經過調用esp_wifi_set_auto_connect()。
另外,當咱們鏈接到接入點時,咱們的設備正在成爲一個station。 鏈接到接入點AP不是自動的,意味着咱們如今有一個IP地址。 咱們堅持必須從DHCP服務器請求已創建的IP地址。 這可能須要幾秒。在某些狀況下,咱們可讓設備請求特定的IP。 這能夠更快的鏈接時間。 若是咱們指定數據,咱們也須要提供DNS信息,若是咱們須要鏈接到DNS服務器的名字解析度。
這是分配給咱們一個特定IP地址的邏輯片斷: #include <lwip / sockets.h> //咱們但願咱們的設備擁有的IP地址。 #define DEVICE_IP「192.168.1.99」 //咱們但願發送數據包的網關地址 //這一般是咱們的接入點。 的#define DEVICE_GW 「192.168.1 1」 //網絡掩碼規範。 #define DEVICE_NETMASK「255.255.255.0」 //咱們但願鏈接的接入點的身份。 #define AP_TARGET_SSID「RASPI3」 //咱們須要提供給接入點進行受權的密碼。 #define AP_TARGET_PASSWORD「password」 esp_err_t wifiEventHandler(void * ctx,system_event_t * event) { 返回ESP_OK; } //代碼片斷在這裏... nvs_flash_init(); tcpip_adapter_init(); tcpip_adap ter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); tcpip_adapter_ip_info_t ipInfo; inet_pton(AF_INET,DEVICE_IP,&ipInfo.ip); inet_pton(AF_INET,DEVICE_GW,&ipInfo.gw); inet_pton(AF_INET,DEVICE_NETMASK,&ipInfo.netmask); tcpip_ada pter_set_ip_info(TCPIP_ADAPTER_IF_STA,&ipInfo); ESP_ERROR_CHECK(esp_event_loop_init(wifiEventHandler,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_ST ORAGE_RAM)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); wifi_config_t sta_config = { .sta = { .ssid = AP_TARGET_SSID, .password = AP_TARGET_PASSWORD, .bssid_set = 0 } }; ESP_ERROR_CHECK(esp_wifi_set_config(WI FI_IF_STA,&sta_config)); ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_connect());
做爲接入點AP
到目前爲止,咱們只將ESP32做爲了接入接入點的WiFi站
但它也具備做爲一個接入點使其餘WiFi設備(站)鏈接的能力 。爲了成爲一個接入點,咱們須要定義容許其餘的SSID設備來區分咱們的網絡。 這個SSID能夠被標記爲爲hidden, 若是咱們不但願它在掃描中找到。 另外咱們還要提供認證方式當臺站但願與咱們聯繫時,將使用該功能。 這是用來容許
的,實際的將ES32實例做爲接入點AP請看下一篇文章