您好,今天欣欣来为大家解答以上的问题。lwip协议相信很多小伙伴还不知道,现在让我们一起来看看吧!

lwip协议(lwip协议栈详解)lwip协议(lwip协议栈详解)


lwip协议(lwip协议栈详解)


lwip协议(lwip协议栈详解)


1、在ESP-IDF下copy出/home/andy/esp/esp-idf/examples/wifi/getting_started/station,此demo连接到路由器。

2、整个demo都是在调用ESP-IDF提供的接口,整个过程如下:1、主程序void app_main(void){//Initialize NVSesp_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_LOGI(TAG, "ESP_WIFI_MODE_STA!!!!");wifi_init_sta();}1234567111213123456780111213在main函数中对nvs进行初始化用于保存路由器信息,然后进入wifi_init_sta();函数连接到路由器2、WiFi连接函数WiFi连接函数大致分为三个阶段:1. Wi-Fi/LwIP 初始化阶段;2. Wi-Fi 配置阶段;3. Wi-Fi 启动阶段具体过程在相关函数后注释了一些,细节还是3、回调函数看看乐鑫文档{s_wifi_nt_group = xEventGroupCreate();//1. Wi-Fi/LwIP 初始化阶段ESP_ERROR_CHECK(esp_netif_init());//初始化LwIP,创建LwIP核心任务并初始化与LwIP相关的工作。

3、printf("sequence1.n");ESP_ERROR_CHECK(esp_nt_loop_create_default());//创建一个系统任务,并初始化应用程序的回调函数esp_netif_create_default_wifi_sta();//创建有 TCP/IP 堆栈的默认网络接口实例绑定 stationprintf("sequence2.n");wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));//创建 Wi-Fi 驱动程序任务,并初始化 Wi-Fi 驱动程序printf("sequence3.n");//创建应用程序任务,应用程序可以在使用进行注册的回调中处理这些esp_nt_handler_register()esp_nt_handler_instance_t instance_any_id;esp_nt_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_nt_handler_instance_register(WIFI_,ESP__ANY_ID,&nt_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_nt_handler_instance_register(IP_,IP__STA_GOT_IP,&nt_handler,NULL,&instance_got_ip));printf("sequence4.n");//2. Wi-Fi 配置阶段wifi_config_t wifi_config = {.sta = {.ssid = EXAMPLE_ESP_WIFI_SSID,.password = EXAMPLE_ESP_WIFI_PASS,/ Setting a password implies station will connect to all security modes including WEP/WPA. Howr these modes are deprecated and not aisable to be used. Incase your Access point doesn't support WPA2, these mode can be enabled by commenting below line /.threshold.authmode = WIFI_AUTH_WPA2_PSK,.pmf_cfg = {.capable = true,.required = false},},};printf("sequence5.n");ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );//设置wifi模式ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );//配置wifi接口的参数ESP_ERROR_CHECK(esp_wifi_start() );//3. Wi-Fi 启动阶段//Wi-Fi 驱动程序将 WIFI__STA_START 发布到任务中,然后,任务将执行一些正常作并调用应用程序的回调函数ESP_LOGI(TAG, "wifi_init_sta finished.");/ Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum number of re-tries (WIFI_FAIL_BIT). The bits are set by nt_handler() (see above) /EventBits_t bits = xEventGroupWaitBits(s_wifi_nt_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/ xEventGroupWaitBits() returns the bits before the call returned, hence we can test which nt actually happened. /if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);} else {ESP_LOGE(TAG, "UNEXPECTED ");}printf("sequence7.n");/ The nt will not be processed after unregister /ESP_ERROR_CHECK(esp_nt_handler_instance_unregister(IP_, IP__STA_GOT_IP, instance_got_ip));ESP_ERROR_CHECK(esp_nt_handler_instance_unregister(WIFI_, ESP__ANY_ID, instance_any_id));vEventGroupDelete(s_wifi_nt_group);printf("sequence8.n");}12345671112131516171819202123242526272829303132333435373839404142图中从左到右为0~31位,共四个字节,从上到下依次增长,IP头部占20字节,剩下的为数据,如果传输层为TCP则还有20字节的TCP头部,如果是UDP则还有8字节(如果分片的话,中间的包没有UDP头部,即0字节)的UDP头部。

4、剩下的才是真正的用户要传送的数据。

5、可以看出传送同样多的数据,UDP协议要比TCP传送的数据多,但从这一点来说UDP速度也要比TCP快。

6、4344454647484950515253555657586061626364656667686970717273751234567801112131516171819202123242526272829303132333435373839404142434445464748495051525355565758606162636465666768697071727375在esp_wifi_start()即WiFi启动后调用esp_nt_handler_instance_register()向WiFi组件注册通知,调用回调函数nt_handler(),WiFi驱动程序将WIFI__STA_START发布到任务;然后,任务将执行一些常规作,并将调用应用程序回调函数。

7、应用程序回调函数将WIFI__STA_START中继到应用程序任务。

8、在idf中,整个WiFi协议栈是一个状态机,在每个时刻都有一个状态,当WiFi状态机的状态变化时就会调用nt_handler()并给它传递适当的参数。

9、static void nt_handler(void arg, esp_nt_base_t nt_base,int32_t nt_id, void nt_data){if (nt_base == WIFI_ && nt_id == WIFI__STA_START) {esp_wifi_connect();//4. Wi-Fi 连接阶段printf("wifi nt start.n");}else if (nt_base == WIFI_ && nt_id == WIFI__STA_DISCONNECTED) {//6. Wi-Fi 断开阶段if (s_retry_num esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");} else {xEventGroupSetBits(s_wifi_nt_group, WIFI_FAIL_BIT);}ESP_LOGI(TAG,"connect to the AP fail");}else if (nt_base == IP_ && nt_id == IP__STA_GOT_IP) {//5. Wi-Fi 获取 IP 阶段ip_nt_got_ip_t nt = (ip_nt_got_ip_t) nt_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&nt->ip_.ip));s_retry_num = 0;xEventGroupSetBits(s_wifi_nt_group, WIFI_CONNECTED_BIT);}else{printf("sequence6.n");}}1234567801112131516171819202123242526272812345678011121315161718192021232425262728三、终端查看连接过程状态当连接失败再次进入回调WIFI__STA_DISCONNECTED中重连5次然后 WIFI_CONNECTED_BIT 或 WIFI_FAIL_BIT 被置位后,打印出信息并删除一些变量,打印出ssid与password注销通知在log中看到ssid与password,进入sdkconfig文件夹中看到默认的SSID与PASSWORD,以及重连的次数为5次现在在idf.py menuconfig中更改下ssid与password以连接到路由器。

10、在example configuration中修改可以连接上的路由器名称与密码修改完WiFi信息后再编译烧录进开发板看到输出信息如下,重连两次get IP成功连上路由器,连接成功后我关闭了路由器也就是断网在打开路由器并没有重连WiFi,这是因为在sta函数将该注销掉了也就不会处理该将注销这三行程序注释掉再尝试断网,打开网络之后能重连上,注意在此demo中只会重连5次,5次之后便连接不上了。

11、在实际项目中应该断连之后应该一直尝试连接。

12、可注释掉这几行当掉线时一直去连接。

本文到这结束,希望上面文章对大家有所帮助。