ESP32 IDF优雅解析陶晶驰串口屏WiFi配置
项目概述
实现ESP32通过UART优雅地接收和解析陶晶驰串口屏发送的WiFi配置信息,采用JSON格式进行数据通信。
硬件连接
- ESP32 UART1 RX → 串口屏 TX (GPIO5)
- ESP32 UART1 TX → 串口屏 RX (GPIO4)
- 共地连接
陶晶驰串口屏代码
// 在触摸事件中构建并发送JSON
prints "{\"cmd\":\"wifi_connect\",\"ssid\":\"",0
prints t0.txt,0
prints "\",\"pass\":\"",0
prints t1.txt,0
prints "\"}",0ESP端代码
头文件 data_parser.h
#ifndef DATA_PARSER_H
#define DATA_PARSER_H
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "cJSON.h"
// UART配置
#define UART_NUM UART_NUM_1
#define UART_TX_PIN GPIO_NUM_4
#define UART_RX_PIN GPIO_NUM_5
#define BUF_SIZE (1024)
// WiFi配置结构体
typedef struct {
char ssid[32];
char password[64];
int8_t rssi;
} wifi_config_t;
// 解析回调函数类型
typedef void (*wifi_config_callback_t)(const wifi_config_t *config);
// 函数声明
void uart_parser_init(wifi_config_callback_t callback);
void uart_parser_deinit(void);
void parse_json_data(const char *json_str, wifi_config_t *config);
#endif数据解析核心文件 data_parser.c
#include "data_parser.h"
static const char *TAG = "Data_Parser";
static wifi_config_callback_t user_callback = NULL;
static TaskHandle_t uart_task_handle = NULL;
// UART初始化
static void uart_init(void) {
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,
};
ESP_ERROR_CHECK(uart_driver_install(UART_NUM, BUF_SIZE * 2, 0, 0, NULL, 0));
ESP_ERROR_CHECK(uart_param_config(UART_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_LOGI(TAG, "UART初始化完成");
}
// JSON数据解析函数
void parse_json_data(const char *json_str, wifi_config_t *config) {
if (json_str == NULL || config == NULL) {
ESP_LOGE(TAG, "解析参数错误");
return;
}
ESP_LOGI(TAG, "开始解析JSON: %s", json_str);
cJSON *root = cJSON_Parse(json_str);
if (root == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
ESP_LOGE(TAG, "JSON解析错误前: %s", error_ptr);
}
return;
}
// 清理配置结构体
memset(config, 0, sizeof(wifi_config_t));
// 解析cmd字段
cJSON *cmd = cJSON_GetObjectItemCaseSensitive(root, "cmd");
if (cJSON_IsString(cmd) && (cmd->valuestring != NULL)) {
ESP_LOGI(TAG, "命令: %s", cmd->valuestring);
if (strcmp(cmd->valuestring, "wifi_connect") == 0) {
// 解析SSID
cJSON *ssid = cJSON_GetObjectItemCaseSensitive(root, "ssid");
if (cJSON_IsString(ssid) && (ssid->valuestring != NULL)) {
strncpy(config->ssid, ssid->valuestring, sizeof(config->ssid) - 1);
config->ssid[sizeof(config->ssid) - 1] = '\0';
ESP_LOGI(TAG, "解析到SSID: %s", config->ssid);
} else {
ESP_LOGW(TAG, "SSID字段缺失或格式错误");
}
// 解析密码
cJSON *pass = cJSON_GetObjectItemCaseSensitive(root, "pass");
if (cJSON_IsString(pass) && (pass->valuestring != NULL)) {
strncpy(config->password, pass->valuestring, sizeof(config->password) - 1);
config->password[sizeof(config->password) - 1] = '\0';
ESP_LOGI(TAG, "解析到密码, 长度: %d", strlen(config->password));
} else {
ESP_LOGW(TAG, "密码字段缺失或格式错误");
}
} else {
ESP_LOGW(TAG, "未知命令: %s", cmd->valuestring);
}
} else {
ESP_LOGE(TAG, "cmd字段缺失或格式错误");
}
cJSON_Delete(root);
}
// UART数据接收任务
static void uart_receive_task(void *pvParameter) {
uint8_t data[BUF_SIZE];
char json_buffer[BUF_SIZE];
int json_index = 0;
bool in_json = false;
int json_brace_count = 0;
ESP_LOGI(TAG, "UART数据接收任务启动");
while (1) {
int length = uart_read_bytes(UART_NUM, data, BUF_SIZE - 1, 20 / portTICK_PERIOD_MS);
if (length > 0) {
data[length] = '\0'; // 添加字符串结束符
for (int i = 0; i < length; i++) {
char c = data[i];
// 检测JSON开始
if (c == '{') {
if (!in_json) {
in_json = true;
json_index = 0;
json_brace_count = 0;
}
json_brace_count++;
}
// 累积JSON数据
if (in_json) {
// 防止缓冲区溢出
if (json_index < BUF_SIZE - 1) {
json_buffer[json_index++] = c;
} else {
ESP_LOGE(TAG, "JSON缓冲区溢出,重置解析状态");
in_json = false;
json_index = 0;
json_brace_count = 0;
}
// 检测JSON结束
if (c == '}') {
json_brace_count--;
if (json_brace_count == 0) {
json_buffer[json_index] = '\0';
in_json = false;
ESP_LOGI(TAG, "收到完整JSON数据");
ESP_LOGD(TAG, "JSON内容: %s", json_buffer);
// 解析数据
wifi_config_t wifi_config;
parse_json_data(json_buffer, &wifi_config);
// 如果有有效数据且用户注册了回调,则调用
if (user_callback != NULL && strlen(wifi_config.ssid) > 0) {
user_callback(&wifi_config);
}
json_index = 0;
}
}
}
// 调试输出非JSON字符
if (!in_json && c != '\r' && c != '\n' && c != ' ') {
ESP_LOGV(TAG, "非JSON字符: 0x%02x '%c'", c, (c >= 32 && c <= 126) ? c : '?');
}
}
}
// 处理JSON解析超时(防止半截JSON卡住)
if (in_json) {
static uint32_t json_timeout = 0;
static uint32_t last_receive_time = 0;
uint32_t current_time = xTaskGetTickCount();
if (length > 0) {
last_receive_time = current_time;
json_timeout = 0;
} else {
if (current_time - last_receive_time > pdMS_TO_TICKS(1000)) {
json_timeout++;
if (json_timeout > 3) { // 3秒超时
ESP_LOGW(TAG, "JSON解析超时,重置状态");
in_json = false;
json_index = 0;
json_brace_count = 0;
json_timeout = 0;
}
}
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
// 初始化数据解析器
void uart_parser_init(wifi_config_callback_t callback) {
user_callback = callback;
// 初始化UART
uart_init();
// 创建UART接收任务
xTaskCreate(uart_receive_task, "uart_receive_task", 4096, NULL, 10, &uart_task_handle);
ESP_LOGI(TAG, "数据解析器初始化完成");
}
// 反初始化数据解析器
void uart_parser_deinit(void) {
if (uart_task_handle != NULL) {
vTaskDelete(uart_task_handle);
uart_task_handle = NULL;
}
uart_driver_delete(UART_NUM);
user_callback = NULL;
ESP_LOGI(TAG, "数据解析器已卸载");
}
// 工具函数:打印配置信息
void print_wifi_config(const wifi_config_t *config) {
if (config == NULL) return;
ESP_LOGI(TAG, "=== WiFi配置信息 ===");
ESP_LOGI(TAG, "SSID: %s", config->ssid);
ESP_LOGI(TAG, "密码: %s", config->password);
ESP_LOGI(TAG, "密码长度: %d", strlen(config->password));
ESP_LOGI(TAG, "====================");
}使用示例 main.c
#include "data_parser.h"
static const char *TAG = "Main";
// WiFi配置回调函数
static void wifi_config_callback(const wifi_config_t *config) {
ESP_LOGI(TAG, "收到WiFi配置回调");
// 打印配置信息
print_wifi_config(config);
// 这里可以添加连接WiFi的逻辑
if (strlen(config->ssid) > 0) {
ESP_LOGI(TAG, "准备连接WiFi: %s", config->ssid);
// wifi_connect(config->ssid, config->password);
}
}
void app_main(void) {
ESP_LOGI(TAG, "启动数据提取测试程序");
// 初始化数据解析器
uart_parser_init(wifi_config_callback);
// 保持任务运行
while (1) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
ESP_LOGD(TAG, "系统运行中...");
}
// 清理(通常不会执行到这里)
uart_parser_deinit();
}输出示例
当串口屏发送数据时,ESP32会输出类似以下日志:
I (1254) Data_Parser: 收到完整JSON数据
I (1254) Data_Parser: JSON内容: {"cmd":"wifi_connect","ssid":"MyWiFi","pass":"12345678"}
I (1264) Data_Parser: 开始解析JSON: {"cmd":"wifi_connect","ssid":"MyWiFi","pass":"12345678"}
I (1274) Data_Parser: 命令: wifi_connect
I (1284) Data_Parser: 解析到SSID: MyWiFi
I (1294) Data_Parser: 解析到密码, 长度: 8
I (1304) Main: 收到WiFi配置回调
I (1304) Data_Parser: === WiFi配置信息 ===
I (1314) Data_Parser: SSID: MyWiFi
I (1324) Data_Parser: 密码: 12345678
I (1334) Data_Parser: 密码长度: 8
评论