在本文中,我们通过样例来分析 ESP8266 连接 Wifi 的过程及需要用都的 API。
该程序在 SDK 中 examples/wifi/getting_started/station 目录中。项目包含一个 C 语言的源文件 - hello_world_main.c(位于 main 目录中), 其它的文件是 Make 构建系统需要的配置文件。
主程序解析
打开 station_example_main.c 文件,入口函数 app_main 位于文件末尾,代码如下:
1 | void app_main() |
首先,调用了系统 API: nvs_flash_init , 用来初始化默认的 “nvs” 分区。
然后就调用自定义的 wifi_init_sta 来启动 Wifi 连接。
启动 Wifi
首先看函数 wifi_init_sta 的实现代码:
1 | void wifi_init_sta(void) |
可以看到,程序首先通过 xEventGroupCreate 构建了一个事件组,该 API 是 RTOS 系统 API 的一个。
接下来,程序调用了 tcpip_adapter_init,构建 TCPIP 栈。
然后调用 esp_event_loop_create_default 构建默认的消息(事件)队列。
接着,初始化 Wifi 设备驱动,其实是为运行 Wifi 准备相关的数据结构,存储空间,该调用所涉及到的参数比较多,因此建议使用预定义的宏,代码:
1 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); |
接下来的两行代码注册事件(消息)处理行数,
1 | ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); |
这里我们注册了连个类型的事件: WIFI_EVENT - Wifi 相关事件 和 IP_EVENT - ip 相关事件,这两类事件又包含多个具体的事件,这就由第二个参数来标识: ESP_EVENT_ANY_ID - 表示接收类别下所有的事件,对于 WIFI_EVENT 来说就可以是: WIFI_EVENT_STA_START, WIFI_EVENT_STA_DISCONNECTED 等, IP_EVENT_STA_GOT_IP - 表示接收获得IP的事件。
再下面的代码是设定所要连接的AP的SSID和密码(该值可以通过 make menuconfig 进行设置),并设置 Wifi 工作模式,然后启动。
1 | wifi_config_t wifi_config = { |
ESP_ERROR_CHECK(esp_wifi_start() ); 这行代码启动 Wifi, 事件处理程序中的代码是异步执行的
因为这是一个演示程序,所以执行完成以后需要停止Wifi的连接,并打印是否连接上网络。
下面,执行一个租塞语句,要等待异步执行的事件处理结果,代码:
1 | EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, |
该预计在 s_wifi_event_group 中等待 WIFI_CONNECTED_BIT 或 WIFI_FAIL_BIT 标致。
后续的代码就是打印联网结果及清理现场了。
事件处理
在函数 wifi_init_sta 中,注册了两个事件处理,都使用同样的事件处理函数:
1 | static void event_handler(void* arg, esp_event_base_t event_base, |
可以看到,当 WIFI_EVENT_STA_START 事件触发时,调用API: esp_wifi_connect 建立连接
当 WIFI_EVENT_STA_DISCONNECTED 事件触发时,如果重连次数小于设定的最多重连次数,则调用 esp_wifi_connect 重建连接,否则设置调用 xEventGroupSetBits,触发主线程中调用 xEventGroupWaitBits 的返回。
同样,如果发生 IP_EVENT_STA_GOT_IP 事件,则获取 IP 地址。