ESP32开发之路(7)---ESP32作为TCP客户端连接到局域网的PC机

SP32开发之路(7)—ESP32作为TCP客户端连接到局域网的PC机

本次开发是在Ubuntu下的,使用的模块是GOOUUU-ESP32,使用VSCode编辑项目。代码使用来自esp-idf的例程。

一、代码准备

从上个工程:ESP32开发之路(6)—连接到WiFi然后保存ssid和password,将其中的代码封装成一个wifi_connect_init()函数,新建app_wifi.c文件,在app_main.c代码的基础上,将app_main()函数修改为wifi_connect_init()函数:

void wifi_connect_init(void)
{
    /* 定义一个gpio配置结构体 初始化LED */
    gpio_config_t gpio_config_structure;

    /* 初始化gpio配置结构体*/
    gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
    gpio_config_structure.mode = GPIO_MODE_OUTPUT;              /* 输出模式 */
    gpio_config_structure.pull_up_en = 0;                       /* 不上拉 */
    gpio_config_structure.pull_down_en = 0;                     /* 不下拉 */
    gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE;    /* 禁止中断 */ 

    /* 根据设定参数初始化并使能 */  
	gpio_config(&gpio_config_structure);
    /* 默认熄灭LED */
    gpio_set_level(GPIO_LED_NUM, 0);        /* 熄灭 */

    /* 初始化非易失性存储库 (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 )
        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");
    /* 初始化为wifi STA模式连接 */
    wifi_init_sta();         
}

二、TCP连接

新建一个任务,作为tcp_client连接任务

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

使用socket()函数打开一个socket文件,并返回其socket描述符

    /* 打开一个socket套接字 */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

如果打开成功,则连接到服务端

	if (-1 == sockfd)
	{
		printf("socket open failure !!! \n");
		return -1;
	}
    else
    {
        struct sockaddr_in seraddr = {0};
        seraddr.sin_family = AF_INET;		                    // 设置地址族为IPv4
	    seraddr.sin_port = htons(12341);	                    // 设置地址的端口号信息
	    seraddr.sin_addr.s_addr = inet_addr("192.168.1.107");	// 设置IP地址
	    ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
        if(ret < 0)
            printf("connect to server failure !!! \n");
        else
        {
            printf("connect success, ret = %d.\n", ret);
        }          
        close(sockfd);
    }

在PC上打开网络调试助手,新建一个服务端,可以看到,连接成功。
这里要特别注意,要把windows10的防火墙关了,否则连接不上,重要的事说三编!!!
这里要特别注意,要把windows10的防火墙关了,否则连接不上,重要的事说三编!!!
这里要特别注意,要把windows10的防火墙关了,否则连接不上,重要的事说三编!!!
我因为这个防火墙的原因,折腾了一天才发现这个问题,说起来都是泪。。。
在这里插入图片描述
在这里插入图片描述
连接成功后我们每隔2s向服务端发送一条消息,发送10次后关闭;

	int cnt = 10;
	while(cnt--)
	{
	    ret = send(sockfd, "I am ESP32.", strlen("I am ESP32."), 0);
	    if(ret < 0)
	        printf("send err. \n");
	    else
	        printf("send ok. \n");
	    vTaskDelay(2000 / portTICK_PERIOD_MS);   /* 延时2000ms*/
	}  

烧录下载后,可以看到,服务端收到消息,ESP32每隔2s发送消息成功
在这里插入图片描述
在这里插入图片描述

三、代码

最后,贴上app_wifi.c和app_main.c的代码
app_wifi.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_wifi.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "esp_smartconfig.h"

#define GPIO_LED_NUM 2                      /* LED引脚编号 */

/* 宏定义WiFi更新标识码、WiFi名称和密码 */
#define MY_WIFI_UPDATE  4096                /* 对数值进行修改表示更新NVS的WiFi名称和密码*/
#define MY_WIFI_SSID    "WiFi-William"
#define MY_WIFI_PASSWD  "passwd-william"

/* 宏定义WiFi连接事件标志位、连接失败标志位及智能配网标志位 */
#define WIFI_CONNECTED_BIT  BIT0
#define WIFI_FAIL_BIT       BIT1
#define SMART_CONFIG_BIT    BIT2

/* 定义一个WiFi连接事件标志组句柄 */
static EventGroupHandle_t wifi_event_group_handler;

static void wifi_init_sta(void);

void wifi_connect_init(void)
{
    /* 定义一个gpio配置结构体 初始化LED */
    gpio_config_t gpio_config_structure;

    /* 初始化gpio配置结构体*/
    gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
    gpio_config_structure.mode = GPIO_MODE_OUTPUT;              /* 输出模式 */
    gpio_config_structure.pull_up_en = 0;                       /* 不上拉 */
    gpio_config_structure.pull_down_en = 0;                     /* 不下拉 */
    gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE;    /* 禁止中断 */ 

    /* 根据设定参数初始化并使能 */  
	gpio_config(&gpio_config_structure);
    /* 默认熄灭LED */
    gpio_set_level(GPIO_LED_NUM, 0);        /* 熄灭 */

    /* 初始化非易失性存储库 (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 )
        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");
    /* 初始化为wifi STA模式连接 */
    wifi_init_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);
        }
    }
}

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");
    /* 开启智能配网后让LED亮起 */
    gpio_set_level(GPIO_LED_NUM, 1);        /* 点亮 */

    /* 使用事件标志组等待连接建立(WIFI_CONNECTED_BIT)或连接失败(WIFI_FAIL_BIT)事件 */
    EventBits_t uxBits;  /* 定义一个事件位变量来接收事件标志组等待函数的返回值 */
    /* 等待事件标志组,退出前清除设置的事件标志,任意置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");       
    }
    if(uxBits & SMART_CONFIG_BIT) 
    {
        printf("smartconfig over \n");
    }
    esp_smartconfig_stop(); /* 关闭智能配网 */
    /* 将smartconfig事件从系统默认事件循环中卸载 */
    ESP_ERROR_CHECK(esp_event_handler_unregister(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler));
}


static void wifi_init_sta(void)
{
    /* 创建一个事件标志组 */
    wifi_event_group_handler = xEventGroupCreate();

    /* 初始化底层TCP/IP堆栈。在应用程序启动时,应该调用此函数一次。*/
    ESP_ERROR_CHECK(esp_netif_init());

    /* 创建默认事件循环,*/
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* 创建一个默认的WIFI-STA网络接口,如果初始化错误,此API将中止。*/
    esp_netif_create_default_wifi_sta();				

    /* 使用WIFI_INIT_CONFIG_DEFAULT() 来获取一个默认的wifi配置参数结构体变量*/
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    /* 根据cfg参数初始化wifi连接所需要的资源 */
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

	/* 将事件处理程序注册到系统默认事件循环,分别是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连接成功后不再需要 */
    } 
	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();   /* 开启智能配网 */
    }
}

app_main.c

#include <string.h>
#include <sys/param.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 "esp_netif.h"
#include "driver/gpio.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>

#define GPIO_LED_NUM 2                      /* LED引脚编号 */

/* wifi连接函数,位于app_wifi.c,阻塞状态 */
void wifi_connect_init(void);

#define HOST_IP_ADDR "192.168.0.102"

static void tcp_client_task(void *pvParameters)
{
    int sockfd = -1;    /* 定义一个socket描述符,用来接收打开的socket */
    int ret = -1;
    /* 打开一个socket套接字 */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (-1 == sockfd)
	{
		printf("socket open failure !!! \n");
		return ;
	}
    else
    {
        struct sockaddr_in seraddr = {0};
        seraddr.sin_family = AF_INET;		                    /* 设置地址族为IPv4 */
	    seraddr.sin_port = htons(12341);	                    /* 设置地址的端口号信息 */
	    seraddr.sin_addr.s_addr = inet_addr("192.168.0.107");	/* 设置IP地址 */
	    ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
        if(ret < 0)
            printf("connect to server failure !!! ret = %d \n",ret);
        else
        {
            printf("connect success.\n");
            int cnt = 10;
            while(cnt--)
            {
                ret = send(sockfd, "I am ESP32.", strlen("I am ESP32."), 0);
                if(ret < 0)
                    printf("send err. \n");
                else
                    printf("send ok. \n");
                vTaskDelay(2000 / portTICK_PERIOD_MS);   /* 延时2000ms*/
            }      
        }          
        close(sockfd);
    }
    
    vTaskDelete(NULL);
}


void app_main(void)
{
    /* 打印Hello world! */
    printf("Hello world!\n");

    wifi_connect_init();

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

    while(1)
    {
        gpio_set_level(GPIO_LED_NUM, 0);        /* 熄灭 */
        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时500ms*/
        gpio_set_level(GPIO_LED_NUM, 1);        /* 点亮 */
        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时500ms*/
    }
}

### 关于 ESP8266 Wi-Fi 模块的使用方法 #### 1. 硬件准备 为了开始学习和使用 ESP8266 Wi-Fi 模块,需要准备好以下硬件设备: - **ESP8266 Wi-Fi 模块**:可以选择型号如 esp8266-01 或其他版本[^1]。 - **USB 转 TTL 设备**:用于将计算与 ESP8266 模块连接起来以便进行调试和配置。 - **PC 电脑**:作为主运行终端软件并发送 AT 命令给模块。 #### 2. 配置环境 在实际操作前,需安装必要的驱动程序以及设置好串口工具。以下是具体步骤: - 安装 USB-TTL 芯片对应的驱动程序(如果尚未自动识别)。 - 下载并打开一个支持串口通信的应用程序,比如 `PuTTY`、`SecureCRT` 或者专用的串口调试助手[^3]。 #### 3. 初始化与基本命令测试 当一切就绪之后,可以通过向 ESP8266 发送简单的 AT 指令来进行初步验证其工作状态是否正常。例如输入 `AT` 应返回 OK 表明通讯成功。 #### 4. 工作模式设定 ESP8266 支持三种主要的工作模式——Station (STA),Access Point (AP), 和 Station+Access Point(STA+AP)[^3]: - 在 STA 模式下, 设备会尝试接入现有的 WiFi 网络从而成为客户端之一; - AP 则允许它创建自己的热点供其它装置连入; - 同时启用两者即进入混合模式。 对于远程控制应用来说通常会选择 STA 方式让目标节点加入家庭/办公室局域网之中进而访问广域网资源。 #### 5. 实现功能案例分析 假设我们要完成这样一个场景需求:“利用 STM32 微控制器配合 ESP8266 构建一套基于 Internet 的监控系统”,那么大致流程如下所示: ##### a) 数据采集端设计思路 微处理器负责读取传感器数值并通过 UART 将这些信息传递至联网单元(此处指代的就是我们的主角 - ESP8266) ```c #include "stm32f1xx_hal.h" UART_HandleTypeDef huart1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); char buffer[]="Hello World!"; while (1){ /* Send message */ HAL_UART_Transmit(&huart1,(uint8_t*)buffer,strlen(buffer),HAL_MAX_DELAY); // Simulate delay between transmissions. HAL_Delay(1000); } } /* Additional functions omitted here...*/ ``` 上述代码片段展示了如何从 STM32 中通过 USART 接口发出字符串消息到相连的目标设备上去[^2]. ##### b) 网络交互部分逻辑构建 另一方面,在接收侧也就是 ESP8266 上面,则要编写相应的脚本来处理来自本地MCU的数据包并将它们上传云端或者转发指定地址处等待响应的结果回来再反馈回去形成闭环控制系统: ```lua function send_data(data) conn=net.createConnection(net.TCP, 0) conn:on("connection", function(conn, payload) end ) conn:connect(80,"your.server.ip.address") -- Replace with actual server IP address conn:send("GET /log?data="..data.." HTTP/1.1\r\nHost: yourdomain.com\r\nConnection: close\r\nAccept: */*\r\nUser-Agent: Mozilla/4.0 (compatible; Win32)\r\n\r\n") end pin = 3 gpio.mode(pin,gpio.INPUT) tmr.alarm(1, 1000 , 1,function() local status=gpio.read(pin) if(status==1)then send_data('ON') elseif(status==0) then send_data('OFF') end end) ``` 此 Lua 编写的函数监听 GPIO 输入变化情况一旦检测到电平翻转就会触发事件通知服务器当前开关的状态改变状况。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值