当前位置: 代码迷 >> 综合 >> ESP32 组件中esp_wifi lwip esp_netif三大组件的作用与区别
  详细解决方案

ESP32 组件中esp_wifi lwip esp_netif三大组件的作用与区别

热度:76   发布时间:2023-09-28 05:26:24.0

1. esp32的esp_wifi(wifi驱动库),esp_netif(网络接口) ,lwip(轻量级TCP/IP网络协议栈)是什么?三者之间有什么关系?

esp_wifi驱动库用户控制wifi硬件单元;

lwip是一层纯软件,轻量级TCP/IP协议栈;

esp_netif是esp官方提供的操作TCP/IP协议栈的API。

 ESP32 组件中esp_wifi lwip esp_netif三大组件的作用与区别

从上面的ESP32功能框图中可以看出wifi是单片机中的一个独立的硬件,实现了通过无线发送数据目的。同理蓝牙,以太网等等都是单片机中一块独立的硬件。所以既然是硬件,我们在使用wifi收发数据前就需要进行初始化配置等操作。

ESP32 组件中esp_wifi lwip esp_netif三大组件的作用与区别

以上是一张ESP32官方文档中描述esp_wifi(wifi驱动库),esp_netif(网络接口) ,lwip(轻量级TCP/IP网络协议栈)之间的操作关系图。

ESP-NETIF是ESP32官方在TCP/IP协议栈之上封装的一层供应用程序访问协议栈的便携的接口,也就是说IP协议栈在这里是不需要被用户应用程序直接访问的。

从(A)开始看,用户应用程序调用esp_netif中的API接口初始化TCP/IP协议栈,之后调用esp_wifi中的API接口初始化wifi硬件,接下来就是数据的收发过程,用户程序发送的数据经过TCP/IP协议栈的处理打包后到达wifi驱动,最后经过物理硬件电磁波发送出去,总的来说就是用户层 -》TCP/IP协议栈-》wifi硬件-》对端。

2. ESP-NETIF interaction解读。文档连接:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/network/esp_netif.html

ESP-NETIF library 有两方面的作用。

(1). 在TCP/IP协议栈之上提供了一个抽象层,允许用户在未来可能的情况下选择使用的IP栈;

(2). 这个抽象层的API是线程安全的,即使底层的TCP/IP协议栈接口不是线程安全的。

目前,ESP-IDF框架只为轻量级的TCP/IP协议栈实现了ESP-NETIF抽象层,然而适配器(指前面说的ESP-NETIF抽象层)本身TCP/IP的实现是不可见的即使不同的是实现也是可能的。

一些ESP-NETIF抽象层的API接口函数可以被应用程序调用,比如获取和设置IP地址,配置DHCP。其他的接口函数被网络驱动层调用(在这里我觉得是wifi驱动层)。

在很多情况下,应用程序不需要调用ESP-NETIF抽象层的API接口,因为他们会被默认的网络事件调用。

ESP-NETIF组件是tcpip适配器的继承者,从IDF v4.1开始废弃了tcpip适配器。请参考 TCP/IP 适配器迁移指南 用ESP-NETIF替代tcpip适配器。

(3). ESP-NETIF interaction

A) User code, boiler plate。

    A.初始化代码

  • 总的来说,使用IO驱动作为通信媒介和配置TCP/IP协议栈的应用程序在使用ESP-NETIF APIs 时是抽象的,看下面描述。
  • 初始化IO驱动。
  • 创建一个新的ESP-NETIF实例,进行配置。
  • 连接IO驱动到ESP-NETIF实例 (这里我的理解是wifi硬件单元通过IO驱动和ESP-NETIF网络接口建立连接)。
  • 配置事件处理函数(处理wifi硬件单元事件和tcp/ip协议栈事件)。

    B.使用ESP-NETIF API的网络接口交互。

  • 获取TCP/IP下相关参数。
  • 接收IP事件(连接/断开)。
  • 控制应用程序的生命周期(设置接口的开和关)。

B) 通讯驱动, IO 驱动, 媒介驱动。

  • 与ESP-NETIF有关的通讯驱动扮演着两种重要角色:以后补充。

C) ESP-NETIF, former tcpip_adapter

  • 以后补充。

D) Network stack

  • 以后补充。

3. ESP32 wifi相关代码解读。

最简单的联网代码

#include "esp_wifi.h"

#include "esp_event.h"

#include "nvs_flash.h"

#include "esp_log.h"

#include "string.h"

static const char* TAG = "test esp_wifi";

static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)

{

    ESP_LOGI(TAG, "----> event_base: %s event_id: %d", event_base, event_id);

    if(event_base == WIFI_EVENT) {

        switch(event_id) {

            case WIFI_EVENT_STA_START:

                ESP_LOGI(TAG, "----> %s", "WIFI_EVENT_STA_START");

                break;

            case WIFI_EVENT_STA_DISCONNECTED:

                ESP_LOGI(TAG, "----> %s", "WIFI_EVENT_STA_DISCONNECTED");

                break;

            default:

                break;

        }

    }else if(event_base == IP_EVENT) {

        ip_event_got_ip_t *event = (ip_event_got_ip_t*)event_data;

        switch(event_id) {

            case IP_EVENT_STA_GOT_IP:

                ESP_LOGI(TAG, "----> IP_EVENT_STA_GOT_IP ip:");

                ESP_LOGI(TAG, "----> sta ip:"IPSTR, IP2STR(&event->ip_info.ip));

                ESP_LOGI(TAG, "----> mask:"IPSTR, IP2STR(&event->ip_info.netmask));

                ESP_LOGI(TAG, "----> gw:"IPSTR, IP2STR(&event->ip_info.gw));

                break;

            default:

                break;

        }

    }else {

        ESP_LOGI(TAG, "----> %s", "unknown event_base");

    }

 

    return;

}

void app_main()

{

    esp_err_t ret = nvs_flash_init();

    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {

        ESP_ERROR_CHECK(nvs_flash_erase());

        ret = nvs_flash_init();

    }

    ESP_ERROR_CHECK(ret);

    esp_event_loop_create_default();

    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);

    esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);

 

    //网络接口初始化

    esp_netif_init();

    esp_netif_create_default_wifi_sta();        

 

    //wifi初始化

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

    esp_wifi_init(&cfg);

    wifi_config_t wifi_config = {

        .sta.ssid = "WX-JGGY",

        .sta.password = "juguogongyudb"

    };

    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);

    esp_wifi_set_mode(WIFI_MODE_STA);

    esp_wifi_start(); //启动wifi

    esp_wifi_connect(); //启动连接到ap

 

    while(1) {

        vTaskDelay(1000 / portTICK_PERIOD_MS);

        printf("hello world\n");

    }

}