IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> esp32 smartconfig+然后保存ssid和password+tcp <----->串口通讯 -> 正文阅读

[网络协议]esp32 smartconfig+然后保存ssid和password+tcp <----->串口通讯

?1.先初始化NVS,?nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler):打开配置文件读取wifi配置信息。

if(MY_WIFI_UPDATE == wifi_update ):首次运行时,从配置信息读取出来的wifi_update为0,

所以会将变量中的WiFi信息保存至NVS

接着led初始化,定时器闪烁初始化,wifi 初始化,串口初始化

static void app_init(void)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);
    /* 初始化非易失性存储库 (NVS) */
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        /* NVS分区被截断,需要删除,然后重新初始化NVS */
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK( err );
     /* 定义一个NVS操作句柄 */
    nvs_handle wificfg_nvs_handler;
    /* 打开一个NVS命名空间 */
    ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );

    uint32_t wifi_update = 0;
    err = nvs_get_u32(wificfg_nvs_handler,"wifi_update",&wifi_update);
    if(MY_WIFI_UPDATE == wifi_update )  //最开始需要----是否更新wifi
        printf("wifi_cfg needn't to update. \n");
    else
    {
        printf("wifi_cfg update now... \n");
        ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_ssid",MY_WIFI_SSID) );
        ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_passwd",MY_WIFI_PASSWD) ); 
        ESP_ERROR_CHECK( nvs_set_u32(wificfg_nvs_handler,"wifi_update",MY_WIFI_UPDATE) );
        printf("wifi_cfg update ok. \n");
    }
    ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
    nvs_close(wificfg_nvs_handler);                     /* 关闭 */
    printf("ESP_WIFI_MODE_STA \n");
    configure_led();  //led先初始化    
    esp_timer_init(); //使用定时器API函数, 
    err = esp_timer_create(&test_periodic_arg, &test_p_handle);  // 开始创建一个重复周期的定时器并且执行先调用接口初始化
    // err = esp_timer_start_periodic(test_p_handle, 1000 * 1000);
    initialise_wifi();//初始化wifi


    //串口初始化
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };

    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    //uart_set_pin(EX_UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);//改变引脚
   
}

2.WiFi初始化,首先去读取NVS内部wifi_cfg信息,尝试去连接,如果能连接上:

?if (bits & WIFI_CONNECTED_BIT) ?/* WiFi连接成功事件 */

? ? {

? ? ? ? printf("connected to ap %s OK \n",wifi_ssid);

? ? ? ? vEventGroupDelete(wifi_event_group_handler); ? ?/* 删除WiFi连接事件标志组,WiFi连接成功后不再需要 */

? ? ? ? esp_timer_start_periodic(test_p_handle, 1000 * 1000);//

? ? ? ? xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);? ?//?

? ? }

指示灯闪烁,连接tcp服务器

如果连接不上:smartconfig_init_start(); ? /* 开启智能配网 */

static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());/* 初始化底层TCP/IP堆栈。在应用程序启动时,应该调用此函数一次。*/
   
    wifi_event_group_handler = xEventGroupCreate(); /* 创建一个事件标志组 */

    ESP_ERROR_CHECK(esp_event_loop_create_default());/* 创建默认事件循环,*/
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();/* 创建一个默认的WIFI-STA网络接口,如果初始化错误,此API将中止。*/
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); /* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的wifi配置参数结构体变量*/
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); /* 根据cfg参数初始化wifi连接所需要的资源 */
    /* 将事件处理程序注册到系统默认事件循环,分别是WiFi事件、IP地址事件及smartconfig事件 */
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

   nvs_handle wificfg_nvs_handler; /* 定义一个NVS操作句柄 */
    char wifi_ssid[32] = { 0 };     /* 定义一个数组用来存储ssid*/
    char wifi_passwd[64] = { 0 };   /* 定义一个数组用来存储passwd */
    size_t len;
    /* 打开一个NVS命名空间 */
    ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );
    len = sizeof(wifi_ssid);    /* 从NVS中获取ssid */
    ESP_ERROR_CHECK( nvs_get_str(wificfg_nvs_handler,"wifi_ssid",wifi_ssid,&len) );
    len = sizeof(wifi_passwd);      /* 从NVS中获取ssid */
    ESP_ERROR_CHECK( nvs_get_str(wificfg_nvs_handler,"wifi_passwd",wifi_passwd,&len) );
    ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
    nvs_close(wificfg_nvs_handler);                     /* 关闭 */
    /* 设置WiFi连接的ssid和password参数 */
    wifi_config_t wifi_config;
    bzero(&wifi_config, sizeof(wifi_config_t)); /* 将结构体数据清零 */
    memcpy(wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid));
    memcpy(wifi_config.sta.password, wifi_passwd, sizeof(wifi_config.sta.password));

    /* 设置WiFi的工作模式为 STA */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    /* 设置WiFi连接的参数,主要是ssid和password */
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    /* 启动WiFi连接 */
    ESP_ERROR_CHECK(esp_wifi_start());

    printf("wifi_init_sta finished. \n");

    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t bits;  /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */ 
    bits = xEventGroupWaitBits( wifi_event_group_handler,	        /* 需要等待的事件标志组的句柄 */
                                WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,	/* 需要等待的事件位 */
                                pdFALSE,    /* 为pdFALSE时,在退出此函数之前所设置的这些事件位不变,为pdFALSE则清零*/ 
                                pdFALSE,    /* 为pdFALSE时,设置的这些事件位任意一个置1就会返回,为pdFALSE则需全为1才返回 */
                                portMAX_DELAY);	                    /* 设置为最长阻塞等待时间,单位为时钟节拍 */

    /* 根据事件标志组等待函数的返回值获取WiFi连接状态 */
    if (bits & WIFI_CONNECTED_BIT)  /* WiFi连接成功事件 */
	{
        printf("connected to ap %s OK \n",wifi_ssid); 
        vEventGroupDelete(wifi_event_group_handler);    /* 删除WiFi连接事件标志组,WiFi连接成功后不再需要 */
        esp_timer_start_periodic(test_p_handle, 1000 * 1000);
        xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);    
    } 
	else if (bits & WIFI_FAIL_BIT) /* WiFi连接失败事件 */
	{
        printf("Failed to connect to ap %s. \n",wifi_ssid);
        smartconfig_init_start();   /* 开启智能配网 */        
    } 
	else 
    {
        printf("UNEXPECTED EVENT \n");  /* 没有等待到事件 */
        smartconfig_init_start();   /* 开启智能配网 */
    }
}

3。智能配网:智能配网有多种type:?

typedef enum {

? ? SC_TYPE_ESPTOUCH = 0, ? ? ? /**< protocol: ESPTouch */

? ? SC_TYPE_AIRKISS, ? ? ? ? ? ?/**< protocol: AirKiss */

? ? SC_TYPE_ESPTOUCH_AIRKISS, ? /**< protocol: ESPTouch and AirKiss */

? ? SC_TYPE_ESPTOUCH_V2, ? ? ? ?/**< protocol: ESPTouch v2*/

} smartconfig_type_t;

配网过程产生事件,并置位标志位:

uxBits = xEventGroupWaitBits(wifi_event_group_handler, WIFI_CONNECTED_BIT | SMART_CONFIG_BIT,? ? ? ? ?true, false, portMAX_DELAY);

通过标志位结束配网,并开启指示灯闪烁,连接tcp服务器。

static void smartconfig_init_start(void)
{
    /* 设置智能配网类型为 AirKiss */
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_AIRKISS) );
    /* 通过SMARTCONFIG_START_CONFIG_DEFAULT宏 来获取一个默认的smartconfig配置参数结构体变量*/
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    /* 开始智能配网 */
    ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    printf("smartconfig start ....... \n");

    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t uxBits;  /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */
    /* 等待事件标志组,退出前清除设置的事件标志,任意置1就会返回*/

    while(1){
        uxBits = xEventGroupWaitBits(wifi_event_group_handler, WIFI_CONNECTED_BIT | SMART_CONFIG_BIT, 
                                    true, false, portMAX_DELAY); 
        if(uxBits & WIFI_CONNECTED_BIT) 
        {
            printf("WiFi Connected to ap ok. \n");
            esp_smartconfig_stop(); /* 关闭智能配网 */
        }
        if(uxBits & SMART_CONFIG_BIT) 
        {
            printf("smartconfig over \n");
            esp_smartconfig_stop(); /* 关闭智能配网 */

            esp_timer_start_periodic(test_p_handle, 1000 * 1000); //指示灯闪烁
            xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL); //连接tcp服务

        }
    }   
}

4.配网事件??

event_base == WIFI_EVENT

WIFI_EVENT_STA_START:通过NVS内部配置信息进行sta连接路由器,连接不成功尝试十次。

event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP:ip事件获取ip并打印

event_base == SC_EVENT:智能配网事件,获取AP的ssid与passwd udp包,通过保存到NVS配置信息,尝试sta连接网络。

/* 系统事件循环处理函数 */
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
    static int retry_num = 0;           /* 记录wifi重连次数 */
    /* 系统事件为WiFi事件 */
    if (event_base == WIFI_EVENT) 
    {
        if(event_id == WIFI_EVENT_STA_START)    /* 事件id为STA开始 */
            esp_wifi_connect();
        else if (event_id == WIFI_EVENT_STA_DISCONNECTED) /* 事件id为失去STA连接 */ 
        {
            esp_wifi_connect();
            retry_num++;
            printf("retry to connect to the AP %d times. \n",retry_num);
            if (retry_num > 10)  /* WiFi重连次数大于10 */
            {
                /* 将WiFi连接事件标志组的WiFi连接失败事件位置1 */
                xEventGroupSetBits(wifi_event_group_handler, WIFI_FAIL_BIT);
            }
            /* 清除WiFi连接成功标志位 */
            xEventGroupClearBits(wifi_event_group_handler, WIFI_CONNECTED_BIT);
        }
    } 
    /* 系统事件为ip地址事件,且事件id为成功获取ip地址 */
    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; /* 获取IP地址信息*/
        printf("got ip:%d.%d.%d.%d \n" , IP2STR(&event->ip_info.ip));  /* 打印ip地址*/
        retry_num = 0;                                              /* WiFi重连次数清零 */
        /* 将WiFi连接事件标志组的WiFi连接成功事件位置1 */
        xEventGroupSetBits(wifi_event_group_handler, WIFI_CONNECTED_BIT);
    }
    /* 系统事件为智能配网事件 */
    else if (event_base == SC_EVENT)
    {
        if(event_id == SC_EVENT_SCAN_DONE )             /* 开始扫描智能配网设备端 */
            printf("Scan done\n");
        else if(event_id == SC_EVENT_FOUND_CHANNEL)     /* 得到了智能配网通道 */
            printf("Found channel \n");
        else if(event_id == SC_EVENT_GOT_SSID_PSWD)     /* 得到了智能配网设备提供的ssid和password */
        {
            printf("smartconfig got SSID and password\n");
            /* 获取智能配网设备端提供的数据信息 */
            smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
            /* 定义WiFi配置结构体和用了结收ssid和password的数组 */
            wifi_config_t wifi_config;
            char ssid[32] = { 0 };
            char password[64] = { 0 };

            bzero(&wifi_config, sizeof(wifi_config_t)); /* 将结构体数据清零 */
            /* 将智能配网设备发送来的WiFi的ssid、password及MAC地址复制到wifi_config */
            memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
            memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
            wifi_config.sta.bssid_set = evt->bssid_set;
            if (wifi_config.sta.bssid_set == true) {
                memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
            }
            
            /* 打印WiFi名称和密码 */
            memcpy(ssid, evt->ssid, sizeof(evt->ssid));
            memcpy(password, evt->password, sizeof(evt->password));
            printf("SSID:%s \n", ssid);
            printf("PASSWORD:%s \n", password);

            /* 将得到的WiFi名称和密码存入NVS*/
            nvs_handle wificfg_nvs_handler;
            ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );
            ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_ssid",ssid) );
            ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_passwd",password) );
            ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
            nvs_close(wificfg_nvs_handler);                     /* 关闭 */ 
            printf("smartconfig save wifi_cfg to NVS .\n");

            /* 根据得到的WiFi名称和密码连接WiFi*/
            ESP_ERROR_CHECK( esp_wifi_disconnect() );
            ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
            ESP_ERROR_CHECK( esp_wifi_connect() );
        }
        else if (event_id == SC_EVENT_SEND_ACK_DONE)    /* 智能配网成功,已经给智能配网设备发送应答*/
        {
            xEventGroupSetBits(wifi_event_group_handler, SMART_CONFIG_BIT);
        }
    }
}

5.tcp_client_task:使用的是IP_V4,绑定服务器IP端口号,建立socket来连接,

配置操作:

添加Kconfig.projbuild?

menu "Example Configuration"

    choice BLINK_LED
        prompt "Blink LED type"
        default BLINK_LED_GPIO if IDF_TARGET_ESP32
        default BLINK_LED_RMT
        help
            Defines the default peripheral for blink example

        config BLINK_LED_GPIO
            bool "GPIO"
        config BLINK_LED_RMT
            bool "RMT - Addressable LED"
    endchoice

    config BLINK_LED_RMT_CHANNEL
        depends on BLINK_LED_RMT
        int "RMT Channel"
        range 0 7
        default 0
        help
            Set the RMT peripheral channel.
            ESP32 RMT channel from 0 to 7
            ESP32-S2 RMT channel from 0 to 3
            ESP32-S3 RMT channel from 0 to 3
            ESP32-C3 RMT channel from 0 to 1

    config BLINK_GPIO
        int "Blink GPIO number"
        range 0 48
        default 8 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32H2
        default 18 if IDF_TARGET_ESP32S2
        default 48 if IDF_TARGET_ESP32S3
        default 5
        help
            GPIO number (IOxx) to blink on and off or the RMT signal for the addressable LED.
            Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.

    config BLINK_PERIOD
        int "Blink period in ms"
        range 10 3600000
        default 1000
        help
            Define the blinking period in milliseconds.

    choice EXAMPLE_IP_MODE
        prompt "IP Version"
        depends on EXAMPLE_SOCKET_IP_INPUT_STRING
        help
            Example can use either IPV4 or IPV6.

        config EXAMPLE_IPV4
            bool "IPV4"

        config EXAMPLE_IPV6
            bool "IPV6"

    endchoice

    config EXAMPLE_IPV4_ADDR
        string "IPV4 Address"
        default "192.168.0.165"
        depends on EXAMPLE_IPV4
        help
            The example will connect to this IPV4 address.

    config EXAMPLE_IPV6_ADDR
        string "IPV6 Address"
        default "FE80::30AD:E57B:C212:68AD"
        depends on EXAMPLE_IPV6
        help
            The example will connect to this IPV6 address.

    config EXAMPLE_PORT
        int "Port"
        range 0 65535
        default 3333
        help
            The remote port to which the client example will connect to.

    choice EXAMPLE_SOCKET_IP_INPUT
        prompt "Socket example source"
        default EXAMPLE_SOCKET_IP_INPUT_STRING
        help
            Selects the input source of the IP used in the example.

        config EXAMPLE_SOCKET_IP_INPUT_STRING
            bool "From string"

        config EXAMPLE_SOCKET_IP_INPUT_STDIN
            bool "From stdin"
    endchoice
        

endmenu

?打开配置选Example Configuration:

重置 修改后保存 :

?接收到服务器消息,通过串口转发

? int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); ? ? ? ? ?

? ? ? ? ? ? if (len < 0) {

? ? ? ? ? ? ? ? ESP_LOGE(TAG, "recv failed: errno %d", errno); // Error occurred during receiving

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? ? ? // Data received

? ? ? ? ? ? else {

? ? ? ? ? ? ? ? rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string

? ? ? ? ? ? ? ? sendData(TAG, rx_buffer);//转发给串口

? ? ? ? ? ? }

//tcp通讯
static void tcp_client_task(void *pvParameters)
{
    char rx_buffer[128];
    char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    while (1) {
        #if defined(CONFIG_EXAMPLE_IPV4)
                struct sockaddr_in dest_addr;
                dest_addr.sin_addr.s_addr = inet_addr(host_ip);
                dest_addr.sin_family = AF_INET;
                dest_addr.sin_port = htons(PORT);
                addr_family = AF_INET;
                ip_protocol = IPPROTO_IP;
        #elif defined(CONFIG_EXAMPLE_IPV6)
                struct sockaddr_in6 dest_addr = { 0 };
                inet6_aton(host_ip, &dest_addr.sin6_addr);
                dest_addr.sin6_family = AF_INET6;
                dest_addr.sin6_port = htons(PORT);
                dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
                addr_family = AF_INET6;
                ip_protocol = IPPROTO_IPV6;
        #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
                struct sockaddr_in6 dest_addr = { 0 };
                ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr));
        #endif
        sock =  socket(addr_family, SOCK_STREAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);

        int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
        if (err != 0) {
            ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Successfully connected");

        while (1) {
          
            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);           
            if (len < 0) {
                ESP_LOGE(TAG, "recv failed: errno %d", errno); // Error occurred during receiving
                break;
            }
            // Data received
            else {
                rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string

                sendData(TAG, rx_buffer);//转发给串口

                // ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
                // ESP_LOGI(TAG, "%s", rx_buffer);
            }

            vTaskDelay(2000 / portTICK_PERIOD_MS);
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}

5.串口事件 接收到串口消息转发给tcp服务端

static void rx_task(void *arg)
{
    static const char *RX_TASK_TAG = "RX_TASK";
    esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
    uint8_t* data = (uint8_t*) malloc(BUF_SIZE+1);
    while (1) {
        const int rxBytes = uart_read_bytes(EX_UART_NUM, data, BUF_SIZE, 1000 / portTICK_RATE_MS);
        if (rxBytes > 0) {
            data[rxBytes] = 0;

            //转发给tcp服务
            int err = send(sock, (char *)data, rxBytes+1, 0);
            if (err < 0) {
                ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                break;
            }

            // ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
            // ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
        }
    }
    free(data);
}

最后,贴上完整代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led_strip.h"
#include "driver/uart.h"
#include "sdkconfig.h"
#include "esp_timer.h"
#include "esp_spi_flash.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "string.h"


#include <sys/param.h>
#include "protocol_examples_common.h"
#include "addr_from_stdin.h"
#include "lwip/err.h"
#include "lwip/sockets.h"

static const char *TAG = "care_robot";
#define BLINK_GPIO CONFIG_BLINK_GPIO

static uint8_t s_led_state = 0;
static led_strip_t *pStrip_a;

#define EX_UART_NUM UART_NUM_0    //串口号
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;


/* 宏定义WiFi更新标识码、WiFi名称和密码 */
#define MY_WIFI_UPDATE  4096                /* 对数值进行修改表示更新NVS的WiFi名称和密码*/
#define MY_WIFI_SSID    "Singhu_test"
#define MY_WIFI_PASSWD  "123123123DESK"
static EventGroupHandle_t wifi_event_group_handler;
/* 宏定义WiFi连接事件标志位、连接失败标志位及智能配网标志位 */
#define WIFI_CONNECTED_BIT  BIT0
#define WIFI_FAIL_BIT       BIT1
#define SMART_CONFIG_BIT    BIT2

int sock=0;
#if defined(CONFIG_EXAMPLE_IPV4)
#define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR
#elif defined(CONFIG_EXAMPLE_IPV6)
#define HOST_IP_ADDR CONFIG_EXAMPLE_IPV6_ADDR
#else
#define HOST_IP_ADDR ""
#endif

#define PORT CONFIG_EXAMPLE_PORT


float arr1[8][3] = { {0.5, 0.5, 0.5}, {0, 0, 1},{0, 1, 0},
    {0, 1, 1},{1, 0, 0},{1, 0, 1},{1, 1, 0}, {1, 1, 1}};//七彩效果
static void blink_led(void)
{
    /* If the addressable LED is enabled */
    static int index=0;   
    if (s_led_state) { 
        index=(index+1)%8;
        /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
        pStrip_a->set_pixel(pStrip_a, 0, arr1[index][0]*255, arr1[index][1]*255, arr1[index][2]*255);
        /* Refresh the strip to send data */
        pStrip_a->refresh(pStrip_a, 100);
    } else {
        /* Set all LED off to clear all pixels */
        pStrip_a->clear(pStrip_a, 50);
    }
}

static void configure_led(void) //led初始化
{
    ESP_LOGI(TAG, "Example configured to blink addressable LED!");
    /* LED strip initialization with the GPIO and pixels number*/
    pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, BLINK_GPIO, 1);
    /* Set all LED off to clear all pixels */
    pStrip_a->clear(pStrip_a, 50);
}
void test_timer_periodic_cb(void *arg) ;// 定义定时器句柄

esp_timer_handle_t test_p_handle = 0;// 定义一个周期重复运行的定时器结构体

esp_timer_create_args_t test_periodic_arg = 
{ 
    .callback = &test_timer_periodic_cb, // 设置回调函数
    .arg = NULL,                         // 不携带参数
    .name = "xjhPeriodicTimer"          // 定时器名字
};


void test_timer_periodic_cb(void *arg) //定时器回调函数
{	
    blink_led();   
    s_led_state = !s_led_state;
    //int64_t tick = esp_timer_get_time();
  
}

int sendData(const char* logName, const char* data)
{
    const int len = strlen(data);
    const int txBytes = uart_write_bytes(EX_UART_NUM, data, len);
    ESP_LOGI(logName, "Wrote %d bytes", txBytes);
    return txBytes;
}

static void rx_task(void *arg)
{
    static const char *RX_TASK_TAG = "RX_TASK";
    esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
    uint8_t* data = (uint8_t*) malloc(BUF_SIZE+1);
    while (1) {
        const int rxBytes = uart_read_bytes(EX_UART_NUM, data, BUF_SIZE, 1000 / portTICK_RATE_MS);
        if (rxBytes > 0) {
            data[rxBytes] = 0;

            //转发给tcp服务
            int err = send(sock, (char *)data, rxBytes+1, 0);
            if (err < 0) {
                ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                break;
            }

            // ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
            // ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
        }
    }
    free(data);
}

//tcp通讯
static void tcp_client_task(void *pvParameters)
{
    char rx_buffer[128];
    char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    while (1) {
        #if defined(CONFIG_EXAMPLE_IPV4)
                struct sockaddr_in dest_addr;
                dest_addr.sin_addr.s_addr = inet_addr(host_ip);
                dest_addr.sin_family = AF_INET;
                dest_addr.sin_port = htons(PORT);
                addr_family = AF_INET;
                ip_protocol = IPPROTO_IP;
        #elif defined(CONFIG_EXAMPLE_IPV6)
                struct sockaddr_in6 dest_addr = { 0 };
                inet6_aton(host_ip, &dest_addr.sin6_addr);
                dest_addr.sin6_family = AF_INET6;
                dest_addr.sin6_port = htons(PORT);
                dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
                addr_family = AF_INET6;
                ip_protocol = IPPROTO_IPV6;
        #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
                struct sockaddr_in6 dest_addr = { 0 };
                ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr));
        #endif
        sock =  socket(addr_family, SOCK_STREAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);

        int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
        if (err != 0) {
            ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Successfully connected");

        while (1) {
          
            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);           
            if (len < 0) {
                ESP_LOGE(TAG, "recv failed: errno %d", errno); // Error occurred during receiving
                break;
            }
            // Data received
            else {
                rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                sendData(TAG, rx_buffer);//转发给串口
                // ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
                // ESP_LOGI(TAG, "%s", rx_buffer);
            }

            vTaskDelay(2000 / portTICK_PERIOD_MS);
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}
/* 系统事件循环处理函数 */
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{
    static int retry_num = 0;           /* 记录wifi重连次数 */
    /* 系统事件为WiFi事件 */
    if (event_base == WIFI_EVENT) 
    {
        if(event_id == WIFI_EVENT_STA_START)    /* 事件id为STA开始 */
            esp_wifi_connect();
        else if (event_id == WIFI_EVENT_STA_DISCONNECTED) /* 事件id为失去STA连接 */ 
        {
            esp_wifi_connect();
            retry_num++;
            printf("retry to connect to the AP %d times. \n",retry_num);
            if (retry_num > 10)  /* WiFi重连次数大于10 */
            {
                /* 将WiFi连接事件标志组的WiFi连接失败事件位置1 */
                xEventGroupSetBits(wifi_event_group_handler, WIFI_FAIL_BIT);
            }
            /* 清除WiFi连接成功标志位 */
            xEventGroupClearBits(wifi_event_group_handler, WIFI_CONNECTED_BIT);
        }
    } 
    /* 系统事件为ip地址事件,且事件id为成功获取ip地址 */
    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; /* 获取IP地址信息*/
        printf("got ip:%d.%d.%d.%d \n" , IP2STR(&event->ip_info.ip));  /* 打印ip地址*/
        retry_num = 0;                                              /* WiFi重连次数清零 */
        /* 将WiFi连接事件标志组的WiFi连接成功事件位置1 */
        xEventGroupSetBits(wifi_event_group_handler, WIFI_CONNECTED_BIT);
    }
    /* 系统事件为智能配网事件 */
    else if (event_base == SC_EVENT)
    {
        if(event_id == SC_EVENT_SCAN_DONE )             /* 开始扫描智能配网设备端 */
            printf("Scan done\n");
        else if(event_id == SC_EVENT_FOUND_CHANNEL)     /* 得到了智能配网通道 */
            printf("Found channel \n");
        else if(event_id == SC_EVENT_GOT_SSID_PSWD)     /* 得到了智能配网设备提供的ssid和password */
        {
            printf("smartconfig got SSID and password\n");
            /* 获取智能配网设备端提供的数据信息 */
            smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
            /* 定义WiFi配置结构体和用了结收ssid和password的数组 */
            wifi_config_t wifi_config;
            char ssid[32] = { 0 };
            char password[64] = { 0 };

            bzero(&wifi_config, sizeof(wifi_config_t)); /* 将结构体数据清零 */
            /* 将智能配网设备发送来的WiFi的ssid、password及MAC地址复制到wifi_config */
            memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
            memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
            wifi_config.sta.bssid_set = evt->bssid_set;
            if (wifi_config.sta.bssid_set == true) {
                memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
            }
            
            /* 打印WiFi名称和密码 */
            memcpy(ssid, evt->ssid, sizeof(evt->ssid));
            memcpy(password, evt->password, sizeof(evt->password));
            printf("SSID:%s \n", ssid);
            printf("PASSWORD:%s \n", password);

            /* 将得到的WiFi名称和密码存入NVS*/
            nvs_handle wificfg_nvs_handler;
            ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );
            ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_ssid",ssid) );
            ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_passwd",password) );
            ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
            nvs_close(wificfg_nvs_handler);                     /* 关闭 */ 
            printf("smartconfig save wifi_cfg to NVS .\n");

            /* 根据得到的WiFi名称和密码连接WiFi*/
            ESP_ERROR_CHECK( esp_wifi_disconnect() );
            ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
            ESP_ERROR_CHECK( esp_wifi_connect() );
        }
        else if (event_id == SC_EVENT_SEND_ACK_DONE)    /* 智能配网成功,已经给智能配网设备发送应答*/
        {
            xEventGroupSetBits(wifi_event_group_handler, SMART_CONFIG_BIT);
        }
    }
}

static void smartconfig_init_start(void)
{
    /* 设置智能配网类型为 AirKiss */
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_AIRKISS) );
    /* 通过SMARTCONFIG_START_CONFIG_DEFAULT宏 来获取一个默认的smartconfig配置参数结构体变量*/
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    /* 开始智能配网 */
    ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    printf("smartconfig start ....... \n");

    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t uxBits;  /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */
    /* 等待事件标志组,退出前清除设置的事件标志,任意置1就会返回*/

    while(1){
        uxBits = xEventGroupWaitBits(wifi_event_group_handler, WIFI_CONNECTED_BIT | SMART_CONFIG_BIT, 
                                    true, false, portMAX_DELAY); 
        if(uxBits & WIFI_CONNECTED_BIT) 
        {
            printf("WiFi Connected to ap ok. \n");
            esp_smartconfig_stop(); /* 关闭智能配网 */
        }
        if(uxBits & SMART_CONFIG_BIT) 
        {
            printf("smartconfig over \n");
            esp_smartconfig_stop(); /* 关闭智能配网 */

            esp_timer_start_periodic(test_p_handle, 1000 * 1000); //指示灯闪烁
            xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL); //连接tcp服务

        }
    }   
}
static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());/* 初始化底层TCP/IP堆栈。在应用程序启动时,应该调用此函数一次。*/
   
    wifi_event_group_handler = xEventGroupCreate(); /* 创建一个事件标志组 */

    ESP_ERROR_CHECK(esp_event_loop_create_default());/* 创建默认事件循环,*/
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();/* 创建一个默认的WIFI-STA网络接口,如果初始化错误,此API将中止。*/
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); /* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的wifi配置参数结构体变量*/
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); /* 根据cfg参数初始化wifi连接所需要的资源 */
    /* 将事件处理程序注册到系统默认事件循环,分别是WiFi事件、IP地址事件及smartconfig事件 */
    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

   nvs_handle wificfg_nvs_handler; /* 定义一个NVS操作句柄 */
    char wifi_ssid[32] = { 0 };     /* 定义一个数组用来存储ssid*/
    char wifi_passwd[64] = { 0 };   /* 定义一个数组用来存储passwd */
    size_t len;
    /* 打开一个NVS命名空间 */
    ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );
    len = sizeof(wifi_ssid);    /* 从NVS中获取ssid */
    ESP_ERROR_CHECK( nvs_get_str(wificfg_nvs_handler,"wifi_ssid",wifi_ssid,&len) );
    len = sizeof(wifi_passwd);      /* 从NVS中获取ssid */
    ESP_ERROR_CHECK( nvs_get_str(wificfg_nvs_handler,"wifi_passwd",wifi_passwd,&len) );
    ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
    nvs_close(wificfg_nvs_handler);                     /* 关闭 */
    /* 设置WiFi连接的ssid和password参数 */
    wifi_config_t wifi_config;
    bzero(&wifi_config, sizeof(wifi_config_t)); /* 将结构体数据清零 */
    memcpy(wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid));
    memcpy(wifi_config.sta.password, wifi_passwd, sizeof(wifi_config.sta.password));

    /* 设置WiFi的工作模式为 STA */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    /* 设置WiFi连接的参数,主要是ssid和password */
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    /* 启动WiFi连接 */
    ESP_ERROR_CHECK(esp_wifi_start());

    printf("wifi_init_sta finished. \n");

    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t bits;  /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */ 
    bits = xEventGroupWaitBits( wifi_event_group_handler,	        /* 需要等待的事件标志组的句柄 */
                                WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,	/* 需要等待的事件位 */
                                pdFALSE,    /* 为pdFALSE时,在退出此函数之前所设置的这些事件位不变,为pdFALSE则清零*/ 
                                pdFALSE,    /* 为pdFALSE时,设置的这些事件位任意一个置1就会返回,为pdFALSE则需全为1才返回 */
                                portMAX_DELAY);	                    /* 设置为最长阻塞等待时间,单位为时钟节拍 */

    /* 根据事件标志组等待函数的返回值获取WiFi连接状态 */
    if (bits & WIFI_CONNECTED_BIT)  /* WiFi连接成功事件 */
	{
        printf("connected to ap %s OK \n",wifi_ssid); 
        vEventGroupDelete(wifi_event_group_handler);    /* 删除WiFi连接事件标志组,WiFi连接成功后不再需要 */
        esp_timer_start_periodic(test_p_handle, 1000 * 1000);
        xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);    
    } 
	else if (bits & WIFI_FAIL_BIT) /* WiFi连接失败事件 */
	{
        printf("Failed to connect to ap %s. \n",wifi_ssid);
        smartconfig_init_start();   /* 开启智能配网 */        
    } 
	else 
    {
        printf("UNEXPECTED EVENT \n");  /* 没有等待到事件 */
        smartconfig_init_start();   /* 开启智能配网 */
    }
}

static void app_init(void)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);
    /* 初始化非易失性存储库 (NVS) */
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        /* NVS分区被截断,需要删除,然后重新初始化NVS */
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK( err );
     /* 定义一个NVS操作句柄 */
    nvs_handle wificfg_nvs_handler;
    /* 打开一个NVS命名空间 */
    ESP_ERROR_CHECK( nvs_open("WiFi_cfg", NVS_READWRITE, &wificfg_nvs_handler) );

    uint32_t wifi_update = 0;
    err = nvs_get_u32(wificfg_nvs_handler,"wifi_update",&wifi_update);
    if(MY_WIFI_UPDATE == wifi_update )  //最开始需要----是否更新wifi
        printf("wifi_cfg needn't to update. \n");
    else
    {
        printf("wifi_cfg update now... \n");
        ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_ssid",MY_WIFI_SSID) );
        ESP_ERROR_CHECK( nvs_set_str(wificfg_nvs_handler,"wifi_passwd",MY_WIFI_PASSWD) ); 
        ESP_ERROR_CHECK( nvs_set_u32(wificfg_nvs_handler,"wifi_update",MY_WIFI_UPDATE) );
        printf("wifi_cfg update ok. \n");
    }
    ESP_ERROR_CHECK( nvs_commit(wificfg_nvs_handler) ); /* 提交 */
    nvs_close(wificfg_nvs_handler);                     /* 关闭 */
    printf("ESP_WIFI_MODE_STA \n");
    configure_led();  //led先初始化    
    esp_timer_init(); //使用定时器API函数, 
    err = esp_timer_create(&test_periodic_arg, &test_p_handle);  // 开始创建一个重复周期的定时器并且执行先调用接口初始化
    // err = esp_timer_start_periodic(test_p_handle, 1000 * 1000);
    initialise_wifi();//初始化wifi


    //串口初始化
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };

    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    //uart_set_pin(EX_UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);//改变引脚
   
}

void app_main(void)
{
    app_init();//外设初始化     
    xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL);//串口接收任务
    // vTaskDelay(1000 / portTICK_PERIOD_MS);
}

编译:Makefile与CMakelist让添加外部依赖

?收发结果:

?

?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:27:49  更:2022-09-24 21:28:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:27:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码