第五十章 ESP32S3 WiFi 热点实验
本章学习把 ESP32-S3 配置为 AP 模式,即创建连接热点,可使用手机连接该热点。
本章分为如下几个小节:
50.1 硬件设计
50.2 软件设计
50.3 下载验证
50.1 硬件设计
1. 例程功能
本章实验功能简介:当手机连接这个热点时, LCD 显示该连接设备的 MAC 地址,断开时,LCD 显示断开设备的 MAC 地址。
2. 硬件资源
1) LED 灯
LED-IO1
2) XL9555
IIC_INT-IO0(需在 P5 连接 IO0)
IIC_SDA-IO41
IIC_SCL-IO42
3) SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
4) ESP32-S3 内部 WiFi
3. 原理图
本章实验使用的 WiFi 为 ESP32-S3 的片上资源,因此并没有相应的连接原理图。
50.2 软件设计
50.2.1 程序流程图
本实验的程序流程图:

图 50.2.1.1 程序流程图
50.2.2 程序解析
50.2.2.1 本次实验用到库函数说明
(1)创建并配置一个适用于 WiFi AP 模式的网络接口
用于创建并配置一个默认的 WiFi 接入点(AP)模式网络接口。这个函数简化了 WiFi AP 模式的初始化过程,自动设置了许多默认参数。函数无参数,原型如下:
esp_netif_t *esp_netif_create_default_wifi_ap(void);
返回值:
|
返回值 |
类型 |
说明 |
|---|---|---|
|
成功 |
|
指向新创建的网络接口对象的指针 |
|
失败 |
|
如果创建失败则返回 NULL |
表 50.2.2.1 函数esp_netif_create_default_wifi_ap()返回值说明
函数返回值esp_netif_t*说明: esp_netif_t是连接底层网络驱动(如 WiFi、以太网)和上层 TCP/IP 协议栈(LwIP)的桥梁。它的地位可以用下图表示:

它是一个不透明指针(Opaque Pointer),代表一个抽象的网络接口实例。
关键特性:
- 不透明性:不需要知道其内部结构的具体细节,只需通过 ESP-IDF 提供的 API 函数来操作它;
- 抽象代表:每个 esp_netif_t实例代表一个具体的网络接口(如 WiFi STA、WiFi AP、以太网等);
- 操作句柄:它是几乎所有 esp_netif_xxx()API 函数的第一个参数,用于指定要操作哪个网络接口。
总结:简单来说,可以将 esp_netif_t*理解为网络接口的“身份证”。ESP-IDF 提供了各种函数(API),需要出示这张“身份证”(传入 esp_netif_t*参数)来告诉系统想要操作哪个具体的接口。不需要关心里面包含了什么信息,只需知道如何使用它即可。
函数主要作用:
- 创建并配置一个适用于 WiFi AP 模式的网络接口;
- 设置默认的 TCP/IP 栈配置;
- 自动配置 DHCP 服务器;
- 设置默认的 IP 地址(通常为 192.168.4.1)。
创建的默认配置:
|
配置项 |
默认值 |
说明 |
|---|---|---|
|
IP 地址 |
192.168.4.1 |
AP 的默认 IP 地址 |
|
子网掩码 |
255.255.255.0 |
C 类网络的默认掩码 |
|
网关 |
192.168.4.1 |
与 IP 地址相同 |
|
DHCP 服务器 |
启用 |
自动为连接的客户端分配 IP |
表 50.2.2.2 函数esp_netif_create_default_wifi_ap()创建的默认配置说明
使用流程:初始化 NVS -> 创建默认事件循环 -> 初始化网络接口 -> 调用 esp_netif_create_default_wifi_ap() -> 配置 WiFi AP 参数 -> 启动 WiFi AP模式
注意事项:
- 调用时机:应在 WiFi 初始化之前调用此函数;
- 内存管理:创建的接口由 ESP-IDF 内部管理,通常不需要手动释放;
- 默认配置:如果不需特殊配置,使用默认值即可满足大多数应用场景;
- 多接口:如果需要多个 AP 接口,应使用 esp_netif_create()创建自定义接口;
- 错误处理:始终检查返回值,确保接口创建成功。
(2)Wifi事件注册
esp_event_handler_register()函数在上一章做了详细说明,需要说一点本次函数使用如下:
ESP_ERROR_CHECK( esp_event_handler_register(
WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler, NULL) );
函数第二个参数传入的参数为ESP_EVENT_ANY_ID,ESP_EVENT_ANY_ID是一个通配符(Wildcard)。当它作为 event_id参数传递给 esp_event_handler_register()时,意思是:“请为指定事件基(event_base)下的 所有具体事件,注册这个事件处理函数”。参数说明:
- event_base = WIFI_EVENT:监听来自 WiFi 模块 的事件;
- event_id = ESP_EVENT_ANY_ID:不挑剔具体是哪种 WiFi 事件。无论是连接开始、连接成功、连接断开、扫描完成等等,只要是 WiFi 模块产生的事件,我都要监听;
- event_handler = &wifi_event_handler:当上述 任何WiFi 事件发生时,都去调用wifi_event_handler这个函数。
简单来说,ESP_EVENT_ANY_ID就是“我全都要”的意思。它告诉事件系统:“只要是 WIFI_EVENT这家公司(事件基)派来的所有快递(事件),都直接交给 wifi_event_handler这个人(处理函数)签收处理”。
(3)获取对应网络接口句柄
函数用于通过接口的唯一标识键(if_key)获取对应的网络接口句柄(esp_netif_t)。 函数原型如下:
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key);
参数说明:
|
参数名 |
类型 |
方向 |
说明 |
|---|---|---|---|
|
|
|
输入 |
网络接口的唯一标识键字符串 |
表 50.2.2.3 函数esp_netif_get_handle_from_ifkey()参数说明
返回值:
|
返回值 |
类型 |
说明 |
|---|---|---|
|
成功 |
|
指向找到的网络接口对象的指针 |
|
失败 |
|
未找到与提供的 |
表 50.2.2.4 函数esp_netif_get_handle_from_ifkey()返回值说明
主要作用:
- 接口查找:在已创建的网络接口中查找具有指定键名的接口;
- 句柄获取:返回找到的接口的操作句柄;
- 接口访问:提供了一种在不同代码模块中访问同一网络接口的方式。
常用接口键名,系统为默认创建的网络接口预定义了以下键名(本次实验传入WIFI_AP_DEF"):
|
接口键名 (if_key) |
对应的接口类型 |
创建函数 |
|---|---|---|
|
|
默认 WiFi Station 接口 |
|
|
|
默认 WiFi AP 接口 |
|
|
|
默认以太网接口 |
|
表 50.2.2.5 常用接口键名说明
(4)获取指定网络接口的 IP 地址、子网掩码和网关信息
用于获取指定网络接口的 IP 地址、子网掩码和网关信息。这个函数对于查询网络接口的当前 IP 配置状态非常有用。
函数原型:
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info);
参数说明:
|
参数名 |
类型 |
方向 |
说明 |
|---|---|---|---|
|
|
|
输入 |
要查询的网络接口句柄。 本次实验为esp_netif_get_handle_from_ifkey()函数的返回值 |
|
|
|
输出 |
存储获取的 IP 信息的结构体指针 |
表 50.2.2.6 函数esp_netif_get_ip_info()参数说明
返回值:
|
返回值 |
类型 |
说明 |
|---|---|---|
|
|
|
获取成功 |
|
其他错误码 |
|
获取失败 |
表 50.2.2.7 函数esp_netif_get_ip_info()返回值说明
函数作用:
- 提供 IP 配置查询:获取网络接口的 IP 地址、子网掩码和网关信息;
- 支持网络状态监测:通过检查 IP 地址判断网络连接状态;
- 简化信息显示:方便在用户界面或日志中显示网络配置;
- 与其他函数配合:与 IP 设置、接口创建等函数协同工作。
(5)字节序转换函数
inet_ntoa_r是一个用于将 IPv4 地址从二进制格式(网络字节序)转换为点分十进制字符串格式的函数。它是 inet_ntoa的可重入(线程安全)版本。函数原型如下:
char *inet_ntoa_r(struct in_addr addr, char *buf, int buflen);
参数说明:
|
参数名 |
类型 |
方向 |
说明 |
|---|---|---|---|
|
|
|
输入 |
包含要转换的二进制IPv4地址的结构体 |
|
|
|
输出 |
用于存储结果字符串的缓冲区 |
|
|
|
输入 |
缓冲区的大小(字节数) |
表 50.2.2.7 函数inet_ntoa_r()参数说明
返回值:
|
返回值 |
类型 |
说明 |
|---|---|---|
|
成功 |
|
指向结果字符串的指针(与 |
|
失败 |
|
如果缓冲区太小无法容纳结果字符串 |
表 50.2.2.7 函数inet_ntoa_r()返回值说明
主要作用:
- 二进制到字符串转换:将32位网络字节序的IPv4地址转换为点分十进制格式;
- 线程安全:与 inet_ntoa不同,inet_ntoa_r是可重入的,可以在多线程环境中安全使用;
- 内存安全:使用用户提供的缓冲区,避免静态缓冲区带来的安全问题。
(6)其他函数说明参见之前章节说明
50.2.2.2 main函数解析
static const char *TAG = "AP";
#define EXAMPLE_ESP_WIFI_SSID "MyWifi"
#define EXAMPLE_ESP_WIFI_PASS "abc1234567"
#define EXAMPLE_MAX_STA_CONN 5
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
static char lcd_buff[100] = {0};
/**
* @brief WIFI链接糊掉函数
* @param arg:传入网卡控制块
* @param event_base:WIFI事件
* @param event_id:事件ID
* @param event_data:事件数据
* @retval 无
*/
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
/* 设备连接 */
if (event_id == WIFI_EVENT_AP_STACONNECTED)
{
spilcd_fill(0,90,320,240,WHITE);
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
ESP_LOGI(TAG, "station " MACSTR " join, AID=%d",
MAC2STR(event->mac), event->aid);
sprintf(lcd_buff, "MACSTR:"MACSTR,MAC2STR(event->mac));
spilcd_show_string(0, 90, 320, 16, 16, lcd_buff, BLUE);
spilcd_show_string(0, 110, 320, 16, 16, "With device connection", BLUE);
}
/* 设备断开 */
else if (event_id == WIFI_EVENT_AP_STADISCONNECTED)
{
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d",
MAC2STR(event->mac), event->aid);
spilcd_fill(0,90,320,320,WHITE);
sprintf(lcd_buff, "Device disconnected:"MACSTR,MAC2STR(event->mac));
spilcd_show_string(0, 90, 320, 16, 16, lcd_buff, BLUE);
}
}
/**
* @brief WIFI初始化
* @param 无
* @retval 无
*/
static void wifi_init_softap(void)
{
/* 初始化网卡 */
ESP_ERROR_CHECK(esp_netif_init());
/* 创建新的事件循环 */
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* 使用默认配置初始化包括netif的Wi-Fi */
esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
/* 配置WIFI */
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0)
{
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
esp_netif_ip_info_t ip_info;
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info);
char ip_addr[16];
inet_ntoa_r(ip_info.ip.addr, ip_addr, 16);
ESP_LOGI(TAG, "Set up softAP with IP: %s", ip_addr);
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:'%s' password:'%s'",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
spilcd_show_string(0, 90, 240, 16, 16, "wifi connecting......", BLUE);
}
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
esp_err_t ret;
ret = nvs_flash_init(); /* 初始化NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init());
}
led_init(); /* LED初始化 */
my_spi_init(); /* SPI初始化 */
myiic_init(); /* IIC初始化 */
xl9555_init(); /* 初始化按键 */
spilcd_init(); /* LCD屏初始化 */
spilcd_show_string(0, 0, 240, 32, 32, "ESP32-S3", RED);
spilcd_show_string(0, 40, 240, 24, 24, "WiFi AP Test", RED);
spilcd_show_string(0, 70, 240, 16, 16, "ATOM@ALIENTEK", RED);
wifi_init_softap();
while (1)
{
LED0_TOGGLE();
vTaskDelay(pdMS_TO_TICKS(500));
}
}
上述源码相对简单,主要将 ESP32-S3 设备配置为 AP 模式,即作为热点设备。然后,设置热点设备的账号、密码、安全模式等参数。在 WiFi 事件回调函数中,当有外部设备请求连接时,程序会在 LCD 上显示连接设备的 MAC 地址等信息。而当外部设备从连接状态断开时, LCD 会显示当前断开的外部设备 MAC 地址。
50.3 下载验证
程序下载成功后,利用手机连接 ESP32-S3 热点设备(本次实验命名为"MyWifi"),当手机连接热点设备成功时,LCD 显示手机的 MAC 地址等信息,当手机从已连接状态断开时, LCD 显示断开的外部设备的MAC 地址。下图为连接成功的 LCD 显示效果图。

图 50.3.1 外部设备连接热点设备
下图为外部设备从已连接状态断开效果图,如下所示。

图 50.3.2 外部设备断开热点设备
更多推荐


所有评论(0)