讓 ESP32 連線到你的 WiFi 熱點
功能說明:將 ESP32 當做一個 STA,連線到一個 WiFi 熱點。
關於 ESP32 更多好玩、有趣、實用的專案,請檢視 【ESP32 系列部落格 - 目錄】
【快速開始】
【假設】
- 你已經安裝好 ESP-IDF 和工具鏈。
- 你已經有一個 WiFi 熱點。
【步驟】
- 使用資料線將開發板連線到你的系統中,讓系統能夠識別到你的板子(Windows 是
COM\*
, Linux 是/dev/ttyUSB\*
)。 - 進入
sta
所在目錄。 - 執行命名
make menuconfig
進行配置。
- 對熱點的 SSID 和密碼進行配置。依次進入配置選項
Demo Configuration --->
WiFi SSID
和WiFi Password
中填寫你的 SSID 和密碼。然後退出配置選單,儲存配置。 - 對串列埠進行配置。
- 對熱點的 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()
,並給它傳遞適當的引數。這一部分內容我們將在下一篇部落格中詳細介紹,所以這裡就不再說明,請參考
【設定 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_NULL
和 WIFI_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 介面,需要配置的引數一般包括 ssid
和 password
。注意,這裡的ssid
和password
的長度是由限制的,具體請看結構體:
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
,則不再需要配置其它引數。否則,則需要根據授權模式來判斷還需要其它啥引數,不過一般都至少還需要 ssid
和 password
兩個引數,其它引數的作用請自行研究。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 狀態機;對於前者,如果有興趣,請自行追蹤原始碼,這部分內容也是開源的。