ESP32-P4 无线连接实战指南 —— 基于 ESP-Hosted 与 esp_wifi_remote 模块

ESP32-P4 无线连接实战指南 —— 基于 ESP-Hosted 与 esp_wifi_remote 模块

在物联网应用中,ESP32 系列芯片以其高性能和丰富功能备受青睐。对于 ESP32-P4 来说,由于本身不集成 Wi-Fi 模块,需要借助外部模块实现无线连接,因此如何选择适合的无线连接方案成为关键。本文将对比 ESP-AT、ESP-Hosted 和 ESP-Extconn 三种解决方案,并详细介绍为何在此项目中选择 ESP-Hosted 方案,同时展示如何使用 esp_wifi_remote 模块实现 Wi-Fi 扫描和连接。

wifi scan

概述

ESP32-P4 不具备内置 Wi-Fi 模块,必须借助外部无线模块实现无线连接。虽然市面上有 ESP-AT、ESP-Hosted 和 ESP-Extconn 三种解决方案,但本教程选择了 ESP-Hosted 方案。ESP-Hosted 方案在硬件和软件层面上具有更好的灵活性,而 esp_wifi_remote 模块对 ESP-Hosted API 进行了封装,使开发者能够更便捷地实现无线连接与管理。本文将从依赖安装、配置、代码实现等方面为大家呈现完整的解决方案。

ESP-AT、ESP-Hosted 和 ESP-Extconn 解决方案的的对比分析参考: https://developer.espressif.com/blog/wireless-connectivity-solutions-for-esp32-p4/。


环境准备与依赖安装

使用 ESP-IDF 开发环境时,我们首先需要安装 esp_wifi_remote 模块的依赖,具体命令如下:

idf.py add-dependency "espressif/esp_wifi_remote^0.8.0"

执行该命令后,系统会自动生成 idf_component.yml 文件,并在编译过程中自动下载相应依赖。安装成功的信息如下所示:

Executing action: add-dependency
NOTICE: Created "C:\Users\cheungxiongwei\esp32_cppforger\wifi\main\idf_component.yml"
NOTICE: Successfully added dependency "espressif/esp_wifi_remote": "^0.8.0" to component "main"
NOTICE: If you want to make additional changes to the manifest file at path C:/Users/cheungxiongwei/esp32_cppforger/wifi/main/idf_component.yml manually, please refer to the documentation: https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/manifest_file.html

这一步骤确保了我们在后续开发中可以直接调用 esp_wifi_remote 封装的 API,从而更高效地实现无线连接功能。

sdkconfig Wi-Fi Remote 配置

WiFi Remote

输出示例

,boot:0x30f (SPI_FAST_FLASH_BOOT)
SPI mode:DIO, clock div:1
load:0x4ff33ce0,len:0x162c
load:0x4ff2abd0,len:0xd70
load:0x4f�ESP-ROM:esp32p4-eco1-20240205
Build:Feb  5 2024
rst:0x1 (POWERON),boot:0x30f (SPI_FAST_FLASH_BOOT)
SPI mode:DIO, clock div:1
load:0x4ff33ce0,len:0x162c
load:0x4ff2abd0,len:0xd70
load:0x4ff2cbd0,len:0x32fc
entry 0x4ff2abda
I (25) boot: ESP-IDF v5.4-446-g5c75a994da 2nd stage bootloader
I (26) boot: compile time Mar 11 2025 15:56:37
I (26) boot: Multicore bootloader
I (28) boot: chip revision: v0.1
I (30) boot: efuse block revision: v0.0
I (33) boot.esp32p4: SPI Speed      : 80MHz
I (37) boot.esp32p4: SPI Mode       : DIO
I (41) boot.esp32p4: SPI Flash Size : 16MB
I (45) boot: Enabling RNG early entropy source...
I (49) boot: Partition Table:
I (52) boot: ## Label            Usage          Type ST Offset   Length
I (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (71) boot:  2 factory          factory app      00 00 00010000 00100000
I (79) boot: End of partition table
I (81) esp_image: segment 0: paddr=00010020 vaddr=40070020 size=24cc0h (150720) map
I (115) esp_image: segment 1: paddr=00034ce8 vaddr=30100000 size=0002ch (    44) load
I (116) esp_image: segment 2: paddr=00034d1c vaddr=3010002c size=0003ch (    60) load
I (120) esp_image: segment 3: paddr=00034d60 vaddr=4ff00000 size=0b2b8h ( 45752) load
I (136) esp_image: segment 4: paddr=00040020 vaddr=40000020 size=60328h (394024) map
I (203) esp_image: segment 5: paddr=000a0350 vaddr=4ff0b2b8 size=05820h ( 22560) load
I (209) esp_image: segment 6: paddr=000a5b78 vaddr=4ff10b00 size=02754h ( 10068) load
I (216) boot: Loaded app from partition at offset 0x10000
I (216) boot: Disabling RNG early entropy source...
I (228) hex_psram: vendor id    : 0x0d (AP)
I (229) hex_psram: Latency      : 0x01 (Fixed)
I (229) hex_psram: DriveStr.    : 0x00 (25 Ohm)
I (230) hex_psram: dev id       : 0x03 (generation 4)
I (234) hex_psram: density      : 0x07 (256 Mbit)
I (239) hex_psram: good-die     : 0x06 (Pass)
I (243) hex_psram: SRF          : 0x02 (Slow Refresh)
I (248) hex_psram: BurstType    : 0x00 ( Wrap)
I (252) hex_psram: BurstLen     : 0x03 (2048 Byte)
I (256) hex_psram: BitMode      : 0x01 (X16 Mode)
I (261) hex_psram: Readlatency  : 0x02 (10 cycles@Fixed)
I (266) hex_psram: DriveStrength: 0x00 (1/1)
I (270) esp_psram: Found 32MB PSRAM device
I (274) esp_psram: Speed: 20MHz
I (277) hex_psram: psram CS IO is dedicated
I (280) cpu_start: Multicore app
I (4078) esp_psram: SPI SRAM memory test OK
I (4088) cpu_start: Pro cpu start user code
I (4088) cpu_start: cpu freq: 360000000 Hz
I (4088) app_init: Application information:
I (4088) app_init: Project name:     wifi
I (4092) app_init: App version:      6d97d21-dirty
I (4097) app_init: Compile time:     Mar 11 2025 15:56:23
I (4102) app_init: ELF file SHA256:  83abc4c98...
I (4106) app_init: ESP-IDF:          v5.4-446-g5c75a994da
I (4111) efuse_init: Min chip rev:     v0.1
I (4115) efuse_init: Max chip rev:     v1.99
I (4119) efuse_init: Chip rev:         v0.1
I (4123) heap_init: Initializing. RAM available for dynamic allocation:
I (4130) heap_init: At 4FF158B0 len 00025710 (149 KiB): RAM
I (4135) heap_init: At 4FF3AFC0 len 00004BF0 (18 KiB): RAM
I (4140) heap_init: At 4FF40000 len 00060000 (384 KiB): RAM
I (4146) heap_init: At 50108080 len 00007F80 (31 KiB): RTCRAM
I (4151) heap_init: At 30100068 len 00001F98 (7 KiB): TCM
I (4156) esp_psram: Adding pool of 32768K of PSRAM memory to heap allocator
I (4163) spi_flash: detected chip: generic
I (4166) spi_flash: flash io: dio
I (4170) host_init: ESP Hosted : Host chip_ip[18]
I (4206) H_API: ESP-Hosted starting. Hosted_Tasks: prio:23, stack: 5120 RPC_task_stack: 5120
sdio_mempool_create free:33735284 min-free:33735284 lfb-def:33030144 lfb-8bit:33030144

I (4211) gpio: GPIO[18]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (4219) gpio: GPIO[19]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (4228) gpio: GPIO[14]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (4236) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (4245) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (4253) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4262) H_API: ** add_esp_wifi_remote_channels **
I (4266) transport: Add ESP-Hosted channel IF[1]: S[0] Tx[0x4000db74] Rx[0x4001d38e]
--- 0x4000db74: transport_drv_sta_tx at C:/Users/cheungxiongwei/esp32_cppforger/wifi/managed_components/espressif__esp_hosted/host/drivers/transport/transport_drv.c:209
0x4001d38e: esp_wifi_remote_channel_rx at C:/Users/cheungxiongwei/esp32_cppforger/wifi/managed_components/espressif__esp_wifi_remote/esp_wifi_remote_net.c:19

I (4273) transport: Add ESP-Hosted channel IF[2]: S[0] Tx[0x4000dabc] Rx[0x4001d38e]
--- 0x4000dabc: transport_drv_ap_tx at C:/Users/cheungxiongwei/esp32_cppforger/wifi/managed_components/espressif__esp_hosted/host/drivers/transport/transport_drv.c:239
0x4001d38e: esp_wifi_remote_channel_rx at C:/Users/cheungxiongwei/esp32_cppforger/wifi/managed_components/espressif__esp_wifi_remote/esp_wifi_remote_net.c:19

I (4282) main_task: Started on CPU0
I (4292) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (4292) main_task: Calling app_main()
I (4302) transport: Attempt connection with slave: retry[0]
I (4302) transport: Reset slave using GPIO[54]
I (4302) os_wrapper_esp: GPIO [54] configured
I (4312) gpio: GPIO[54]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (5482) sdio_wrapper: SDIO master: Data-Lines: 4-bit Freq(KHz)[40000 KHz]
I (5482) sdio_wrapper: GPIOs: CLK[18] CMD[19] D0[14] D1[15] D2[16] D3[17] Slave_Reset[54]
I (5482) sdio_wrapper: Queues: Tx[20] Rx[20] SDIO-Rx-Mode[1]
I (5482) H_SDIO_DRV: Starting SDIO process rx task
I (5522) gpio: GPIO[15]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (5522) gpio: GPIO[17]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
Name:
Type: SDIO
Speed: 40.00 MHz (limit: 40.00 MHz)
Size: 0MB
CSD: ver=1, sector_size=0, capacity=0 read_bl_len=0
SCR: sd_spec=0, bus_width=0
TUPLE: DEVICE, size: 3: D9 01 FF
TUPLE: MANFID, size: 4
  MANF: 0092, CARD: 6666
TUPLE: FUNCID, size: 2: 0C 00
TUPLE: FUNCE, size: 4: 00 00 02 32
TUPLE: CONFIG, size: 5: 01 01 00 02 07 
TUPLE: CFTABLE_ENTRY, size: 8
  INDX: C1, Intface: 1, Default: 1, Conf-Entry-Num: 1
  IF: 41
  FS: 30, misc: 0, mem_space: 1, irq: 1, io_space: 0, timing: 0, power: 0
  IR: 30, mask: 1,   IRQ: FF FF
  LEN: FFFF
TUPLE: END
I (5572) sdio_wrapper: Function 0 Blocksize: 512
I (5582) sdio_wrapper: Function 1 Blocksize: 512
I (5582) H_SDIO_DRV: SDIO Host operating in STREAMING MODE
I (5582) H_SDIO_DRV: generate slave intr
I (5592) transport: Received INIT event from ESP32 peripheral
I (5592) transport: EVENT: 12
I (5602) transport: EVENT: 11
I (5602) transport: capabilities: 0xd
I (5602) transport: Features supported are:
I (5612) transport:      * WLAN
I (5612) transport:        - HCI over SDIO
I (5612) transport:        - BLE only
I (5622) transport: EVENT: 13
I (5622) transport: ESP board type is : 13

I (5622) transport: Base transport is set-up

I (5632) transport: Slave chip Id[12]
I (5632) hci_stub_drv: Host BT Support: Disabled
I (5632) H_SDIO_DRV: Received INIT event
I (6662) main_task: Returned from app_main()
I (6672) Wi-Fi Event: event WIFI_EVENT 41
I (6692) H_API: esp_wifi_remote_connect
I (9432) Wi-Fi Event: event WIFI_EVENT 41
I (10442) Wi-Fi Event: WiFi 断开,尝试重新连接...
I (10442) H_API: esp_wifi_remote_connect
I (12862) Wi-Fi Event: WiFi 断开,尝试重新连接...
I (12862) H_API: esp_wifi_remote_connect
I (15632) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x4002ff10
--- 0x4002ff10: wifi_sta_receive at C:/Users/cheungxiongwei/esp/v5.4/esp-idf/components/esp_wifi/src/wifi_netif.c:38

I (15632) Wi-Fi Event: event WIFI_EVENT 4
I (16712) esp_netif_handlers: sta ip: 192.168.4.207, mask: 255.255.255.0, gw: 192.168.4.1
I (16712) Wi-Fi Event: 获得 IP: 192.168.4.207
I (16712) rpc_req: Scan start Req

I (19122) Wi-Fi Event: 热点列表:
I (19152) Wi-Fi Event: 扫描到 36 个 Wi-Fi 热点:
I (19152) Wi-Fi Event: -------------------------------------------------------------
I (19152) Wi-Fi Event: | SSID                             | RSSI | Channel |       MAC Address |
I (19162) Wi-Fi Event: -------------------------------------------------------------
I (19162) Wi-Fi Event: | Abcc_Office_MR                   |  -30 dBm |   6 (2.4GHz) | E2:69:94:1A:98:9F |
I (19172) Wi-Fi Event: | DIRECT-46-HP M233 LaserJet R&D   |  -36 dBm |   6 (2.4GHz) | 62:E9:AA:30:82:46 |
I (19182) Wi-Fi Event: | Abcc_Office_R&D                  |  -40 dBm |  11 (2.4GHz) | C2:E2:2B:5C:63:37 |
I (19192) Wi-Fi Event: | ChinaNet-gsTl                    |  -48 dBm |  11 (2.4GHz) | 0A:A1:4A:CB:59:CB |
I (19202) Wi-Fi Event: | zhiyi                            |  -58 dBm |  11 (2.4GHz) | 78:CF:2F:DB:BC:71 |
I (19212) Wi-Fi Event: | AlogAPP                          |  -59 dBm |   1 (2.4GHz) | D4:DA:21:C8:BD:69 |
I (19222) Wi-Fi Event: | TP-LINK_2.4G                     |  -61 dBm |   6 (2.4GHz) | 04:F9:F8:C7:53:7C |
I (19232) Wi-Fi Event: | ZHIYI                            |  -62 dBm |   1 (2.4GHz) | 7A:3A:20:02:32:10 |
I (19242) Wi-Fi Event: | gc                               |  -63 dBm |  13 (2.4GHz) | 9C:3A:9A:09:4B:5A |
I (19252) Wi-Fi Event: | PDA                              |  -63 dBm |  13 (2.4GHz) | 9C:3A:9A:01:4B:5A |
I (19262) Wi-Fi Event: | Tenda_7769D0-2.4G                |  -63 dBm |  11 (2.4GHz) | CC:2D:21:77:69:D4 |
I (19272) Wi-Fi Event: | Abcc_Office_CEO                  |  -64 dBm |   6 (2.4GHz) | 22:88:CC:0C:FA:8F |
I (19282) Wi-Fi Event: | JHDLCM                           |  -70 dBm |   1 (2.4GHz) | DC:FE:18:B4:66:00 |
I (19292) Wi-Fi Event: | midea_ca_0049                    |  -72 dBm |   1 (2.4GHz) | FC:DF:00:4C:E7:1C |
I (19292) Wi-Fi Event: | Abcc_Network_2.4G                |  -72 dBm |   1 (2.4GHz) | 62:62:91:06:FA:8F |
I (19302) Wi-Fi Event: | itron                            |  -73 dBm |  10 (2.4GHz) | B8:3A:08:AA:5F:31 |
I (19312) Wi-Fi Event: | DIRECT-0e-HP M254 LaserJet       |  -74 dBm |   6 (2.4GHz) | F2:A6:54:90:7C:0E |
I (19322) Wi-Fi Event: | Abcc_Office_ET                   |  -74 dBm |   6 (2.4GHz) | 22:47:3E:0B:FA:8F |
I (19332) Wi-Fi Event: | DIRECT-44-HP M203 LaserJet       |  -75 dBm |   6 (2.4GHz) | AA:93:4A:24:3B:44 |
I (19342) Wi-Fi Event: | uniqscan-market                  |  -76 dBm |   6 (2.4GHz) | 4C:10:D5:8F:00:3B |
I (19352) Wi-Fi Event: | 15Pro                            |  -77 dBm |  11 (2.4GHz) | 40:45:DA:93:70:8A |
I (19362) Wi-Fi Event: | DIRECT-a0-HP M227f LaserJet      |  -77 dBm |   6 (2.4GHz) | B2:52:16:A1:04:A0 |
I (19372) Wi-Fi Event: | HUAWEI-8888                      |  -78 dBm |   1 (2.4GHz) | 00:BE:3B:E0:C1:70 |
I (19382) Wi-Fi Event: | DIRECT-63-HP M15 LaserJet        |  -78 dBm |   6 (2.4GHz) | 86:2A:FD:02:65:63 |
I (19392) Wi-Fi Event: | Xiaomi_itron                     |  -78 dBm |   2 (2.4GHz) | C8:BF:4C:42:3B:A1 |
I (19402) Wi-Fi Event: | HUAWEI-99999                     |  -78 dBm |  11 (2.4GHz) | 62:09:F9:F0:5D:92 |
I (19412) Wi-Fi Event: | TEST-2.4G                        |  -80 dBm |   4 (2.4GHz) | 44:DF:65:9F:B0:92 |
I (19422) Wi-Fi Event: | ChinaNet-Gizs                    |  -81 dBm |  13 (2.4GHz) | 78:91:E9:C6:92:01 |
I (19422) Wi-Fi Event: | hkls                             |  -82 dBm |   6 (2.4GHz) | 44:F9:71:84:21:FA |
I (19432) Wi-Fi Event: | EPROLO-DYJ                       |  -83 dBm |  11 (2.4GHz) | 64:6E:97:9F:E0:43 |
I (19442) Wi-Fi Event: -------------------------------------------------------------

完整代码

接下来,我们通过一段完整代码来演示如何实现 Wi-Fi 的基本功能:扫描热点并连接 Wi-Fi 网络。以下代码中,我们重点关注以下功能点:

  • 初始化 NVS 与网络接口:确保系统能够正常存储数据和管理网络连接。
  • 事件处理函数:处理 Wi-Fi 启动、获得 IP、断开连接、扫描完成等事件,并根据事件类型采取相应的操作。
  • Wi-Fi 扫描与打印:调用 esp_wifi_remote_scan_start() 函数启动 Wi-Fi 扫描,并对扫描到的热点按信号强度排序及去重后打印详细信息。
  • 自动重连机制:在 Wi-Fi 断开时自动调用 esp_wifi_remote_connect() 函数进行重连,保证网络稳定性。

CMakeLists.txt

idf_component_register(SRCS "main.cpp"
                    PRIV_REQUIRES spi_flash esp_wifi esp_wifi_remote nvs_flash
                    INCLUDE_DIRS "")

main.cpp

#ifdef __cplusplus
extern "C"
{
#endif

#include "esp_log.h"
#include "esp_wifi_remote.h"
#include "nvs_flash.h"

#ifdef __cplusplus
}
#endif

// std
#include <algorithm>
#include <string>
#include <unordered_set>
#include <vector>


#define WIFI_SSID "Abcc_Office_R&D"
#define WIFI_PASS "abccabcc521"

static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_remote_connect();
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
        ESP_LOGI("Wi-Fi Event", "获得 IP: " IPSTR, IP2STR(&event->ip_info.ip));

        wifi_scan_config_t scan_config = {.ssid = NULL,         // NULL 表示扫描所有 SSID
                                          .bssid = NULL,        // NULL 表示扫描所有 AP
                                          .channel = 0,         // 0 表示扫描所有信道
                                          .show_hidden = false, // 避免显示隐藏 SSID
                                          .scan_type = WIFI_SCAN_TYPE_ACTIVE};

        ESP_ERROR_CHECK(esp_wifi_remote_scan_start(&scan_config, false));
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        ESP_LOGI("Wi-Fi Event", "WiFi 断开,尝试重新连接...");
        esp_wifi_remote_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE)
    {
        ESP_LOGI("Wi-Fi Event", "热点列表:");
        uint16_t ap_count = 0;
        std::vector<wifi_ap_record_t> ap_info;

        // 获取扫描结果数量
        if (esp_wifi_scan_get_ap_num(&ap_count) != ESP_OK)
        {
            ESP_LOGE("Wi-Fi Event", "获取 AP 数量失败");
            return;
        }

        // 限制最大获取数量,避免内存不足
        if (ap_count > 64)
        {
            ap_count = 64;
        }
        ap_info.resize(ap_count);

        // 获取 Wi-Fi 热点信息
        if (esp_wifi_scan_get_ap_records(&ap_count, ap_info.data()) != ESP_OK)
        {
            ESP_LOGE("Wi-Fi Event", "获取 AP 记录失败");
            return;
        }

        // 释放缓存
        ESP_ERROR_CHECK(esp_wifi_clear_ap_list());

        ESP_LOGI("Wi-Fi Event", "扫描到 %d 个 Wi-Fi 热点:", ap_count);

        // **按信号强度 RSSI 降序排序**
        std::sort(ap_info.begin(), ap_info.end(),
                  [](const wifi_ap_record_t& a, const wifi_ap_record_t& b)
                  {
                      return a.rssi > b.rssi; // RSSI 越大信号越强
                  });

        // **去重 SSID**
        std::unordered_set<std::string> seen_ssids;
        std::vector<wifi_ap_record_t> unique_ap_info;

        for (const auto& info : ap_info)
        {
            std::string ssid_str(reinterpret_cast<const char*>(info.ssid)); // 转换为 std::string
            if (!ssid_str.empty() && seen_ssids.find(ssid_str) == seen_ssids.end())
            {
                seen_ssids.emplace(ssid_str);
                unique_ap_info.emplace_back(info);
            }
        }

        // **遍历并打印 Wi-Fi 热点信息**

        ESP_LOGI("Wi-Fi Event", "-------------------------------------------------------------");
        ESP_LOGI("Wi-Fi Event", "| %-32s | %4s | %7s | %17s |", "SSID", "RSSI", "Channel", "MAC Address");
        ESP_LOGI("Wi-Fi Event", "-------------------------------------------------------------");

        for (const auto& info : unique_ap_info)
        {
            const char* band = (info.primary <= 14) ? "2.4GHz" : "5GHz";
            ESP_LOGI("Wi-Fi Event", "| %-32s | %4d dBm | %3d (%s) | %02X:%02X:%02X:%02X:%02X:%02X |", info.ssid,
                     info.rssi, info.primary, band, info.bssid[0], info.bssid[1], info.bssid[2], info.bssid[3],
                     info.bssid[4], info.bssid[5]);
        }

        ESP_LOGI("Wi-Fi Event", "-------------------------------------------------------------");
    }
    else
    {
        ESP_LOGI("Wi-Fi Event", "event %s %ld", event_base, event_id);
    }
}

void wifi_init_sta()
{
    // Initialize NVS
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_remote_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(
        esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));

    wifi_config_t wifi_config = {
        .sta =
            {
                .ssid = WIFI_SSID,
                .password = WIFI_PASS,
            },
    };

    ESP_ERROR_CHECK(esp_wifi_remote_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_remote_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_remote_start());
}

/*
- **事件驱动机制**  
  通过注册事件处理器,我们能够在 Wi-Fi 启动、连接、断开和扫描完成等状态时,自动调用相应函数,实现自动连接与扫描功能。这种事件驱动机制极大地简化了状态管理,提高了系统稳定性。

- **Wi-Fi 扫描与排序**  
  在获得 IP 后,系统会主动启动扫描功能,并对扫描到的热点列表按 RSSI 信号强度进行降序排序,再通过哈希去重避免重复 SSID 的干扰,从而清晰展示热点信息。

- **自动重连功能**  
  当 Wi-Fi 连接断开时,系统会自动重新尝试连接目标网络,确保网络连接的持续性和可靠性。
*/

// WiFi api 参考 https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
extern "C" void app_main(void) { 
    wifi_init_sta(); 
}

总结

本文详细介绍了如何在 ESP32-P4 平台上基于 ESP-Hosted 方案实现 Wi-Fi 无线连接。通过安装 esp_wifi_remote 模块依赖、配置网络初始化、编写事件驱动代码以及处理 Wi-Fi 扫描与连接逻辑,开发者可以快速构建出稳定高效的无线通信应用。希望这篇指南能为您在物联网项目中提供有价值的参考和帮助!


在后续开发中,您可以根据实际需求对代码进行扩展,比如增加更多的异常处理机制、支持更多无线连接配置选项等。如果您有任何疑问或建议,欢迎在评论区留言讨论。Happy coding!

### ESP32 P4 定时器使用配置 对于ESP32中的P4定时器,实际上ESP32内部集成了两个通用硬件定时器组,每组包含两个通用定时器。这些定时器可以被用来实现精确的时间控制功能[^3]。 #### 配置环境准备 为了能够顺利操作ESP32的定时器,在开发环境中需要安装相应的库文件和支持包。确保已经正确设置了Arduino IDE或其他IDE来支持ESP32平台,并加载了必要的驱动程序和工具链版本[^4]。 #### 初始化定时器 下面是一个简单的例子展示如何初始化并启动一个基于乐鑫官方SDK的单次触发模式下的定时器: ```cpp #include "driver/timer.h" #include "esp_log.h" #define TIMER_DIVIDER 16 // Hardware timer clock divider #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // to seconds unit #define TEST_WITH_RELOAD 0 /* testing will be done with auto reload */ #if(TEST_WITH_RELOAD == 0) #define TEST_ALARM_VALUE (40000000/TIMER_DIVIDER) // no autoreload: alarm after 2 sec #else #define TEST_ALARM_VALUE (20000000/TIMER_DIVIDER) // with autoreload: alarm every 1 sec #endif #define TEST_TIMER_GROUP TIMER_GROUP_0 // we'll use Timer Group 0 #define TEST_TIMER TIMER_0 // and its Timer 0 static void IRAM_ATTR onTimer() { static int count = 0; printf("Intrrupt %d\n", ++count); } void setup_timer() { /* Select and initialize Basic Parameters of the timer */ timer_config_t config; config.divider = TIMER_DIVIDER; config.counter_dir = TIMER_COUNT_UP; config.counter_en = TIMER_PAUSE; config.alarm_en = TIMER_ALARM_EN; config.intr_type = TIMER_INTR_LEVEL; /* Initialize timer with above settings, then install ISR handler for timer group */ timer_init(TEST_TIMER_GROUP, TEST_TIMER, &config); /* Start timer counter from zero value */ timer_set_counter_value(TEST_TIMER_GROUP, TEST_TIMER, 0x00000000ULL); /* Set a one-shot or periodic alarm according to test type selection */ if (TEST_WITH_RELOAD){ timer_set_alarm_value(TEST_TIMER_GROUP, TEST_TIMER, TEST_ALARM_VALUE); timer_enable_intr(TEST_TIMER_GROUP, TEST_TIMER); timer_isr_register(TEST_TIMER_GROUP, TEST_TIMER, onTimer, NULL, 0 , NULL); }else{ timer_set_alarm_value(TEST_TIMER_GROUP, TEST_TIMER, TEST_ALARM_VALUE); timer_enable_intr(TEST_TIMER_GROUP, TEST_TIMER); timer_isr_register(TEST_TIMER_GROUP, TEST_TIMER, onTimer, NULL, 0 , NULL); } /* Start timer counting */ timer_start(TEST_TIMER_GROUP, TEST_TIMER); } ``` 此代码片段展示了如何设置一个计数方向向上、具有中断处理机制以及设定报警阈值的一次性或周期性的定时任务。注意这里选择了`TIMER_GROUP_0`作为工作对象,并指定了具体的定时单元为`TIMER_0`[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cheungxiongwei.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值