一、概述

Wi-Fi 库支持配置及监控 ESP32 Wi-Fi 连网功能。

支持配置:

  • 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 ESP32 连接到接入点 (AP)。

  • AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 ESP32。

  • AP-STA 共存模式(ESP32 既是接入点,同时又作为基站连接到另外一个接入点)。

  • 上述模式的各种安全模式(WPA、WPA2 及 WEP 等)。

  • 扫描接入点(包括主动扫描及被动扫描)。

  • 使用混杂模式监控 IEEE802.11 Wi-Fi 数据包。

ESP-IDF 编程指南——Wi-Fi

二、API说明

以下 WIFI 接口位于 esp_wifi/include/esp_wifi.h

2.1 esp_wifi_init

2.2 esp_wifi_set_mode

2.3 esp_wifi_get_mode

2.4 esp_wifi_start

2.5 esp_wifi_connect

2.6 esp_wifi_disconnect

2.7 esp_wifi_scan_start

2.8 esp_wifi_get_mac

2.9 esp_wifi_set_config

2.10 esp_wifi_get_config

三、AP模式

3.1 一般场景

3.2 Wi-Fi/LwIP初始阶段

如上图中 1.1\1.2\1.3\1.4 所示,分别

  • 初始化LwIP
    创建LwIP核心任务并初始化与LwIP相关的工作。
ESP_ERROR_CHECK(esp_netif_init());
  • 初始化Wi-Fi事件处理
    Wi-Fi事件处理基于esp_event库。Wi-Fi驱动程序会将事件发送到默认事件循环。应用程序可以在使用进行注册的回调中处理这些事件esp_event_handler_register()。esp_netif组件还处理Wi-Fi事件,以提供一组默认行为。例如,当Wi-Fi站连接到AP时,esp_netif将自动启动DHCP客户端(默认情况下)。
// 创建系统事件任务并初始化应用程序事件的回调函数。
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 创建具有TCP / IP堆栈的默认网络接口实例绑定AP。
esp_netif_create_default_wifi_ap();ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));
  • 初始化Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

3.3 Wi-Fi配置阶段

wifi_config_t wifi_config = {.ap = {.ssid = EXAMPLE_ESP_WIFI_SSID,.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.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));

3.4 Wi-Fi启动阶段

ESP_ERROR_CHECK(esp_wifi_start());

3.5 Wi-Fi连接阶段

当有终端接入或断开连接时,产生 WIFI_EVENT_AP_STACONNECTEDWIFI_EVENT_AP_STADISCONNECTED 事件。

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) {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);} 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);}
}

3.6 完整代码

/*  WiFi softAP ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"#include "lwip/err.h"
#include "lwip/sys.h"/* The examples use WiFi configuration that you can set via project configuration menu.If you'd rather not, just change the below entries to strings withthe config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID      CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL   CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN       CONFIG_ESP_MAX_STA_CONNstatic const char *TAG = "wifi softAP";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) {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);} 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);}
}void wifi_init_softap(void)
{ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());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_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));wifi_config_t wifi_config = {.ap = {.ssid = EXAMPLE_ESP_WIFI_SSID,.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.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_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}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_AP");wifi_init_softap();
}

四、STA模式

4.1 一般场景

4.2 Wi-Fi/LwIP初始阶段

如上图中 1.1\1.2\1.3\1.4 所示,分别

  • 初始化LwIP
    创建LwIP核心任务并初始化与LwIP相关的工作。
ESP_ERROR_CHECK(esp_netif_init());
  • 初始化Wi-Fi事件处理
    Wi-Fi事件处理基于esp_event库。Wi-Fi驱动程序会将事件发送到默认事件循环。应用程序可以在使用进行注册的回调中处理这些事件esp_event_handler_register()。esp_netif组件还处理Wi-Fi事件,以提供一组默认行为。例如,当Wi-Fi站连接到AP时,esp_netif将自动启动DHCP客户端(默认情况下)。
// 创建系统事件任务并初始化应用程序事件的回调函数。
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 创建具有TCP / IP堆栈的默认网络接口实例绑定基站。
esp_netif_create_default_wifi_sta();esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,instance_got_ip));
  • 初始化Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

4.3 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.* However these modes are deprecated and not advisable 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},},};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );

4.4 Wi-Fi启动阶段

调用esp_wifi_start()以启动Wi-Fi驱动程序。

Wi-Fi驱动程序将WIFI_EVENT_STA_START发布到事件任务;然后,事件任务将执行一些常规操作,并将调用应用程序事件回调函数。

应用程序事件回调函数将WIFI_EVENT_STA_START中继到应用程序任务。此时调用esp_wifi_connect()

ESP_ERROR_CHECK(esp_wifi_start());

4.5 Wi-Fi连接阶段

一旦esp_wifi_connect()被调用,Wi-Fi驱动程序将开始内部扫描/连接过程。

如果内部扫描/连接过程成功,将生成WIFI_EVENT_STA_CONNECTED。在事件任务中,它将启动DHCP客户端,该客户端最终将触发DHCP进程。

由于例如密码错误,找不到AP等原因,Wi-Fi连接可能会失败。在这种情况下,会出现WIFI_EVENT_STA_DISCONNECTED并提供这种失败的原因。

static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");} else {xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);}ESP_LOGI(TAG,"connect to the AP fail");} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));s_retry_num = 0;xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);}
}

4.6 Wi-Fi“Got IP”阶段

初始化DHCP客户端后,将开始IP阶段。如果从DHCP服务器成功接收到IP地址,则将出现IP_EVENT_STA_GOT_IP,并且事件任务将执行常规处理。

在应用程序事件回调中,IP_EVENT_STA_GOT_IP被中继到应用程序任务。对于基于LwIP的应用程序,此事件非常特殊,这意味着该应用程序已准备就绪,可以开始其任务,例如创建TCP / UDP套接字等。一个非常常见的错误是在收到IP_EVENT_STA_GOT_IP之前初始化套接字。接收IP之前,请勿开始与套接字相关的工作。

五、扫描

当前,esp_wifi_scan_start()仅在Station或Station + AP模式下支持该API。

扫描所有频道后,将出现WIFI_EVENT_SCAN_DONE。

应用程序的事件回调函数通知应用程序任务已接收到WIFI_EVENT_SCAN_DONE。esp_wifi_scan_get_ap_num()调用以获取在此扫描中找到的AP的数量。然后,它分配足够的条目和调用esp_wifi_scan_get_ap_records()以获取AP记录。请注意,一旦esp_wifi_scan_get_ap_records()被调用,Wi-Fi驱动程序中的AP记录将被释放。esp_wifi_scan_get_ap_records()一次扫描完成事件请勿调用两次。如果esp_wifi_scan_get_ap_records()在发生扫描完成事件时未调用,则不会释放由Wi-Fi驱动程序分配的AP记录。因此,请确保调用esp_wifi_scan_get_ap_records(),但只能调用一次。

/* Scan ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*//*This example shows how to scan for available set of APs.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_event.h"
#include "nvs_flash.h"#define DEFAULT_SCAN_LIST_SIZE CONFIG_EXAMPLE_SCAN_LIST_SIZEstatic const char *TAG = "scan";static void print_auth_mode(int authmode)
{switch (authmode) {case WIFI_AUTH_OPEN:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN");break;case WIFI_AUTH_WEP:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP");break;case WIFI_AUTH_WPA_PSK:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_PSK");break;case WIFI_AUTH_WPA2_PSK:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_PSK");break;case WIFI_AUTH_WPA_WPA2_PSK:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_WPA2_PSK");break;case WIFI_AUTH_WPA2_ENTERPRISE:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_ENTERPRISE");break;case WIFI_AUTH_WPA3_PSK:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_PSK");break;case WIFI_AUTH_WPA2_WPA3_PSK:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_WPA3_PSK");break;default:ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_UNKNOWN");break;}
}static void print_cipher_type(int pairwise_cipher, int group_cipher)
{switch (pairwise_cipher) {case WIFI_CIPHER_TYPE_NONE:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_NONE");break;case WIFI_CIPHER_TYPE_WEP40:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP40");break;case WIFI_CIPHER_TYPE_WEP104:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP104");break;case WIFI_CIPHER_TYPE_TKIP:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP");break;case WIFI_CIPHER_TYPE_CCMP:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_CCMP");break;case WIFI_CIPHER_TYPE_TKIP_CCMP:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");break;default:ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");break;}switch (group_cipher) {case WIFI_CIPHER_TYPE_NONE:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_NONE");break;case WIFI_CIPHER_TYPE_WEP40:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP40");break;case WIFI_CIPHER_TYPE_WEP104:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP104");break;case WIFI_CIPHER_TYPE_TKIP:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP");break;case WIFI_CIPHER_TYPE_CCMP:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_CCMP");break;case WIFI_CIPHER_TYPE_TKIP_CCMP:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");break;default:ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");break;}
}/* Initialize Wi-Fi as sta and set scan method */
static void wifi_scan(void)
{ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));uint16_t number = DEFAULT_SCAN_LIST_SIZE;wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];uint16_t ap_count = 0;memset(ap_info, 0, sizeof(ap_info));ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_start());ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, true));ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));ESP_LOGI(TAG, "Total APs scanned = %u", ap_count);for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) {ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid);ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi);print_auth_mode(ap_info[i].authmode);if (ap_info[i].authmode != WIFI_AUTH_WEP) {print_cipher_type(ap_info[i].pairwise_cipher, ap_info[i].group_cipher);}ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary);}}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 );wifi_scan();
}

• 由 Leung 写于 2021 年 4 月 19 日

• 参考:Wi-Fi驱动程序
    ESP32 开发笔记(三)源码示例 19_WIFI_STA 创建STA站模式连接路由器
    ESP32 开发笔记(三)源码示例 15_WIFI_AP 创建软AP示例
    ESP32 开发笔记(三)源码示例 14_WIFI_Scan 附近WIFI信号扫描示例

ESP32学习笔记(5)——WiFi接口使用(STA和AP模式)相关推荐

  1. HI3861学习笔记(19)——WiFi接口使用(STA和AP模式)

    一.简介 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 HI3861 连接到接入点 (AP). AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 HI3861. 二. ...

  2. ESPIDF开发ESP32学习笔记【WiFi实现】

    WiFi外设配置 ESP32/8266的Wi-Fi库支持配置及监控Wi-Fi连网功能 相关内容参考乐鑫的ESP32/8266文档https://docs.espressif.com/projects/ ...

  3. ESP32学习笔记(7)——SmartConfig接口使用(ESP-Touch和AirKiss)

    一.概述 SmartConfig是TI开发的一种配置技术,用于将新的Wi-Fi设备连接到Wi-Fi网络.它使用移动应用程序将网络凭据从智能手机或平板电脑广播到未配置的Wi-Fi设备. 该技术的优点是设 ...

  4. ESP32学习笔记(50)——ESP-WIFI-MESH接口使用

    一.ESP-WIFI-MESH简介 1.1 概述 ESP-WIFI-MESH是建立在Wi-Fi协议之上的网络协议.ESP-WIFI-MESH允许分布在大范围物理区域内(室内和室外)的许多设备(以下称为 ...

  5. ESP32学习笔记(20)——SPI(从机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  6. ESP32学习笔记(19)——SPI(主机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  7. ESP32学习笔记(14)——HTTP服务器

    一.HTTP简介 HTTP(Hyper Text Transfer Protocol) 超文本传输协议,是一种建立在 TCP 上的无状态连接,整个基本的工作流程是客户端发送一个 HTTP 请求,说明客 ...

  8. ESP32学习笔记(27)——BLE GAP主机端扫描

    一.背景 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...

  9. ESP32学习笔记(七) 复位和时钟

    ESP32学习笔记(七) 复位和时钟 目录: ESP32学习笔记(一) 芯片型号介绍 ESP32学习笔记(二) 开发环境搭建 VSCode+platformio ESP32学习笔记(三) 硬件资源介绍 ...

最新文章

  1. 学习一个 Linux 命令:sort 命令
  2. .net 同步mysql_MySQL服务器主从数据库同步配置
  3. 如何将linux装入空白硬盘,如何将tiny core linux装入硬盘
  4. Moving stones(暴力+思维)
  5. 对于Force.com平台的一些批评 - 持续更新中
  6. 大数据-如何在Docker上使用Hadoop
  7. linux 配置 java tomcat,Linux配置Tomcat和JDK
  8. 腾讯手机QQ更新:最想要的功能终于实现了!
  9. memset初始化类对象出错解析
  10. Git 源码禁止使用 C 标准库中容易被错用的函数
  11. 成功解决pycharm导入第三方库出现ReadTimeoutError超时的问题
  12. java 中j= i_java中 i = i++和 j = i++ 的区别
  13. elementUI table 绑定数据
  14. html调用摄像头ios,html5调用摄像头
  15. 【转载:80个Python经典资料(教程+源码+工具)汇总】
  16. 2022-06微软漏洞通告
  17. 正交补与矩阵的正交补
  18. 看董事长陈睿11周年演讲,一起了解B站未来的三个使命吧
  19. 【Verilog】时序逻辑电路 -- 程序设计与应用
  20. 20篇高质量程序人生文章分享,做开发不仅仅只有代码

热门文章

  1. 使用Arduino ESP32 通过PWM波控制大疆GM6020以及3508无刷电机(更新)
  2. 微信小程序—查询快递
  3. kegg 上ko号对应的通路数据
  4. htcm7刷linux,htc one m7刷官方原版recovery的教程
  5. Mobl试用之helloword
  6. 【STM32】标准库与HAL库对照学习教程十三--软件IIC控制AT24C02
  7. ffmpeg命令分析【详细分析合集】
  8. Win10+OpenCV4.5 无法正常读取USB摄像头数据解决方案
  9. MySQL内部联结和外部联结
  10. 数据库可视化库_漂亮的javascript数据可视化库