(5)WiFi使用(STA模式)

已写文章链接

本专栏主要内容是记录基于ESP32的开发工作,包括介绍 ESP32 基础知识、开发环境搭建、基础外设使用、蓝牙、WiFi 、与微信小程序联动等知识,达到自己动手做一些智能硬件的目的。
开发过程中主要参考官方资料,包括官网、规格书、参考手册、编程指南、驱动包等。
本专栏适合对ESP32感兴趣,想要找一个简单入手教程的同学。

ESP32 基础知识(已完成)

(1)ESP32基础知识

开发环境搭建(已完成)

(2-1)开发环境搭建(基于Arduino)
(2-2)开发环境搭建(基于VS Code+PlatformIO)
(2-3)开发环境搭建(基于ESP-IDF软件)

基础外设使用(已完成)

(3-1)基础外设使用(GPIO)
(3-2)基础外设使用(USART)

蓝牙(已完成)

(4)蓝牙使用(Classic BT+BLE)

WiFi(已完成)

(5)WiFi使用(STA模式)

微信小程序(已完成)

(6)微信小程序(配网和开关灯)


本章会介绍一下 wifi 的基础知识。并给出扫描 wifi、按键、连接 wifi 的示例。

硬件和软件版本

本文章使用的软硬件版本如下。
硬件

  • 开发板:ESP32-DevKitC-32E
  • 模组:ESP32-WROOM-32E
  • 芯片:ESP32-DOWD-V3

软件

  • 开发环境:Arduino IDE V2.2.1
  • ESP32 软件包:V2.0.11

WiFi 基础知识

以下定义来自于 ChatGPT

WiFi是一种无线网络技术,允许设备通过无线信号进行互联和互通。它使用无线电波来传输数据,使设备能够在没有物理连接的情况下进行网络通信。
WiFi的Station模式和AP模式是两种不同的操作模式,各自有着不同的功能和工作方式:
Station模式(站点模式):
作用: 在Station模式下,设备像普通的客户端一样连接到现有的WiFi网络,类似于笔记本电脑、智能手机等设备连接到家庭或办公室的无线路由器。
功能: 设备可以获取IP地址并与网络中的其他设备进行通信,能够接收和发送数据。它作为网络中的一个客户端,依赖于一个已建立的WiFi接入点来连接网络。
AP模式(接入点模式):
作用: 在AP模式下,设备充当WiFi接入点,允许其他设备通过WiFi连接到它所创建的网络。
功能: 设备在AP模式下可以创建自己的WiFi网络,其他设备可以搜索并连接到它创建的网络。它负责路由数据包并提供连接,类似于一个无线路由器。
区别:
功能角色不同: 在Station模式下,设备是连接到一个现有网络的客户端;而在AP模式下,设备是创建并提供WiFi网络的主机。
连接方式不同: 在Station模式下,设备连接到现有的WiFi网络;在AP模式下,设备创建自己的WiFi网络,其他设备连接到它。
网络管理权限不同: 在AP模式下,设备可以管理创建的网络设置和连接参数;而在Station模式下,设备需要遵循网络提供的设置。
需要注意的是,某些设备可能支持同时处于Station和AP模式,允许设备既连接到一个网络,同时也提供自己的网络给其他设备连接。

硬件连接

本章硬件无连接,开发板使用 WIFI 的 Station 模式来连接路由器。
image.png
现在有些路由器是双频的,即 2.4G 和 5G,其中 ESP32 的 wifi 硬件不支持 5G。所以后边我们连接 2.4G WIFI 即可。要是路由设置了多频合一,那有可能搜不到 wifi,在路由管理界面中关闭多频合一即可。
image.pngimage.png

软件设计

源文件功能

本章使用Arduino的例程,选择示例—WiFi—WiFiClientConnect
image.png
这里先贴出源文件代码。源文件大概的流程是初始化了一个按键和 wifi,上电之后按照用户设定的ssidpassword尝试连接 wifi,有 wifi 未找见、wifi 连接失败、连接丢失、连接成功等状态,要是超时未连接成功,则认为连接失败,退出。使用按键可以关闭当前连接 wifi。

/* Wi-Fi STA Connect and Disconnect Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
   
*/
#include <WiFi.h>

const char* ssid     = "your-ssid";
const char* password = "your-password";

int btnGPIO = 0;
int btnState = false;

void setup()
{
    Serial.begin(115200);
    delay(10);

    // Set GPIO0 Boot button as input
    pinMode(btnGPIO, INPUT);

    // We start by connecting to a WiFi network
    // To debug, please enable Core Debug Level to Verbose

    Serial.println();
    Serial.print("[WiFi] Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);
// Auto reconnect is set true as default
// To set auto connect off, use the following function
//    WiFi.setAutoReconnect(false);

    // Will try for about 10 seconds (20x 500ms)
    int tryDelay = 500;
    int numberOfTries = 20;

    // Wait for the WiFi event
    while (true) {
        
        switch(WiFi.status()) {
          case WL_NO_SSID_AVAIL:
            Serial.println("[WiFi] SSID not found");
            break;
          case WL_CONNECT_FAILED:
            Serial.print("[WiFi] Failed - WiFi not connected! Reason: ");
            return;
            break;
          case WL_CONNECTION_LOST:
            Serial.println("[WiFi] Connection was lost");
            break;
          case WL_SCAN_COMPLETED:
            Serial.println("[WiFi] Scan is completed");
            break;
          case WL_DISCONNECTED:
            Serial.println("[WiFi] WiFi is disconnected");
            break;
          case WL_CONNECTED:
            Serial.println("[WiFi] WiFi is connected!");
            Serial.print("[WiFi] IP address: ");
            Serial.println(WiFi.localIP());
            return;
            break;
          default:
            Serial.print("[WiFi] WiFi Status: ");
            Serial.println(WiFi.status());
            break;
        }
        delay(tryDelay);
        
        if(numberOfTries <= 0){
          Serial.print("[WiFi] Failed to connect to WiFi!");
          // Use disconnect function to force stop trying to connect
          WiFi.disconnect();
          return;
        } else {
          numberOfTries--;
        }
    }
}

void loop()
{
    // Read the button state
    btnState = digitalRead(btnGPIO);
    
    if (btnState == LOW) {
      // Disconnect from WiFi
      Serial.println("[WiFi] Disconnecting from WiFi!");
      // This function will disconnect and turn off the WiFi (NVS WiFi data is kept)
      if(WiFi.disconnect(true, false)){
        Serial.println("[WiFi] Disconnected from WiFi!");
      }
      delay(1000);
    }
}

更改一些功能

我们对源文件加一些改造,完成这个功能:上电之后扫描并打印周围的 wifi,按键按下后采用用户设定的 wifi 参数(ssid+password)连接指定 wifi,连接成功后打印当前 wifi 的 ip。
我们分解一下任务功能。完成大概 3 个任务:

  • 扫描周围 wifi 并打印。
  • 可以响应按键按下。
  • 连接指定 wifi,可以根据连接状态打印 ip。

扫描周围 wifi

Arduino有一个扫描 wifi 的例程,如下。
image.png
源文件如下,大概逻辑是初始化 wifi 为 STA 模式,每隔 5 秒扫描一次周围 wifi,如果扫描结果显示周围有 wifi,就打印 wifi 的 ssid 、信号强度、通道、加密方式。

/*
 *  This sketch demonstrates how to scan WiFi networks.
 *  The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported.
 *  E.g. the return value of `encryptionType()` different because more modern encryption is supported.
 */
#include "WiFi.h"

void setup()
{
    Serial.begin(115200);

    // Set WiFi to station mode and disconnect from an AP if it was previously connected.
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);

    Serial.println("Setup done");
}

void loop()
{
    Serial.println("Scan start");

    // WiFi.scanNetworks will return the number of networks found.
    int n = WiFi.scanNetworks();
    Serial.println("Scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        Serial.println("Nr | SSID                             | RSSI | CH | Encryption");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.printf("%2d",i + 1);
            Serial.print(" | ");
            Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
            Serial.print(" | ");
            Serial.printf("%4d", WiFi.RSSI(i));
            Serial.print(" | ");
            Serial.printf("%2d", WiFi.channel(i));
            Serial.print(" | ");
            switch (WiFi.encryptionType(i))
            {
            case WIFI_AUTH_OPEN:
                Serial.print("open");
                break;
            case WIFI_AUTH_WEP:
                Serial.print("WEP");
                break;
            case WIFI_AUTH_WPA_PSK:
                Serial.print("WPA");
                break;
            case WIFI_AUTH_WPA2_PSK:
                Serial.print("WPA2");
                break;
            case WIFI_AUTH_WPA_WPA2_PSK:
                Serial.print("WPA+WPA2");
                break;
            case WIFI_AUTH_WPA2_ENTERPRISE:
                Serial.print("WPA2-EAP");
                break;
            case WIFI_AUTH_WPA3_PSK:
                Serial.print("WPA3");
                break;
            case WIFI_AUTH_WPA2_WPA3_PSK:
                Serial.print("WPA2+WPA3");
                break;
            case WIFI_AUTH_WAPI_PSK:
                Serial.print("WAPI");
                break;
            default:
                Serial.print("unknown");
            }
            Serial.println();
            delay(10);
        }
    }
    Serial.println("");

    // Delete the scan result to free memory for code below.
    WiFi.scanDelete();

    // Wait a bit before scanning again.
    delay(5000);
}

执行结果如下。从结果中也能看到只能搜到 2.4G 的 wifi,搜不到 5G 的。
image.png
我们只需要做到上电时扫描即可。所以将loop中的函数放到setup中执行,最终代码如下:

/*
 *  This sketch demonstrates how to scan WiFi networks.
 *  The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported.
 *  E.g. the return value of `encryptionType()` different because more modern encryption is supported.
 */
#include "WiFi.h"

void setup()
{
    Serial.begin(115200);

    // Set WiFi to station mode and disconnect from an AP if it was previously connected.
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);

    Serial.println("Setup done");
    
    Serial.println("Scan start");
      // WiFi.scanNetworks will return the number of networks found.
    int n = WiFi.scanNetworks();
    Serial.println("Scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        Serial.println("Nr | SSID                             | RSSI | CH | Encryption");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.printf("%2d",i + 1);
            Serial.print(" | ");
            Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
            Serial.print(" | ");
            Serial.printf("%4d", WiFi.RSSI(i));
            Serial.print(" | ");
            Serial.printf("%2d", WiFi.channel(i));
            Serial.print(" | ");
            switch (WiFi.encryptionType(i))
            {
            case WIFI_AUTH_OPEN:
                Serial.print("open");
                break;
            case WIFI_AUTH_WEP:
                Serial.print("WEP");
                break;
            case WIFI_AUTH_WPA_PSK:
                Serial.print("WPA");
                break;
            case WIFI_AUTH_WPA2_PSK:
                Serial.print("WPA2");
                break;
            case WIFI_AUTH_WPA_WPA2_PSK:
                Serial.print("WPA+WPA2");
                break;
            case WIFI_AUTH_WPA2_ENTERPRISE:
                Serial.print("WPA2-EAP");
                break;
            case WIFI_AUTH_WPA3_PSK:
                Serial.print("WPA3");
                break;
            case WIFI_AUTH_WPA2_WPA3_PSK:
                Serial.print("WPA2+WPA3");
                break;
            case WIFI_AUTH_WAPI_PSK:
                Serial.print("WAPI");
                break;
            default:
                Serial.print("unknown");
            }
            Serial.println();
            delay(10);
        }
    }
    Serial.println("");

    // Delete the scan result to free memory for code below.
    WiFi.scanDelete();

    Serial.println("Scan finished");

}

void loop()
{
  
}

代码执行结果如下。
image.png

响应按键

这个功能采用之前 GPIO 章节的即可。读按键引脚电平的周期为 5 秒,所以按键要超过 5 秒才有效。

/* Wi-Fi STA Connect and Disconnect Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
   
*/
#include <WiFi.h>

#define LED 16
#define BUTTON 0

int btnGPIO = 0;
int btnState = false;

void setup()
{
    pinMode(LED, OUTPUT);
    pinMode(BUTTON, INPUT);
    
    Serial.begin(115200);
    delay(10);
}

void loop()
{
    if(digitalRead(BUTTON) == 0) 
    {
      digitalWrite(LED, HIGH);
      delay(1000);
    }
    delay(5000);
}

连接指定 wifi

我的网络如下。2.4G 的 SSID 为JinHuan_2,密码为自己设定的。
image.png
然后来做连接指定 wifi,并根据 wifi 连接结果打印 ip 的功能。改造一下开头的那个示例:示例—WiFi—WiFiClientConnect,在响应按键的基础上加入连接 wifi 功能。
代码如下。

/* Wi-Fi STA Connect and Disconnect Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
   
*/
#include <WiFi.h>

#define LED 16
#define BUTTON 0

const char* ssid     = "JinHuan_2";
const char* password = "your-password";

int btnGPIO = 0;
int btnState = false;

void setup()
{
    pinMode(LED, OUTPUT);
    pinMode(BUTTON, INPUT);
    
    Serial.begin(115200);
    delay(10);
      // Set WiFi to station mode and disconnect from an AP if it was previously connected.
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);

    Serial.println("Setup done");
    Serial.println("Scan start");
      // WiFi.scanNetworks will return the number of networks found.
    int n = WiFi.scanNetworks();
    Serial.println("Scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        Serial.println("Nr | SSID                             | RSSI | CH | Encryption");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.printf("%2d",i + 1);
            Serial.print(" | ");
            Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
            Serial.print(" | ");
            Serial.printf("%4d", WiFi.RSSI(i));
            Serial.print(" | ");
            Serial.printf("%2d", WiFi.channel(i));
            Serial.print(" | ");
            switch (WiFi.encryptionType(i))
            {
            case WIFI_AUTH_OPEN:
                Serial.print("open");
                break;
            case WIFI_AUTH_WEP:
                Serial.print("WEP");
                break;
            case WIFI_AUTH_WPA_PSK:
                Serial.print("WPA");
                break;
            case WIFI_AUTH_WPA2_PSK:
                Serial.print("WPA2");
                break;
            case WIFI_AUTH_WPA_WPA2_PSK:
                Serial.print("WPA+WPA2");
                break;
            case WIFI_AUTH_WPA2_ENTERPRISE:
                Serial.print("WPA2-EAP");
                break;
            case WIFI_AUTH_WPA3_PSK:
                Serial.print("WPA3");
                break;
            case WIFI_AUTH_WPA2_WPA3_PSK:
                Serial.print("WPA2+WPA3");
                break;
            case WIFI_AUTH_WAPI_PSK:
                Serial.print("WAPI");
                break;
            default:
                Serial.print("unknown");
            }
            Serial.println();
            delay(10);
        }
    }
    Serial.println("");

    // Delete the scan result to free memory for code below.
    WiFi.scanDelete();

    Serial.println("Scan finished");
}

void loop()
{
    if(digitalRead(BUTTON) == 0) 
    {
      digitalWrite(LED, HIGH);

      Serial.print("[WiFi] Connecting to ");
      Serial.println(ssid);

      WiFi.begin(ssid, password);
      WiFi.setAutoReconnect(false);

      delay(1000);
    }
    
    if(WiFi.status() == WL_CONNECTED)
    {
      Serial.println("[WiFi] WiFi is connected!");
      Serial.print("[WiFi] IP address: ");
      Serial.println(WiFi.localIP());
    }
    else
    {
      Serial.print("[WiFi] WiFi Status: ");
      Serial.println(WiFi.status());
    }
    delay(5000);
}

执行结果如下,连接上了 SSID 为JinHuan_2的 wifi,并且获取到了 IP。
image.png
从路由器的管理界面也能看到 2.4G 的已连设备从 0 变为 1。
image.png
若我们想设置上电自动连接 wifi,则可以修改源码如下。

/* Wi-Fi STA Connect and Disconnect Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
   
*/
#include <WiFi.h>

#define LED 16
#define BUTTON 0

const char* ssid     = "JinHuan_2";
const char* password = "your-password";

int btnGPIO = 0;
int btnState = false;

void setup()
{
    pinMode(LED, OUTPUT);
    pinMode(BUTTON, INPUT);
    
    Serial.begin(115200);
    delay(10);

    Serial.print("[WiFi] Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);
    
    do
    {
      Serial.print("[WiFi] WiFi Status: ");
      Serial.println(WiFi.status());
      delay(1000);
    }while(WiFi.status() != WL_CONNECTED);

    Serial.println("[WiFi] WiFi is connected!");
    Serial.print("[WiFi] IP address: ");
    Serial.println(WiFi.localIP());
}

void loop()
{

}

执行结果如下。

在这里插入图片描述

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: ESP8266 WiFi模块STA模式是一种工作模式,它允许ESP8266模块连接到一个已经存在的WiFi网络中,以便实现无线通信。在STA模式下,ESP8266模块作为客户端连接到WiFi网络,可以通过TCP/IP协议与其他设备进行通信。此模式需要提供WiFi网络的SSID和密码,以便ESP8266模块能够连接到网络。STA模式是ESP8266模块最常用的工作模式之一,它可以用于许多应用,如远程控制、数据传输、物联网等。 ### 回答2: ESP8266是一款可以集成WiFi功能的芯片,它的STA模式是其中一种工作模式STA全称为Station,即作为客户端连接到现有的WiFi网络。STA模式可以让用户轻松地连接到一个无线路由器或者接入点,并通过这个路由器或者接入点来连接到互联网。 使用ESP8266的STA模式,我们需要在代码中设置WiFi的SSID和密码,以便模块可以连接到该WiFi网络。代码中可以通过`WiFi.begin(ssid, password)`函数来连接WiFi网络。ESP8266连接到WiFi网络后,可以使用WiFi库中的函数来执行网络操作,如使用HTTP请求向云服务器发送数据等。 在STA模式下,ESP8266可以连接到任何支持WiFi的设备上,包括路由器,手机热点等,使得其应用范围非常广泛。我们可以使用它来实现各种物联网应用,比如智能家居、智能车联网等。 除了STA模式,ESP8266还有AP模式,即作为一个热点连接到其他设备上。在AP模式下,ESP8266可以作为一个服务器,为其他设备提供服务。AP模式也可以和STA模式一样在同一个程序中切换,这使得我们可以使用ESP8266作为一个智能设备的核心模块。 总之,ESP8266的STA模式提供了一种简便的方法来连接到现有的WiFi网络,使得我们可以轻松地实现各种物联网应用。同时,ESP8266在STA模式下还支持多路连接,可以同时处理多个TCP连接,为我们提供更加强大的网络功能。 ### 回答3: ESP8266WiFi模块STA模式简介 ESP8266WiFi模块是一种低成本且易于使用的Wi-Fi模块,它采用基于ESP8266芯片设计的物联网解决方案,支持标准802.11b/g/n协议。在ESP8266WiFi模块中,STA模式使模块能够与Wi-Fi路由器连接,实现对互联网的访问。现在让我们来深入了解一下ESP8266WiFi模块STA模式。 1. STA模式的特点 STA是ESP8266WiFi模块的一种连接模式。在该模式中,ESP8266WiFi模块将作为Wi-Fi客户端工作,并尝试连接到其他Wi-Fi接入点或路由器。它能够访问互联网,获取IP地址并连接到其他设备。以下是STA模式的特点: - 可通过Wi-Fi路由器连接互联网,实现对网络资源的访问。 - 可以在任意地方实现远程测量、监测和控制。 - 可以通过向ESP8266WiFi模块发送数据来控制连接的设备。 - 可以通过使用TCP/IP协议与其他设备通信。 2. STA模式的连接方式 在ESP8266WiFi模块STA模式中,您可以选择不同的连接方式。以下是常用的两种连接方式: - 正常连接方式:在此模式下,ESP8266WiFi模块将实时监测Wi-Fi网络以确定何时可用并尝试连接到可用的Wi-Fi接入点或路由器。 - 强制连接方式:在该模式下,ESP8266WiFi模块将尝试一直连接到指定的Wi-Fi接入点或路由器。 3. STA模式的代码实现 要使用ESP8266WiFi模块STA模式,需要编写相关代码来初始化模块并实现连接。以下是一些示例代码: - 配置模块:在此示例中,您需要为ESP8266WiFi模块设置网络参数,例如Wi-Fi网络名称和密码。 ``` #include <ESP8266WiFi.h> const char* ssid = "YOUR_SSID"; // Wi-Fi网络名称 const char* password = "YOUR_PASSWORD"; // Wi-Fi网络密码 void setup() { Serial.begin(115200); delay(10); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("IP address: "); Serial.println(WiFi.localIP()); } ``` - 监听网络:在此示例中,您需要在ESP8266WiFi模块连接到Wi-Fi网络后监听TCP端口。 ``` #include <ESP8266WiFi.h> #include <WiFiServer.h> const char* ssid = "YOUR_SSID"; // Wi-Fi网络名称 const char* password = "YOUR_PASSWORD"; // Wi-Fi网络密码 WiFiServer server(80); void setup() { Serial.begin(115200); delay(10); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); } void loop() { WiFiClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); } } client.stop(); } } ``` 总结 ESP8266WiFi模块STA模式是连接Wi-Fi网络的有用工具。它能够访问互联网,接收网络数据并控制其他设备。同时,编写基于ESP8266WiFi模块STA模式的代码是非常简单的。我们只需定义要连接的Wi-Fi网络名称和密码,并实现TCP/IP通信协议即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尽欢_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值