此代码为接收STM32的数据然后直接转发到网络调试助手,当有设备连接到esp32软件热点时会通过串口发送字符'a'给STM32,当有设备断开连接时会通过串口发送字符'b',
ESP32的TX:GPIO4, RX:GPIO5
ESP32作为TCP服务器地址为192.168.4.1 监听端口为3333
cpp
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h" //lwip错误代码
#include "lwip/sys.h"
#include "sdkconfig.h"
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include "esp_netif.h"
#include <sys/param.h>
#include "esp_system.h"
#include "lwip/sockets.h"
#include <lwip/netdb.h>
#include "driver/uart.h"
#include "driver/gpio.h"
#define EXAMPLE_ESP_WIFI_SSID "laotie666" // 热点名
#define EXAMPLE_ESP_WIFI_PASS "12345678" // 热点密码
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL // 信道(来自menuconfig)
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN // 最大连接数(来自menuconfig)
#define CONFIG_EXAMPLE_IPV4 1 // 启用IPv4
#define PORT 3333 // 服务器监听的端口号
#define KEEPALIVE_IDLE 5 // TCP Keepalive空闲时间(秒)
#define KEEPALIVE_INTERVAL 5 // Keepalive探测间隔(秒)
#define KEEPALIVE_COUNT 3 // 超时前的探测次数
#define EX_UART_NUM UART_NUM_1 // 使用UART1端口
#define BUF_SIZE (1024) // UART缓冲区大小
#define RD_BUF_SIZE (BUF_SIZE) // 读取缓冲区大小
/*函数声明*/
uint8_t mac[6];
// 日志标签
static const char *TAG = "wifi softAP";
static const char *TAG_ZH = "Zhanghui:";
static uint8_t uart_buffer1[1024];
uint8_t uart_data;
static QueueHandle_t uart0_queue;
// 当建立tcp连接之后才会进行串口接收震动数据
uint8_t uart_re_en_flag = 0;
// TCP发送错误标志
int tcp_send_error_flag;
// WiFi事件处理函数
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED)
{
// 有设备连接到我们的软件热点时会触发这个事件
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
ESP_LOGI(TAG, "station " MACSTR " join, AID=%d",
MAC2STR(event->mac), event->aid);
// 当有设备连接到esp32软件热点时会通过串口发送字符'a'
uart_data = 'a';
uart_write_bytes(EX_UART_NUM, &uart_data, 1);
}
else if (event_id == WIFI_EVENT_AP_STADISCONNECTED)
{
// 断开连接时
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
// 打印断开设备的信息,如ip
ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d, reason=%d",
MAC2STR(event->mac), event->aid, event->reason);
// 当有设备断开连接时会通过串口发送字符'b'
uart_data = 'b';
uart_write_bytes(EX_UART_NUM, &uart_data, 1);
}
}
// 初始化SoftAP模式
void wifi_init_softap(void)
{
// 通过调用esp_netif_init()来启动LWIPtask
ESP_ERROR_CHECK(esp_netif_init()); // 初始化底层TCP/IP栈
// 通过esp_event_loop_create_default()来创建启动事件task--eventtask
ESP_ERROR_CHECK(esp_event_loop_create_default()); // 创建默认事件循环
esp_netif_create_default_wifi_ap(); // 创建默认WIFI AP网络接口
// 初始化WIFI驱动配置为默认值
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
// esp_wifi_init() 初始化WIFI driver
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// 4.对我们所需处理的一些事件注册了一个回调函数wifi_event_handler
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
// 配置driver
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID, // 热点的名字
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID), // SSID长度
.channel = EXAMPLE_ESP_WIFI_CHANNEL, // 无线信道 WiFi信号工作在2.4GHz或5GHz频段(取决于设备支持),这些频段被划分为多个子频段,每个子频段称为一个信道。
.password = EXAMPLE_ESP_WIFI_PASS, // 热点的密码
.max_connection = EXAMPLE_MAX_STA_CONN, // 热点的最大连接数目
#ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT // 用于根据系统配置决定使用哪种 Wi-Fi 安全协议
.authmode = WIFI_AUTH_WPA3_PSK, // 授权的模式,登录的加密模式 // WPA3加密模式
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH, // SAE密码交换方法
#else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */
.authmode = WIFI_AUTH_WPA2_PSK, // 默认WPA2加密
#endif
.pmf_cfg = {
// 受保护的管理帧配置
.required = true, // 要求PMF
},
},
};
// 如果密码为空则使用开放模式
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0)
{
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
// 使用esp_wifi_set_mode()对driver进行配置
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); // 设置WIFI为AP模式
// 应用AP配置
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
// 启动driver
ESP_ERROR_CHECK(esp_wifi_start()); // 启动WIFI
// 打印热点配置信息
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
/*
wifi driver被启动之后, 会发送WIFI_EVENT_AP_START这个事件到event Task中,
如果有处理这个事件的回调函数,就会再这个回调函数中进行处理;
如果有设备进行连接,就会发送WIFI_EVENT_AP_STACONNECTED这个事件到event Task,
之后再wifi_event_handler中进行处理(实例代码中只是打印了相应的信息)
如果有断开连接的事件WIFI_EVENT_AP_STADISCONNECTED,也会发送到event Task,
event Task调用wifi_event_handler进行处理
*/
// 数据转发函数
static void do_retransmit(const int sock)
{
int len;
uart_event_t event; // UART事件结构体
uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
while (1)
{
//从名为`uart0_queue`的队列中接收数据,并将接收到的数据存储到`event`变量中,如果没有数据可接收,则无限期等待(阻塞)直到有数据到来。
if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY))
{
//清零内存区域,即将这段内存区域中的所有字节都设置为0,与memset()函数类似但功能受限。由于bzero()已被废弃,推荐使用memset()进行内存设置。
bzero(dtmp, RD_BUF_SIZE);
ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
switch (event.type)
{
// 接收到的数据通常会在这里被处理 dtmp指向接收到的数据 event.size为接收到数据的大小
case UART_DATA:
{
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
int written = send(sock, dtmp, event.size, 0);
if (written < 0)
{
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
// Failed to retransmit, giving up
return;
}
}
break;
// 硬件FIFO溢出事件
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;
// 环形缓冲区满事件
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;
// 检测到UART线路断开
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
// 帧错误
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
// do {
// len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
// if (len < 0) {
// ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
// } else if (len == 0) {
// ESP_LOGW(TAG, "Connection closed");
// } else {
// rx_buffer[len] = 0; // Null-terminate whatever is received and treat it like a string
// ESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer);
// // send() can return less bytes than supplied length.
// // Walk-around for robust implementation.
// int to_write = len;
// while (to_write > 0) {
// int written = send(sock, rx_buffer + (len - to_write), to_write, 0);
// if (written < 0) {
// ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
// // Failed to retransmit, giving up
// return;
// }
// to_write -= written;
// }
// }
// } while (len > 0);
}
/* UART事件处理任务 */
// TCP服务器任务
static void tcp_server_task(void *pvParameters)
{
char addr_str[128]; // 存储客户端IP字符串
int addr_family = (int)pvParameters; // 获取地址族参数
int ip_protocol = 0; // IP协议类型
int keepAlive = 1; // 启用Keepalive
int keepIdle = 5; // Keepalive空闲时间
int keepInterval = 5; // 探测间隔
int keepCount = 3; // 探测次数
struct sockaddr_storage dest_addr; // 服务器地址存储结构
// 配置服务器地址
if (addr_family == AF_INET)
{
struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有接口
dest_addr_ip4->sin_family = AF_INET; // IPv4地址族
dest_addr_ip4->sin_port = htons(PORT); // 设置端口
ip_protocol = IPPROTO_IP; // IP协议
}
// 创建监听套接字
ESP_LOGE(TAG_ZH, "create socket");
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0)
{
ESP_LOGE(TAG_ZH, "Unable to create socket: errno %d", errno);
vTaskDelete(NULL);
return;
}
// 设置套接字选项(地址重用)
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)
// Note that by default IPV6 binds to both protocols, it is must be disabled
// if both protocols used at the same time (used in CI)
setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
#endif
ESP_LOGI(TAG, "套接字已创建");
int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err != 0)
{
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); // 套接字绑定失败
ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
goto CLEAN_UP;
}
ESP_LOGI(TAG, "Socket bound, port %d", PORT);
err = listen(listen_sock, 1); // 最大挂起连接数为1
if (err != 0)
{
ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
goto CLEAN_UP;
}
while (1)
{
struct sockaddr_storage source_addr; // 客户端地址存储
socklen_t addr_len = sizeof(source_addr);
// 接受客户端连接
int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
if (sock < 0)
{
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
// 设置TCP Keepalive选项
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
// 将客户端IP地址转换为字符串
#ifdef CONFIG_EXAMPLE_IPV4
if (source_addr.ss_family == PF_INET)
{
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
}
#endif
#ifdef CONFIG_EXAMPLE_IPV6
if (source_addr.ss_family == PF_INET6)
{
inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
}
#endif
ESP_LOGI(TAG_ZH, "Socket accepted ip address: %s", addr_str); // 接受的客户端IP:
uart_re_en_flag = 1; // 设置标志位,表示可以接收串口数据
// do_retransmit(sock);
do_retransmit(sock);
shutdown(sock, 0);
close(sock);
}
CLEAN_UP:
close(listen_sock);
vTaskDelete(NULL);
}
void app_main(void)
{
// 初始化存储空间
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);
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_DEFAULT,
};
// 安装UART驱动程序(创建事件队列)
uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
// 应用参数配置
uart_param_config(EX_UART_NUM, &uart_config);
// 设置UART引脚(TX:GPIO4, RX:GPIO5)
uart_set_pin(EX_UART_NUM, GPIO_NUM_4, GPIO_NUM_5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
ESP_ERROR_CHECK(esp_efuse_mac_get_default(mac));
wifi_init_softap();
xTaskCreate(tcp_server_task, "tcp_server", 4096, (void *)AF_INET, 5, NULL);
}