:讓芯片“上網(wǎng)“)
ESP32-S3 自帶 Wi-Fi。本章講清楚①Wi-Fi 協(xié)議棧在芯片里的分層LwIP/TCP-IP/事件②STA連接路由器模式的完整流程與事件驅(qū)動(dòng)模型③與前面章節(jié)的整合思路如通過手機(jī)控制電機(jī)④常見問題。目標(biāo)不是讓你成為網(wǎng)絡(luò)專家而是能寫出第一個(gè)能上網(wǎng)的程序。16.1 芯片里的網(wǎng)絡(luò)分層先建立地圖一個(gè)網(wǎng)絡(luò)請(qǐng)求從應(yīng)用到天線經(jīng)過多層。ESP-IDF 幫你把下面這些層都封裝好了你的應(yīng)用HTTP 請(qǐng)求 / MQTT 消息 │ LwIPTCP/IP 協(xié)議棧TCP/UDP/IP 分包 │ esp_netif網(wǎng)絡(luò)接口抽象WiFi/以太網(wǎng) │ esp_wifiWiFi 驅(qū)動(dòng)連接路由器、收發(fā)無線幀 │ 射頻硬件天線你主要打交道的是事件esp_eventWiFi 連上/斷開、拿到 IP 地址系統(tǒng)都會(huì)發(fā)出事件你注冊(cè)回調(diào)處理即可?!居布疤帷縀SP32-S3 只有 2.4GHz 的無線電。S3 的 Wi-Fi 只支持2.4GHz802.11 b/g/n不支持 5GHz。如果家里路由器是僅 5GHz的網(wǎng)絡(luò)或 2.4G 頻段被關(guān)掉/隱藏了 SSID芯片掃遍信道也找不到它癥狀就是日志里反復(fù)出現(xiàn)W (2311) wifi_sta: 斷開原因碼 201201 NO_AP_FOUND“沒看到這個(gè) AP”。遇到 201 先懷疑頻段和 SSID不要懷疑板子壞了到路由器后臺(tái)打開 2.4GHz 頻段或單獨(dú)給 2.4G 起一個(gè) SSID 名或者干脆用手機(jī)熱點(diǎn)開 2.4GHz 模式來測(cè)——這是本章所有示例的第一道關(guān)卡?!救齻€(gè)詞先說人話】SSID路由器報(bào)家門的名字一個(gè)字符串標(biāo)簽區(qū)分大小寫IP設(shè)備在局域網(wǎng)里的門牌號(hào)別人要找你就報(bào)這個(gè)號(hào)IPv4 就是四段數(shù)字如 192.168.1.105DHCP路由器自動(dòng)發(fā)門牌號(hào)的流程——設(shè)備喊一聲給我一個(gè)號(hào)路由器回一個(gè)空閑 IP順帶給出網(wǎng)關(guān)和 DNS。串成一句話憑 SSID 找到路由器 → 對(duì)暗號(hào)密碼→ DHCP 領(lǐng)到 IP → 這才算上網(wǎng)。注意領(lǐng)到 IP只代表你和路由器之間這條鏈路通了不代表外網(wǎng)可達(dá)DNS、網(wǎng)關(guān)、運(yùn)營(yíng)商都可能出問題見 16.6 的對(duì)應(yīng)行。16.2 STA 模式連接家里的路由器流程先看全局① nvs_flash_initWiFi 驅(qū)動(dòng)要用 NVS 存射頻校準(zhǔn)數(shù)據(jù)。注意只是校準(zhǔn)數(shù)據(jù) SSID/密碼默認(rèn)并不存在 NVS 里要應(yīng)用自己持久化見 16.6 的說明 ② esp_netif_init esp_event_loop_create_default網(wǎng)絡(luò)與事件系統(tǒng) ③ esp_netif_create_default_wifi_sta創(chuàng)建 STA 網(wǎng)絡(luò)接口 ④ esp_wifi_init初始化 WiFi 驅(qū)動(dòng) ⑤ 注冊(cè)事件回調(diào)WIFI_EVENT_STA_*、IP_EVENT_STA_GOT_IP ⑥ esp_wifi_set_mode(WIFI_MODE_STA) ⑦ esp_wifi_set_config(配置 SSID/密碼) ⑧ esp_wifi_start → 驅(qū)動(dòng)開始掃描連接 ⑨ 收到 IP_EVENT_STA_GOT_IP → 局域網(wǎng)這條路通了能不能出外網(wǎng)還要看 DNS/網(wǎng)關(guān)見 16.6完整示例事件驅(qū)動(dòng)寫法可直接抄進(jìn)工程下面是一份完整的main/main.cpp新建工程、把它替換進(jìn)去、改兩個(gè)宏再按后面的 CMakeLists 配好就能編譯燒錄對(duì)照第 3 章的工程骨架。這一版比最小骨架多了三樣?xùn)|西全都是踩坑修正include 列表補(bǔ)全原骨架缺esp_log.h和 FreeRTOS 頭文件編譯不過SSID/密碼用編譯期長(zhǎng)度校驗(yàn)寫入不再用strcpy往固定數(shù)組里硬塞斷線重連不在事件回調(diào)里睡 3 秒那是全書反復(fù)禁止的做法而是回調(diào)只投隊(duì)列、由專門的任務(wù)做指數(shù)退避重連。// main/main.cpp —— ESP32-S3 Wi-Fi STA 連接示例v6.0.1 實(shí)測(cè)口徑#includestring.h#includeesp_event.h#includeesp_log.h#includeesp_netif.h#includeesp_wifi.h#includeesp_wifi_default.h// esp_netif_create_default_wifi_sta() 的聲明在這里#includefreertos/FreeRTOS.h#includefreertos/queue.h#includefreertos/task.h#includenvs_flash.hstaticconstchar*TAGwifi_sta;// ------- 改這兩行就能連你家路由器 -------#defineWIFI_SSID你的路由器名#defineWIFI_PASS你的密碼// 編譯期長(zhǎng)度校驗(yàn)。wifi_config_t 里 ssid 是 uint8_t[32]、password 是 uint8_t[64]// 見 esp_wifi_types_generic.h不寫校驗(yàn)、直接 strcpy 進(jìn)去一旦超長(zhǎng)就是// 越界寫內(nèi)存——程序當(dāng)場(chǎng)不崩之后在莫名其妙的地方崩最難查的那種。// sizeof 宏字符串時(shí)把結(jié)尾 \0 也算 1 字節(jié)所以 SSID 實(shí)際最長(zhǎng) 31 字符、// 密碼最長(zhǎng) 63 字符超了直接在編譯期報(bào)錯(cuò)根本到不了運(yùn)行。// sizeof 里的 ((wifi_config_t *)nullptr)-sta.ssid 只求類型尺寸、不求值// 不會(huì)真的解引用空指針這是 C/C 老手也常用的取成員尺寸寫法。static_assert(sizeof(WIFI_SSID)sizeof(((wifi_config_t*)nullptr)-sta.ssid),SSID 太長(zhǎng)加上結(jié)尾零字節(jié)最多 32 字節(jié));static_assert(sizeof(WIFI_PASS)sizeof(((wifi_config_t*)nullptr)-sta.password),密碼太長(zhǎng)加上結(jié)尾零字節(jié)最多 64 字節(jié));// 回調(diào)和重連任務(wù)之間用隊(duì)列傳消息——第 13 章的老朋友typedefenum{WIFI_EVT_DISCONNECTED,// 斷線了該重連WIFI_EVT_GOT_IP,// 連上了退避計(jì)時(shí)清零}wifi_evt_t;staticQueueHandle_t s_evt_queueNULL;staticvoidon_wifi_event(void*arg,esp_event_base_t base,int32_tid,void*data){if(baseWIFI_EVENTidWIFI_EVENT_STA_START){esp_wifi_connect();// 驅(qū)動(dòng)就緒發(fā)起第一次連接}elseif(baseWIFI_EVENTidWIFI_EVENT_STA_CONNECTED){ESP_LOGI(TAG,已連上路由器等待 IP);}elseif(baseWIFI_EVENTidWIFI_EVENT_STA_DISCONNECTED){wifi_event_sta_disconnected_t*e(wifi_event_sta_disconnected_t*)data;// 原因碼很有診斷價(jià)值esp_wifi_types_generic.h// 201WIFI_REASON_NO_AP_FOUNDSSID 錯(cuò)/信號(hào)不到、// 202WIFI_REASON_AUTH_FAIL多半密碼錯(cuò)、203關(guān)聯(lián)失敗ESP_LOGW(TAG,斷開原因碼 %d,e-reason);// 鐵律回調(diào)里絕不 vTaskDelay默認(rèn)事件循環(huán)只有一個(gè)任務(wù)// 你在這里睡 3 秒全系統(tǒng)所有事件都停 3 秒——和第 13/15 章// 回調(diào)要快、重活交給任務(wù)的原則直接沖突。// 這里只做一件事往隊(duì)列投一條消息超時(shí)給 0不等待。wifi_evt_t evtWIFI_EVT_DISCONNECTED;xQueueSend(s_evt_queue,evt,0);}}staticvoidon_ip_event(void*arg,esp_event_base_t base,int32_tid,void*data){if(baseIP_EVENTidIP_EVENT_STA_GOT_IP){ip_event_got_ip_t*e(ip_event_got_ip_t*)data;ESP_LOGI(TAG,拿到 IP: IPSTR,IP2STR(e-ip_info.ip));wifi_evt_t evtWIFI_EVT_GOT_IP;xQueueSend(s_evt_queue,evt,0);// 通知重連任務(wù)鏈路已恢復(fù)// 到這里局域網(wǎng)這條路通了能不能出外網(wǎng)還要看 DNS/網(wǎng)關(guān)16.6}}// 專門的重連任務(wù)睡在這里不阻塞任何人staticvoidwifi_manager_task(void*arg){TickType_t backoffpdMS_TO_TICKS(1000);// 初始退避 1 秒constTickType_t kMaxBackoffpdMS_TO_TICKS(60000);// 封頂 60 秒wifi_evt_t evt;while(true){// 一直等消息來一條處理一條第 13 章的阻塞收隊(duì)xQueueReceive(s_evt_queue,evt,portMAX_DELAY);if(evtWIFI_EVT_GOT_IP){backoffpdMS_TO_TICKS(1000);// 連上了退避歸零下次從頭算continue;}ESP_LOGW(TAG,%u ms 后嘗試重連,(unsigned)(backoff*portTICK_PERIOD_MS));vTaskDelay(backoff);// 睡在任務(wù)里事件循環(huán)毫無壓力esp_wifi_connect();// 指數(shù)退避1s → 2s → 4s → … 最多 60s避免路由器長(zhǎng)時(shí)間掛掉時(shí)// 設(shè)備 1 秒一次地猛 reconnect費(fèi)電、刷屏、還可能擠占掃描backoff(backoff*2kMaxBackoff)?kMaxBackoff:backoff*2;}}externCvoidapp_main(void){ESP_ERROR_CHECK(nvs_flash_init());// ① NVSESP_ERROR_CHECK(esp_netif_init());// ② 網(wǎng)絡(luò)ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();// ③ 接口// 隊(duì)列和重連任務(wù)要在 esp_wifi_start() 之前就緒// 否則啟動(dòng)瞬間的斷線事件來了卻沒人接s_evt_queuexQueueCreate(8,sizeof(wifi_evt_t));xTaskCreate(wifi_manager_task,wifi_mgr,4096,NULL,5,NULL);wifi_init_config_t icWIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(ic));// ④ 驅(qū)動(dòng)// ⑤ 事件回調(diào)ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,on_wifi_event,NULL));ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT,IP_EVENT_STA_GOT_IP,on_ip_event,NULL));wifi_config_t cfg{};// 先清零兩個(gè)數(shù)組的剩余字節(jié)全為 0memcpy(cfg.sta.ssid,WIFI_SSID,sizeof(WIFI_SSID));// 長(zhǎng)度已由memcpy(cfg.sta.password,WIFI_PASS,sizeof(WIFI_PASS));// static_assert 把關(guān)ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));// ⑥ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA,cfg));// ⑦ESP_ERROR_CHECK(esp_wifi_start());// ⑧// 之后一切靠事件驅(qū)動(dòng) 重連任務(wù)app_main 可以結(jié)束}配套main/CMakeLists.txt少了任何一項(xiàng)都鏈接不過idf_component_register( SRCS main.cpp INCLUDE_DIRS . REQUIRES nvs_flash esp_wifi esp_netif esp_event )esp_log.h和freertos/*不用寫進(jìn) REQUIRESv6 里log、freertos屬于公共依賴每個(gè)組件自動(dòng)獲得這和第 3 章說driver已拆分不矛盾——被拆掉的只是外設(shè)驅(qū)動(dòng)事件循環(huán)、Wi-Fi、NVS 這些仍要顯式 REQUIRES。抄完第一件事替換那兩個(gè)中文占位符#define WIFI_SSID 你的路由器名和#define WIFI_PASS 你的密碼里的中文只是占位符必須整對(duì)引號(hào)換成真值四個(gè)細(xì)節(jié)最容易翻車SSID區(qū)分大小寫Home和home在空口上是兩個(gè)不同的網(wǎng)絡(luò)肉眼難分的字符別抄錯(cuò)0零≠O、1一≠l小寫 L、B≠8引號(hào)內(nèi)結(jié)尾不要留空格MyWiFi 和MyWiFi也是兩個(gè)網(wǎng)絡(luò)中文 SSID 能連但編碼坑多下面另有一小節(jié)測(cè)試期先起個(gè)英文名最省事。改完必須重新idf.py build——宏是編譯期展開進(jìn)二進(jìn)制的不重編等于沒改?!緞?dòng)手框】① 在哪執(zhí)行新建一個(gè)空工程第 3 章骨架或idf.py create-project wifi_sta上面的示例存成main/main.cpp、main/CMakeLists.txt換成上面那份在IDF 終端里cd到工程根目錄含CMakeLists.txt的那層。② 敲什么idf.py set-target esp32s3 idf.py build idf.py-pCOM3 flash monitor③ 預(yù)期看到編譯末尾文件名跟著你project(...)里起的工程名走這個(gè)示例代碼沒幾行bin 卻有 754KB0xb82d0——Wi-Fi 協(xié)議棧本身就是這么大一塊對(duì)照第 5 章 l298n 工程的 172KB 就能感受到 16.5 說的那句WiFi 很吃內(nèi)存/體積wifi_sta_demo.bin binary size 0xb82d0 bytes. Smallest app partition is 0x100000 bytes. 0x47d30 bytes (28%) free. Project build complete. To flash, run: idf.py flash燒錄末尾Hash of data verified串口輸出見下面跑起來應(yīng)該看到什么。④ 沒看到a) 編譯報(bào)esp_netif_create_default_wifi_sta was not declared→ 去本節(jié)頭文件迷宮那張表b) 報(bào)端口占用 /PermissionError(13)→ 關(guān)掉另一個(gè)監(jiān)視器或串口助手2.6 那張表的對(duì)應(yīng)行c) 反復(fù)原因碼 201→ 回到 16.1 末尾的2.4GHz 硬件前提框。跑起來應(yīng)該看到什么下面是這一路走下來該看到的片段每行的格式都按 v6.0.1 本地源碼/預(yù)編譯庫(kù)里的日志語句核對(duì)過毫秒數(shù)、MAC、任務(wù)句柄、信道、RSSI、IP 會(huì)因環(huán)境不同而不同要對(duì)的是行的內(nèi)容和先后順序驅(qū)動(dòng)起來 → 握手 → 已連上路由器 → 拿到 IPI (749) main_task: Calling app_main() ← 進(jìn)入你的 app_main第 2 章 2.9 nvs_flash_init 成功時(shí)不打日志 靜默通過就是正常 I (1021) wifi:wifi driver task: 3fceca64, prio:23, stack:6656, core0 ← ④ esp_wifi_init I (1035) wifi:mode : sta (68:ee:xx:xx:xx:xx) ← ⑥ 模式 STA括號(hào)里是本機(jī) MAC I (2312) wifi:new:6,0, old:1,0, ap:255,255, sta:6,0, prof:1, snd_ch_cfg:0x0 I (2313) wifi:state: init - auth (0xb0) ← 802.11 三步握手開始對(duì)暗號(hào) I (2320) wifi:state: auth - assoc (0x0) I (2331) wifi:state: assoc - run (0x10) I (2335) wifi:connected with myhome, aid 4, channel 6, BW20, bssid cc:bb:xx:xx:xx:xx I (2336) wifi:security: WPA2-PSK, phy: bgn, rssi: -53, cipher(pairwise:0x3, group:0x3), pmf:0 I (2340) wifi_sta: 已連上路由器等待 IP ← 我們的回調(diào)CONNECTED 事件 I (3012) esp_netif_handlers: sta ip: 192.168.1.105, mask: 255.255.255.0, gw: 192.168.1.1 I (3012) wifi_sta: 拿到 IP: 192.168.1.105 ← GOT_IPDHCP 領(lǐng)到門牌號(hào)帶wifi_sta的兩行是我們自己的ESP_LOGITAG 來自代碼帶wifi:的是驅(qū)動(dòng)打的TAG 就叫wifi別以為是自己的日志讀個(gè)關(guān)鍵詞就行state: init - auth - assoc - run走通、并出現(xiàn)connected with 你的 SSID就說明 SSID 找對(duì)了、密碼也對(duì)密碼錯(cuò)會(huì)停在 auth 前并報(bào)原因碼 202/203最后一行之后程序就沒事了本示例只做連接監(jiān)視器還在滾按Ctrl]退出監(jiān)視器2.8 第 4 步的老規(guī)矩退出后才能再次燒錄。想驗(yàn)證網(wǎng)絡(luò)真的能用把esp_wifi_start()之后的邏輯換成 16.3 說的 HTTP 請(qǐng)求或者先到路由器管理頁看這臺(tái)設(shè)備有沒有出現(xiàn)在客戶端列表里。頭文件迷宮esp_netif_defaults.h ≠ esp_wifi_default.h上例最容易抄錯(cuò)的是那兩個(gè)長(zhǎng)得像雙胞胎的頭文件這里一次講清v6.0.1 本地源碼核實(shí)頭文件住在哪個(gè)組件里面有什么esp_netif_defaults.h注意復(fù)數(shù)esp_netif只有一堆默認(rèn)配置宏/結(jié)構(gòu)體如ESP_NETIF_DEFAULT_WIFI_STA()沒有esp_netif_create_default_wifi_sta()這個(gè)函數(shù)esp_wifi_default.h單數(shù)esp_wifiesp_netif_create_default_wifi_sta()/esp_netif_create_default_wifi_ap()的真正聲明在這里而且esp_wifi.h內(nèi)部已經(jīng)#include esp_wifi_default.h所以只寫esp_wifi.h其實(shí)也能編過——但我們建議顯式寫上esp_wifi_default.h你用了哪個(gè)函數(shù)就 include 哪個(gè)頭別依賴搭便車將來重構(gòu)時(shí)不會(huì)一臉茫然。網(wǎng)上不少教程/舊代碼把函數(shù)聲明記到esp_netif_defaults.h頭上報(bào)“was not declared in this scope” 時(shí)先來這里對(duì)答案。中文 SSID 小提醒SSID 支持中文但它只是一坨字節(jié)路由器用 UTF-8 還是 GBK 編碼各家不一一個(gè)漢字 UTF-8 占 3 字節(jié)、GBK 占 2 字節(jié)。設(shè)備掃到亂碼SSID 而連不上時(shí)先懷疑編碼不是硬件壞了家里路由器起個(gè)英文名能省去 90% 的麻煩。上面抄完第一件事那段講的是占位符替換的坑大小寫、0/O、結(jié)尾空格這里講的是路由器那邊 SSID 本身是中文時(shí)的坑。兩回事別混。事件驅(qū)動(dòng)模型的本質(zhì)不是程序順序等到連上而是注冊(cè)回調(diào) → 系統(tǒng)在事件發(fā)生時(shí)調(diào)用你。這就是嵌入式/網(wǎng)絡(luò)的通用模型不要等等會(huì)來叫你。和第 15 章ISR 通知任務(wù)是同一個(gè)思想。16.3 拿到了 IP 之后能干什么三個(gè)方向先把這節(jié)出現(xiàn)的四個(gè)縮寫說清各一句話夠用HTTP瀏覽器/客戶端和服務(wù)器一問一答的請(qǐng)求協(xié)議GET /api/speed?value60就是它TCP/UDP更底層的兩條管道——TCP 保證順序和送達(dá)打電話UDP 只管扔出去廣播喊話WebSocket把 HTTP 的一問一答升級(jí)成一條長(zhǎng)期雙向的管道服務(wù)器能主動(dòng)推消息給設(shè)備MQTT物聯(lián)網(wǎng)專用的訂閱頻道協(xié)議——設(shè)備往motor/cmd這個(gè)主題發(fā)消息訂閱了它的誰都收得到協(xié)議頭比 HTTP 小得多很適合帶寬差的設(shè)備。三個(gè)方向HTTP 客戶端esp_http_client內(nèi)置組件向服務(wù)器發(fā)請(qǐng)求TCP/UDP直接和上位機(jī)/手機(jī) App 通信自定義協(xié)議HTTP 服務(wù)器 / WebSocket設(shè)備自己當(dāng)服務(wù)器手機(jī)瀏覽器訪問。例把電機(jī)項(xiàng)目升級(jí)成手機(jī)遙控小車手機(jī) → HTTP/WebSocket → ESP32 → 解析指令 → motor.setSpeed(…)。網(wǎng)絡(luò)任務(wù)收指令和電機(jī)任務(wù)執(zhí)行之間用隊(duì)列通信第 13 章。16.4 配網(wǎng)設(shè)備第一次怎么知道密碼真實(shí)產(chǎn)品不能讓用戶改代碼。常見方案先補(bǔ)兩個(gè)詞APAccess Point熱點(diǎn)是別人來連我的那個(gè)角色SoftAP就是用芯片的軟件做出一個(gè) AP相對(duì)硬件 AP而言也就是讓開發(fā)板自己變成一個(gè) Wi-Fi 熱點(diǎn)。STA 和 AP 兩種角色 S3 可以同時(shí)擔(dān)任。方案做法SmartConfig樂鑫方案手機(jī) App 用 UDP 廣播 SSID/密碼設(shè)備監(jiān)聽捕獲SoftAP 配網(wǎng)設(shè)備自己開熱點(diǎn)上面的 SoftAP手機(jī)連上后填密碼提交BLE 配網(wǎng)手機(jī)通過藍(lán)牙把配置發(fā)給設(shè)備S3 支持預(yù)置出廠預(yù)燒一個(gè)默認(rèn) WiFi 配置入門先做預(yù)置 代碼里改密碼能跑通后再學(xué) SmartConfig。16.5 資源與注意WiFi 使用 NVS 存儲(chǔ)射頻校準(zhǔn)數(shù)據(jù)必須先nvs_flash_init否則啟動(dòng)報(bào)錯(cuò)再?gòu)?qiáng)調(diào)一遍NVS 里存的是校準(zhǔn)數(shù)據(jù)不是你寫的 SSID/密碼WiFi 會(huì)占用較多內(nèi)存約 200KB大內(nèi)存應(yīng)用注意和 PSRAM 配合天線/射頻天線區(qū)域不要被金屬遮擋天線下方盡量留空看門狗WiFi 連接是異步的不要在 app_main 里死等斷線重連回調(diào)里只投消息重連在專門任務(wù)里做指數(shù)退避——16.2 的完整示例就是這么寫的別在事件回調(diào)里 vTaskDelay。16.6 常見問題速查現(xiàn)象原因解決nvs_flash_init失敗NVS 分區(qū)沒建/損壞檢查分區(qū)表、擦除 Flash日志反復(fù)斷開原因碼 201NO_AP_FOUND怎么都掃不到網(wǎng)絡(luò)路由器只有 5GHz、SSID 隱藏、或 SSID 名字抄錯(cuò)大小寫/0 與 O/結(jié)尾空格先看 16.1 末尾的2.4GHz 硬件前提框開 2.4G 頻段或用手機(jī)熱點(diǎn) 2.4G 模式測(cè)再核對(duì)WIFI_SSID的真值連不上路由器SSID/密碼錯(cuò)原因碼 202 多是密碼錯(cuò)、信道問題核對(duì)配置、看 WIFI_EVENT 日志里的原因碼拿到 IP 但請(qǐng)求失敗DNS/網(wǎng)關(guān)問題DNS把域名翻譯成 IP 的電話簿路由器沒給好或外網(wǎng)不通都會(huì)栽在這用 IP 直連測(cè)試檢查路由器重啟后又要填 WiFi 密碼以為esp_wifi 默認(rèn)把配置存 NVS 了誤會(huì)esp_wifi 存進(jìn) NVS 的只有射頻校準(zhǔn)數(shù)據(jù)SSID/密碼存在 RAM 里的wifi_config_t斷電即忘。想不丟就自己持久化把憑據(jù)寫進(jìn) NVS第 14 章 nvs_handle 的用法開機(jī)讀出來再esp_wifi_set_config啟動(dòng)很慢掃描信道固定信道可加速16.7 想一想 小測(cè)驗(yàn)想一想為什么esp_wifi_start()之后 app_main 可以結(jié)束事件驅(qū)動(dòng)設(shè)備連上路由器后靠什么確認(rèn)網(wǎng)絡(luò)真的可用手機(jī)遙控小車的消息流里隊(duì)列放在哪一層小測(cè)驗(yàn)WiFi 初始化前必須先初始化哪個(gè)存儲(chǔ)A. PSRAM B. NVS C. SRAM拿到 IP 的事件是A. WIFI_EVENT_STA_START B. IP_EVENT_STA_GOT_IP C. WIFI_EVENT_AP_START斷線重連的正確姿勢(shì)是A. 死等 B. 定時(shí)重連/退避 C. 重啟事件驅(qū)動(dòng)模型的本質(zhì)是什么16.8 本章總結(jié)分層應(yīng)用 → LwIP → esp_netif → esp_wifi → 射頻硬件前提S3 只有 2.4GHz路由器不給開 2.4G 就永遠(yuǎn)掃不到原因碼 201STA 流程N(yùn)VS → netif → 事件 → 模式 → 配置 → start → 等 GOT_IP事件驅(qū)動(dòng)注冊(cè)回調(diào)別死等拿到 IP 后可用 HTTP/TCP/MQTT可把電機(jī)升級(jí)成遙控小車配網(wǎng)方案SmartConfig / SoftAP / BLE產(chǎn)品級(jí)必配。下一章把工程做大——組件化與工程進(jìn)階。