让 ESP32 连接到你的 WiFi 热点

本工程已托管到 GitHub,具体路径是 https://github.com/tidyjiang8/esp32-projects/tree/master/sta

功能说明将 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 状态机;对于前者,如果有兴趣,请自行追踪源码,这部分内容也是开源的。

你可能感兴趣的:(玩转ESP32)