【保姆级IDF】ESP32使用WIFI作为STA模式实现:WIFI扫描串口输出+串口输入指定WIFI名称和密码+连接WIFI

Tips:

抛砖引玉,本文记录ESP32学习过程中遇到的收获。如有不对的地方,欢迎指正。

Tcp通信参看我其他文章:

【保姆级IDF】ESP32使用WIFI作为STA模式与其他设备进行TCP通信

【保姆级IDF】ESP32使用WIFI作为AP模式TCP通信:连接客户端+一对多通信

目录

1.实现的具体功能

2.代码思路

3.具体代码解释

3.1 串口配置(以下代码需要特定头文件,这里不赘述)

3.2 WIFI初始化及扫描发送至串口

3.3 WIFI信息输入后再次开启并初始化连接

3.4 主函数部分

3.5 其他代码

3.6 成果展示

4.总结


1.实现的具体功能

        ESP32上电后开启WIFI扫描,将周围可扫描到的10个WIFI热点(如果有,不够十个则以具体扫描到的数量为准)利用串口打印出来,随后可通过串口发送数据来选择要连接的WIFI热点以及密码。密码输入完成后即自动连接,连接成功会打印所连接的WIFI信息和密码,连接失败比如密码错误等会重试连接,若还是连不上则打印连接失败。

        可以搭配其他主控芯片(如:C51、STM32、GD32等等)来对ESP32进行串口通信,继而向其他无线设备进行通信(利用WIFI建立TCP通信下期更新),这提升了ESP32对于WIFI连接的拓展性,不需要再将WIFI信息写死在代码中,而是可有选择的连接WIFI,提升了代码灵活性。

2.代码思路

        1.初始化串口通信,使用队列处理串口事件。

        2.初始化WIFI,开启扫描,并将扫描到的结果利用串口发送出去,随后关闭WIFI

        3.屏蔽WIFI事件函数中,当WIFI_Start状态时进行连接的connect函数,此时并未配置SSID和PASSWORD。依据发送的WIFI名称的顺序编号,等待串口输入选择几号WIFI,则将该WIFI名称写入到WIFI配置的结构体中(wifi_config_t  wifi_config),再等待密码输入,同样的操作写入到WIFI配置的结构体中。

        4.在密码写入完成后,再次初始化WIFI并开启,这时的WIFI初始化代码和第一次有点不太一样。开启WIFI后直接进行连接,此时已完成WIFI连接信息的配置。

3.具体代码解释

3.1 串口配置(以下代码需要特定头文件,这里不赘述)

#define EX_UART_NUM UART_NUM_0
#define PATTERN_CHR_NUM    (3) 
uint8_t Command[1024];
wifi_config_t wifi_config = {//wifi配置结构体初始化
    .sta = {
        .ssid = "",
        .password = "",
        /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
         * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
         * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
         * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
         */
        .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
        .sae_pwe_h2e = ESP_WIFI_SAE_MODE,
        .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
    },
};
static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    size_t buffered_size;
    uint8_t EndFlag1 = 0;
    uint8_t EndFlag2 = 0;
    int xiabiao = 0;
    //uint8_t* Command = (uint8_t*) malloc(RD_BUF_SIZE);
    for (;;) {
        //Waiting for UART event.
        if (xQueueReceive(uart0_queue, (void *)&event, 20 / portTICK_PERIOD_MS)) {//队列接收
            bzero(Command, RD_BUF_SIZE);
            //ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
            switch (event.type) {    //判断串口事件类型
            //Event of UART receving data
            /*We'd better handler data event fast, there would be much more data events than
            other types of events. If we take too much time on data event, the queue might
            be full.*/
            case UART_DATA:   //数据事件,接收数据在此触发
                //ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                memset(Command,0,1024); //初始化缓冲区buffer:Command[1024]
                uart_read_bytes(EX_UART_NUM, Command, event.size, portMAX_DELAY);//读取串口缓冲区数据
                for(int i = 0; i < strlen((const char*)Command); i++)//这里我使用一种特定协议,在这里判断信息数据是否符合协议格式
                {
                    if(Command[i] == 0x3c && Command[i+1] == 0x3c)
                    {
                        xiabiao = i;
                    }
                }
                EndFlag1 = Command[xiabiao+3] + 4 + xiabiao;
                EndFlag2 = Command[xiabiao+3] + 5 + xiabiao;
                if(Command[xiabiao] == 0x3c && Command[xiabiao+1] == 0x3c && Command[EndFlag1] == 0x3e && Command[EndFlag2] == 0x3e)//如果符合协议格式则进入判断信息的类型:输入WIFI名称orWIFI密码
                {
                    ESP_LOGI(TAG, "判断帧头进入");
                    if(Command[xiabiao+2] == WIFI_Number && Command[xiabiao+3] == 0x01)
                    {
                        ESP_LOGI(TAG, "判断选择WIFI进入");
                        OrderSwitch(Command[xiabiao+4]);//选择WIFI的函数,下文会讲到
                    }
                    else if(Command[xiabiao+2] == PASSWORD)
                    {
                        ESP_LOGI(TAG, "判断密码进入");
                        for(int i = 0; i < Command[xiabiao+3]; i++)//协议格式中第四个字节表示为实际有效数据的长度
                        {
                            wifi_config.sta.password[i] = Command[xiabiao+4+i];//将密码写入WIFI配置的结构体
                        }
                        wifi_init_sta();//配置好后初始化WIFI
                    }
                }
                break;
            //Event of HW FIFO overflow detected
            case UART_FIFO_OVF:
                ESP_LOGI(TAG, "hw fifo overflow");
                // If fifo overflow happened, you should consider adding flow control for your application.
                // The ISR has already reset the rx FIFO,
                // As an example, we directly flush the rx buffer here in order to read more data.
                uart_flush_input(EX_UART_NUM);
                xQueueReset(uart0_queue);
                break;
            //Event of UART ring buffer full
            case UART_BUFFER_FULL:
                ESP_LOGI(TAG, "ring buffer full");
                // If buffer full happened, you should consider increasing your buffer size
                // As an example, we directly flush the rx buffer here in order to read more data.
                uart_flush_input(EX_UART_NUM);
                xQueueReset(uart0_queue);
                break;
            //Event of UART RX break detected
            
            //Others
            default:
                ESP_LOGI(TAG, "uart event type: %d", event.type);
                break;
            }
        }
    }
    //free(Command);
    //Command = NULL;
    vTaskDelete(NULL);
}

void Init_uart() 
{
    esp_log_level_set(TAG, ESP_LOG_INFO);

    // 配置Uart驱动的参数、引脚并安装驱动
    uart_config_t uart_config = {
        .baud_rate = 115200,                    //波特率:115200
        .data_bits = UART_DATA_8_BITS,          //有效位:8位
        .parity = UART_PARITY_DISABLE,          //校验模式:无
        .stop_bits = UART_STOP_BITS_1,          //停止位:1位
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,  //硬件流控制:无
        .source_clk = UART_SCLK_DEFAULT,        //默认时钟
    };
    //安装Uart驱动并获得队列
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 6, BUF_SIZE * 6, 50, &uart0_queue, 0);//20
    uart_param_config(EX_UART_NUM, &uart_config);

    //设置Uart日志级别
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //设置Uart引脚 (使用Uart0默认引脚不用改变)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //设置图形检测功能
    uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    //重置队列长度,最多纪录50条信息
    uart_pattern_queue_reset(EX_UART_NUM, 50);//20

    //为Uart队列接收消息创建freertos任务,这里我给的内存偏大
    xTaskCreate(uart_event_task, "uart_event_task", 1024*16, NULL, 13, &uart_handle);    
}

        初始化Uart,配置好以上参数后为串口队列接收创建任务,这里我设置的任务内存还有队列长度是偏大的。Orderswitch函数在后文会提到,是一个根据编号配置WIFI名称的函数。在接收数据时,我遵循一定的格式,以0x3c,0c3c开头,0x3e,0x3e结尾,第三个字节表示数据类型(名称or密码)第四个字节表示从第五个字节开始到第一个0x3e前的实际有效数据的长度。所以我写了一个简单的算法去识别了一下。判断输入的信息是WIFI名称还是密码,并将它写到WIFI配置的结构体以备WIFI初始化连接时调用。

3.2 WIFI初始化及扫描发送至串口

#define EXAMPLE_ESP_MAXIMUM_RETRY  CONFIG_ESP_MAXIMUM_RETRY
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)

#define WIFI_Number                0x01
#define PASSWORD                   0x02
#define Camera_cmd                 0x03
#define RECV_BUF_SIZE              8192  // 设置接收缓冲区大小

#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif

#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1

typedef struct _SSID_data {
	uint8_t ssid[33];
	int8_t rssi;
}SSID_data;

typedef struct _WIFI_data {
	uint16_t head;
	uint8_t Type;
	uint8_t Length;
	uint8_t data[33];
	int8_t rssi;
	uint16_t end;
}WIFI_data;

static wifi_ap_record_t ap_info[10];
SSID_data WIFI_ID[10];
WIFI_data write_data = {
    .head = head_data,
	.Type = WIFI_SSID,
	.Length = 34,
	.end = end_data,
};

static void wifi_scan(void)
{
    uint8_t X = 0;//去重后的WiFi数量
    ESP_ERROR_CHECK(esp_netif_init());//初始化底层TCP/IP协议栈
    ESP_ERROR_CHECK(esp_event_loop_create_default());//创建默认事件循环
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();//创建默认WIFi STA
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//创建默认配置结构体
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));//配置结构体
    memset(ap_info, 0, sizeof(ap_info));//将ap_info初始化

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));//设置为STA模式
    //esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
    ESP_ERROR_CHECK(esp_wifi_start());//开启WIFI
    esp_wifi_scan_start(NULL, true);//开启扫描
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));//获得扫描到的WIFi信息
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));//获得扫描到的WIFI数量
    //esp_wifi_sta_get_ap_info(ap_info);
    memset(WIFI_ID, 0, sizeof(WIFI_ID));//初始化WIFI_ID
    //strcpy((char*)WIFI_ID[0].ssid,(const char*)ap_info[0].ssid);
    for (int i = 0; i < number; i++) {//因为扫描到的WIFi可能会有重复,所以简单写了个算法过滤
        for (int j = 0; j < i; j++) {
            if (strcmp((const char *)ap_info[i].ssid, (const char *)ap_info[j].ssid) == 0) {
                // 已存在相同的 SSID,跳过
                goto next;
            }
        }
        if(strcmp((const char *)ap_info[i].ssid, "") != 0)//判断WIFi名称是否为空,有时可能不够十个WIFI热点,多余的内存会显示空
        {
            strcpy((char*)WIFI_ID[X].ssid,(const char*)ap_info[i].ssid);//复制WIFI名称信息
            WIFI_ID[X].rssi = ap_info[i].rssi;
            X++;//X变量代表过滤后的WIFI数量
        }
    next:
        continue;
    }
    for (int i = 0; i < X; i++) {//根据X来用串口将WIFi名称发送
        memset(write_data.data, 0, sizeof(write_data.data));//初始化write_data,清零
        //strcpy((char*)WIFI_ID[i].ssid,(const char*)ap_info[i].ssid);
        strcpy((char*)write_data.data,(const char*)WIFI_ID[i].ssid);将WIFi_ID中的WIFI信息复制出来
        write_data.rssi = WIFI_ID[i].rssi;//这是扫描到的WIFi信号强度值
        uart_write_bytes(EX_UART_NUM, &write_data, sizeof(write_data));//将WIFI用串口发送出去
        //printf("%s\n",WIFI_ID[i].ssid);
        vTaskDelay(150 / portTICK_PERIOD_MS);//延时150ms
    }
    esp_wifi_stop();//关闭WIFI
}

        初始化WIFI并开启扫描,这些步骤在idf例程代码中都可以找到。扫描后将数据保存出来,这中间写了一个简单的过滤算法把重复的WIFI信息过滤掉了。然后把过滤好的WIFI信息用串口发送出来,每次发送间隔了150ms,主要为了防止主控是单片机的情况下,发送速度太快,导致接收不全。完成这些工作后关闭WIFI。等待串口提供WIFI信息。

3.3 WIFI信息输入后再次开启并初始化连接

        在上文串口配置部分,已经详细解释了如何用串口接收WIFI信息并将其写入WIFI配置结构体,所以本部分介绍在信息完善的情况下再次开启WIFI功能并连接到指定WIFI。

static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* recv_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        //esp_wifi_connect();(这里一定要将esp_wifi_connect屏蔽,否则在WIFi开启后扫描前会直接进行连接,但是此时你还没有输入WIFi名称和密码)
    } 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);
            //vTaskSuspend(Getinfo_handle);//这里断开连接后将任务挂起,这个任务与本文介绍的功能无关,可以直接屏蔽
            esp_restart();//ESP32重启
        }
        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*) recv_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
        esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
        esp_netif_get_ip_info(netif, &IP_info);
        ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&IP_info.ip));
        ESP_LOGI(TAG, "IP Gw: " IPSTR, IP2STR(&IP_info.gw));
        //IP = inet_ntoa(IP_info.gw);//转换IP为字符串
        //camera();//无需关心
    }
}

void wifi_init_sta(void)
{
    s_wifi_event_group = xEventGroupCreate();//创建WIFI事件组
    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));//将事件处理程序注册到默认循环
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );//设置为STA模式
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );//配置WIFI
    ESP_ERROR_CHECK(esp_wifi_start() );//启动WIFI
    ESP_LOGI(TAG, "wifi_init_sta finished.");
    esp_wifi_connect();//进行连接操作
    /* 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 event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
                 wifi_config.sta.ssid, wifi_config.sta.password);
    send_data.data[0] = 0xa0;
    send_data.data[1] = 0xa0;//连接成功后发送A0A0
    uart_write_bytes(EX_UART_NUM,&send_data, sizeof(send_data));
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
                 wifi_config.sta.ssid, wifi_config.sta.password);
    send_data.data[0] = 0xb0;
    send_data.data[1] = 0xb0;//连接失败后发送B0B0
    uart_write_bytes(EX_UART_NUM,&send_data, sizeof(send_data));
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }
    vTaskDelay(10 / portTICK_PERIOD_MS);
}

        这里重点是默认事件循环中当WIFi开启时(WIFI_EVENT_STA_START)的事件,在这个事件中务必屏蔽esp_wifi_connect()。还有一个特殊点,这里是第二次开启WIFI时,在初始化过程中,相比于第一次扫描时初始化WIFI少了三行代码:   

        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();

以上代码在初始化WIFI过程中只需执行一次即可,后续不用再执行。

3.4 主函数部分

        main函数中只需初始化串口和WIFI即可

void app_main(void)
{
    //fgets(send_data, sizeof(send_data), stdin);
    //Initialize NVS
    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_LOGI(TAG, "ESP_WIFI_MODE_STA");
    Init_uart();
    wifi_scan();
    // QueueHandle_t recvQueue = xQueueCreate(10, 1024);
    // if (recvQueue == NULL) {
    // // 处理队列创建失败
    // }
}

3.5 其他代码

头文件:

#include <string.h>
#include "stdbool.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.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"
#include "esp_netif.h"
#include "lwip/sockets.h"
#include "lwip/errno.h"
#include "lwip/prot/dns.h"
#include "driver/gpio.h"
#include "esp_attr.h"
#include "soc/soc.h"
#include "esp_intr_alloc.h"
#include "esp_efuse.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <lwip/inet.h>
#include <lwip/netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "esp_sleep.h"
#include "esp_timer.h"
#include <errno.h>
#include "esp_task.h"
#include "freertos/task.h"

        按需选取头文件即可。

OrderSwitch函数:

void OrderSwitch(uint8_t cmd)
{
    switch(cmd)
    {
        case Number1:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));//清零
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[0].ssid);
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[0].ssid);//复制WIFi名称到WIFi配置结构体
            uart_write_bytes(EX_UART_NUM, &ap_id,sizeof(ap_id));
            break;
        case Number2:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[1].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[1].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number3:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[2].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[2].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number4:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[3].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[3].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number5:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[4].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[4].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number6:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[5].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[5].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number7:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[6].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[6].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number8:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[7].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[7].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number9:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[8].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[8].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        case Number10:
            memset((char*)wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
            memset((char*)ap_id.data, 0, sizeof(ap_id.data));
            strcpy((char*)wifi_config.sta.ssid, (const char*)WIFI_ID[9].ssid);
            strcpy((char*)ap_id.data, (const char*)WIFI_ID[9].ssid);
            uart_write_bytes(EX_UART_NUM,  &ap_id,sizeof(ap_id));
            break;
        default:
            //uart_write_bytes(EX_UART_NUM, 0xff, 1);
            break;
    }
}

Number1~10是宏定义,值就是1~10

3.6 成果展示

        手机显示有设备接入

4.总结

       串口实现数据的发送,可以传递WIFi信息,总的来说:先开WIFi扫描,然后打印WIFI信息,随后关闭WIFI,等待串口的输入信息,接收到信息后配置WIFi,第二次开启WIFi初始化并连接,中间可以添加一些调试打印。这么做的好处是可以把ESP32的WIFI连接过程变得像手机电脑的WIFI连接过程一样,让作品变得更加智能。

        以上代码博主经过实测可用稳定,如有疑问欢迎留言交流。以上观点为个人理解,只想抛砖引玉,如有不对的地方欢迎指正,不喜轻喷。

tips:下期更新利用WIFI创建socket与其他设备建立TCP通信的方法。


2024.10.19-11:43更新

加上了OrderSwitch函数介绍


如果有收获的话还可以支持一下作者,你的一键三连就是对我最大的肯定!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_山岚_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值