1. 程式人生 > >讓 ESP32 連線到你的 WiFi 熱點

讓 ESP32 連線到你的 WiFi 熱點

功能說明將 ESP32 當做一個 STA,連線到一個 WiFi 熱點。

關於 ESP32 更多好玩、有趣、實用的專案,請檢視 【ESP32 系列部落格 - 目錄】

【快速開始】

【假設】

  • 你已經安裝好 ESP-IDF 和工具鏈。
  • 你已經有一個 WiFi 熱點。

【步驟】

  • 使用資料線將開發板連線到你的系統中,讓系統能夠識別到你的板子(Windows 是COM\*, Linux 是/dev/ttyUSB\*)。
  • 進入sta所在目錄。
  • 執行命名make menuconfig進行配置。
    • 對熱點的 SSID 和密碼進行配置。依次進入配置選項Demo Configuration --->
      ,然後在WiFi SSIDWiFi Password中填寫你的 SSID 和密碼。然後退出配置選單,儲存配置。
    • 對串列埠進行配置。
  • 執行命令make進行編譯
  • 執行命令make flash monitor將編譯生成的映象燒寫到 ESP32 開發板上面,並檢視串列埠輸出。

【現象】

串列埠輸出如下圖所示,從圖中框出的部分可以看出,我們的 ESP32 已經成功連線到熱點,並獲取到 IP 地址了。

這裡寫圖片描述
圖 - 串列埠輸出

【原始碼分析】

整個原始碼非常簡單,一共就幾十行程式碼,幾乎都是在呼叫 ESP-IDF 給我們提供的介面,整個過程的流程如下:

這裡寫圖片描述

上面這個流程中,我們需要強調的有三處:

  • 初始化事件處理模組 esp_event_loop_init()
  • 設定 wifi 模式 esp_wifi_set_mode()
  • 配置介面的引數 esp_wifi_set_config()

【初始化事件排程器】

在 ESP-IDF 中,整個 wifi 協議棧是一個狀態機,它在各個時刻都有一個狀態。使用者可以根據自己的需要,讓協議棧在某個狀態時自動處理某些工作。在呼叫 esp_event_loop_init()函式時 ,我們傳入了一個引數 event_handler,它是一個函式指標,當wifi狀態機的狀態變化時,會呼叫函式 event_handler(),並給它傳遞適當的引數。這一部分內容我們將在下一篇部落格中詳細介紹,所以這裡就不再說明,請參考

深入分析 ESP32 的 WiFi 狀態機

【設定 wifi 模式】

ESP32 支援三種 wifi 模式,它們被定義為三個列舉值:

typedef enum {
    WIFI_MODE_NULL = 0,  /**< null mode */
    WIFI_MODE_STA,       /**< WiFi station mode */
    WIFI_MODE_AP,        /**< WiFi soft-AP mode */
    WIFI_MODE_APSTA,     /**< WiFi station + soft-AP mode */
    WIFI_MODE_MAX
} wifi_mode_t;

第一個列舉值WIFI_MODE_NULL和最後一個列舉值WIFI_MODE_MAX只是一個標記,不是真正支援的模式,因此支援的模式包括:

  • station 模式
  • soft-AP 模式
  • station + soft-AP 模式

設定模式的介面為 esp_err_t esp_wifi_set_mode(wifi_mode_t mode);,它需要的引數就是我們上面所看到的三種模式中的其中一個。

另外還有一個問題,WIFI_MODE_NULLWIFI_MODE_MAX 有啥作用?在函式 esp_wifi_set_mode 內部,可以通過這兩個值來進行入參檢測,判斷傳入的引數是否有效。

【配置介面的引數】

在上面設定 wifi 模式時,wifi 庫會根據我們傳入的引數來分配介面。如果我們傳入的引數是 WIFI_MODE_STA,則 wifi 庫會建立一個 sta 介面;如果我們傳入的引數是 WIFI_MODE_AP,則 wifi 庫會建立一個 ap 介面;如果我們傳入的引數是 WIFI_MODE_APSTA,則 wif 庫會同時建立一個 sta 介面和一個 ap 介面。wifi 庫在執行時需要知道這些介面的引數,所以我們需要在啟動 wifi 前設定介面的引數。

設定 wifi 介面引數的 API 原型是 esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf);,包含兩個引數:

  • wifi_interface_t ifx,即需要配置的介面
  • wifi_config_t *conf,即傳遞給該介面的引數

sta 介面和 ap 介面需要的引數是不同的,這裡一定要注意,它們通過一個 聯合體 來定義的:

typedef union {
    wifi_ap_config_t  ap;  /**< AP 的配置 */
    wifi_sta_config_t sta; /**< STA 的配置 */
} wifi_config_t;

對於 sta 介面,需要配置的引數一般包括 ssidpassword。注意,這裡的ssidpassword的長度是由限制的,具體請看結構體:

typedef struct {
    uint8_t ssid[32];      /**< SSID of target AP*/
    uint8_t password[64];  /**< password of target AP*/
    bool bssid_set;        /**< whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/
    uint8_t bssid[6];     /**< MAC address of target AP*/
    uint8_t channel;       /**< channel of target AP. Set to 1~13 to scan starting from the specified channel before connecting to AP. If the channel of AP is unknown, set it to 0.*/
} wifi_sta_config_t;

對於 ap 介面,第一個需要確定的引數是 authmode,即客戶端連線到這個 AP 時的授權模式。如果配置的授權模式是 WIFI_AUTH_OPEN,則不再需要配置其它引數。否則,則需要根據授權模式來判斷還需要其它啥引數,不過一般都至少還需要 ssidpassword 兩個引數,其它引數的作用請自行研究。ap 介面的配置結構體如下:

typedef struct {
    uint8_t ssid[32];           /**< SSID of ESP32 soft-AP */
    uint8_t password[64];       /**< Password of ESP32 soft-AP */
    uint8_t ssid_len;           /**< Length of SSID. If softap_config.ssid_len==0, check the SSID until there is a termination character; otherwise, set the SSID length according to softap_config.ssid_len. */
    uint8_t channel;            /**< Channel of ESP32 soft-AP */
    wifi_auth_mode_t authmode;  /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */
    uint8_t ssid_hidden;        /**< Broadcast SSID or not, default 0, broadcast the SSID */
    uint8_t max_connection;     /**< Max number of stations allowed to connect in, default 4, max 4 */
    uint16_t beacon_interval;   /**< Beacon interval, 100 ~ 60000 ms, default 100 ms */
} wifi_ap_config_t;

【總結】

雖然只有短短的幾十行程式碼,但是如果我們仔細追蹤原始碼的話,裡面其實藏著很多幹貨的!

我們這裡也只是簡單分析了下原始碼,沒有太深入,比如,tcp/ip 適配層初始化時都幹了啥?事件排程器是幹嘛的/wifi 狀態機是如何執行是?對於後者,理解清楚了有利於我們編寫出更好的應用程式,我們將在下一篇部落格中介紹,請參考 分析 ESP32 的 WiFi 狀態機;對於前者,如果有興趣,請自行追蹤原始碼,這部分內容也是開源的。