【QT 自研上位机 与 ESP32下位机联调>>>串口控制GPIO-基础样例-联合文章】

【QT 自研上位机 与 ESP32下位机联调>>>串口控制GPIO-基础样例-联合文章】

1、概述

最为新手,想要快速入门相关设备,比如ESP32,可能最好的方式就是直接手动去敲一遍代码,而串口算是单片机入门中,必不可少的一个基础课程,很多通讯,以及打印各种信息,都需要,而加入一些交互,能让我们更好调试单片机。

我打算出3章,像之前STM32那种单片机,调试串口一样。

本次第三章,和上位机进行联合调试。

第一章,也就是串口基础篇,简单调试ESP32,进行交互。

第二章,将会结合GPIO,进行一些简单外围控制。

第三章,将会结合上位机,使用自制上位机进行联合调试。

2、实验环境

ESP32说明:ESP32-S3 是一款集成 2.4 GHz Wi-Fi 和 Bluetooth 5 (LE) 的 MCU 芯片,支持远距离模式 (Long Range)。ESP32-S3 搭载 Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz,内置 512 KB SRAM (TCM),具有 45 个可编程 GPIO 管脚和丰富的通信接口。ESP32-S3 支持更大容量的高速 Octal SPI flash 和片外 RAM,支持用户配置数据缓存与指令缓存。

硬件信息:开发板 ESP32-S3-DevKitM-1(EPS32-S3-wroom-1模块)

调试环境:Windows下

串口工具:USB转串口TTL/232等

其他硬件:逻辑分析仪,杜邦线,两个usb-type-c连接线等。

3、 自我总结

有了调试串口的经验,再加上调试IO的经验,其实我们就很容易合在一起,就像那个很有意思的笑话,苹果的英文单词和笔的单词,组合在一起的就是笔记本了。
如下,请允许我在原本应该严肃的科技博文中,加入一个搞笑的部分。

但是这个道理是相通的,我们学习一个东西的时候,其实一块一块学的,或者说以小见大。

举个例子,我们之前学习了ESP32的串口,

【PC电脑windows编写代码-学习uart0串口编写代码-串口程序-ESP32-简单通讯交互-基础样例学习】

同时又做了ESP32的IO实验,

【PC电脑windows-学习样例generic_gpio-拓展GPIO-ESP32的GPIO程序-问题解决-GPIO输出实验-基础样例学习(2)】

那么现在组合起来就可以了。

自己之前就有做联合文章的经历,从上位机,到下位机,一整条链路,一次性打通,学习每个部分,最后组合在一起,其实多少有些分繁琐而简化。

就像之前文章一样。

【QT 自研上位机 与 STM32F4xx下位机联调>>>can通信测试-基础样例-联合文章】

【QT 自研上位机 与 STM32F103下位机联调>>>串口uart通信测试-基础样例-联合文章】

也就有了本次实验,以及这篇文章。

4、 实验过程

1、验证上位机QT程序

上位机这块我们采用之前的串口工厂简单修改,来完成我们的目标。
【QT 5 调试软件+串口相关初试串口+基础样例】

1、下载样例代码

(1)下载代码

代码连接:https://download.csdn.net/download/qq_22146161/86722251

使用qt开,然后硬件转换器短接。

qt运行原件如下,可以看到能收到自己发出的"123"

2、修改qt程序

我们简单改写程序,发出990和991,好和ESP32配合

(1)ui界面修改

(2)转到槽函数

(3)加入代码

3、运行测试验证

2、验证下位机ESP32程序

样例用的下ESP32,如下文章中的。同样的也是验证下。

【PC电脑windows编写代码-ESP32-串口控制GPIO编写代码-简单通讯交互控制IO-进阶样例学习-2】

1、下载样例代码

代码链接:https://download.csdn.net/download/qq_22146161/88678030

2、更改ESP32代码,编译下载

我们在990这条命令上,专门做了个双IO拉低拉高,这样好检验。

c 复制代码
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"

#define TX_PIN 18
#define RX_PIN 19
#define BUF_SIZE 1024

const char *expected_string0 = "990";
const char *expected_string1 = "991";
const char *expected_string2 = "992";
const char *expected_string3 = "993";
const char *expected_string4 = "994";
const char *expected_string5 = "995";
const char *expected_string6 = "996";

#define GPIO_OUTPUT_IO_0    35
#define GPIO_OUTPUT_IO_1    36
#define GPIO_OUTPUT_IO_2    37
#define GPIO_OUTPUT_IO_3    38

 #define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) |(1ULL<<GPIO_OUTPUT_IO_1) | (1ULL<<GPIO_OUTPUT_IO_2) | (1ULL<<GPIO_OUTPUT_IO_3)) // 配置GPIO_OUT位寄存器

void gpio_init(void)
{
    gpio_config_t io_conf;  // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置
    io_conf.intr_type = GPIO_INTR_DISABLE;  // 禁止中断  
    io_conf.mode = GPIO_MODE_OUTPUT;            // 选择输出模式
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 配置GPIO_OUT寄存器
    io_conf.pull_down_en = 0;                   // 禁止下拉
    io_conf.pull_up_en = 1;                     // 禁止上拉

    gpio_config(&io_conf);                      // 最后配置使能
}

void app_main(void) {

    gpio_init();
    // 配置UART参数
    
    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
    };
    uart_param_config(UART_NUM_0, &uart_config);



    // 设置UART1使用的TX和RX引脚
    uart_set_pin(UART_NUM_0, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    // 安装UART驱动程序,使用默认缓冲区大小
    uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);

    // 发送和接收数据的缓冲区
    uint8_t *data = (uint8_t *)malloc(BUF_SIZE);

        const char *test_str0 = "write_this_is_990";
        const char *test_str1 = "write_this_is_991";
        const char *test_str2 = "write_this_is_992";
        const char *test_str3 = "write_this_is_993";
        const char *test_str4 = "write_this_is_994";
        const char *test_str5 = "write_this_is_995";
        const char *test_str6 = "write_this_is_996";

    while (1) {
        // 发送数据
        const char *test_str = "Hello from UART01!";
        uart_write_bytes(UART_NUM_0, test_str, strlen(test_str));

        // 从UART接收数据
        int length = 0;
        ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_0, (size_t *)&length));
        length = uart_read_bytes(UART_NUM_0, data, length, 20 / portTICK_PERIOD_MS);

        if (length > 0) {
            data[length] = 0; // 确保字符串以null终止
            printf("Received data: '%s'\n", (char *)data);
             gpio_set_level(GPIO_OUTPUT_IO_0, 0);            // 把这个GPIO输出地电平
             vTaskDelay(10 / portTICK_PERIOD_MS);
             gpio_set_level(GPIO_OUTPUT_IO_0, 1);          
             vTaskDelay(10 / portTICK_PERIOD_MS);
                //控制第一个IO上下
                if(strstr ((const char *)data, expected_string0)!=NULL )
                {
                      uart_write_bytes(UART_NUM_0, test_str0, strlen(test_str0));
                      gpio_set_level(GPIO_OUTPUT_IO_0, 0);            // 把这个GPIO输出地电平
                      vTaskDelay(1000 / portTICK_PERIOD_MS);
                      gpio_set_level(GPIO_OUTPUT_IO_1, 0);            // 把这个GPIO输出地电平
                      vTaskDelay(1000 / portTICK_PERIOD_MS);
                      gpio_set_level(GPIO_OUTPUT_IO_1, 1);            // 把这个GPIO输出地高平
                      vTaskDelay(1000 / portTICK_PERIOD_MS);
                      gpio_set_level(GPIO_OUTPUT_IO_0, 1);            // 把这个GPIO输出地高平
                      vTaskDelay(1000 / portTICK_PERIOD_MS);
                        printf("this is 990!");
                       // break;
                }
                if(strstr ((const char *)data, expected_string1) !=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str1, strlen(test_str1));
                    gpio_set_level(GPIO_OUTPUT_IO_0, 0);            // 把这个GPIO输出低电平
                        printf("this is 991!");
                      //  break;
                }
                //控制第二个IO上下
                if(strstr ((const char *)data, expected_string2)!=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str2, strlen(test_str2));
                    gpio_set_level(GPIO_OUTPUT_IO_1, 1);            // 把这个GPIO输出高电平
                        printf("this is 992!");
                     //   break;
                }
                if(strstr ((const char *)data, expected_string3)!=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str3, strlen(test_str3));
                    gpio_set_level(GPIO_OUTPUT_IO_1, 0);            // 把这个GPIO输出低电平
                        printf("this is 993!");
                     //   break;
                }
                //控制第三个IO上下
                if(strstr ((const char *)data, expected_string4)!=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str4, strlen(test_str4));
                    gpio_set_level(GPIO_OUTPUT_IO_2, 1);            // 把这个GPIO输出高电平
                        printf("this is 994");
                     //   break;
                }
                if(strstr ((const char *)data, expected_string5)!=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str5, strlen(test_str5));
                    gpio_set_level(GPIO_OUTPUT_IO_2, 0);            // 把这个GPIO输出低电平
                        printf("this is 995!");
                     //   break;
                }
                //单独功能
                if(strstr ((const char *)data, expected_string6)!=NULL )
                {
                    uart_write_bytes(UART_NUM_0, test_str6, strlen(test_str6));
                    //gpio_set_level(GPIO_OUTPUT_IO_2, 0);            // 把这个GPIO输出低电平
                        printf("this is 996!");
                     //   break;
                }
   

       
            
        }

        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

下载完了按下复位

3、验证

硬件连接

c 复制代码
3/5V IN ---  ESP32-18
3V OUT  ---  ESP32-19
GND     ---  GND

然后使用一个串口软件打开,看看是否能收到消息。

3、联合调试-ESP32和qt上位机

1、硬件连接

其实到目前位置,硬件连接已经完成了。

当然我们还需要接上逻辑分析仪

c 复制代码
3/5V IN ---  ESP32-18
3V OUT  ---  ESP32-19
GND     ---  GND

//逻辑分析仪
GND  ---- GND
0通道 ---- ESP32-35
GND  ---- GND
1通道 ---- ESP32-36

2、验证

(1)上位机软件和逻辑分析仪截图说明

如下,为上位机发送990后,上位机>>>通过通讯>>>单片机>>>IO控制>>>逻辑分析仪,整条链路。

(1)代码和逻辑分析仪截图说明

这块要简单分析下代码,35GPIO先跳变了下,然后拉低3S,在此期间36GPIO拉低了1S。

5、代码连接

一套解决办法吧,需要代码的自取。

代码链接:https://download.csdn.net/download/qq_22146161/88689386

6、细节部分

(1)常见错误解决办法:

调试单片机的时候,或者说调试串口的时候,其实很难问题穷尽,但是一些方式,可以帮我们更快定位。

  1. UART配置错误:确保你的UART配置与你所使用的引脚和硬件设置相匹配。检查波特率、数据位、校验位和停止位是否正确配置。
  2. GPIO引脚不正确或被占用:检查你用作UART的GPIO引脚是否正确,并且没有被其他功能(如SPI、I2C或内置功能)占用。
  3. UART驱动安装问题:确保UART驱动正确安装,没有内存分配错误或其他问题。
  4. 缓冲区问题:检查是否有足够的空间在UART的发送缓冲区中存储要发送的数据。如果缓冲区已满,可能需要增加缓冲区大小或等待缓冲区可用。
  5. 硬件问题:检查你的ESP32开发板和任何连接的串行设备是否存在硬件故障。
    电源和接地问题:确保所有设备都有适当的电源和接地。

为了解决这个问题,可以尝试以下步骤:

  • 重新检查UART配置:确保UART的初始化和配置正确无误。
  • 检查GPIO引脚:验证所选择的GPIO引脚是否适合用作UART,且未被占用。
  • 检查驱动安装:确保使用 uart_driver_install 函数正确安装了UART驱动。
  • 增加缓冲区大小:如果需要,可以在调用 uart_driver_install 时增加缓冲区大小。
  • 硬件检查:检查ESP32开发板和相关硬件是否有任何明显的损坏或连接问题。

(2)ESP32工程下载后,先清理下

自己在下载过程中,发现直接编译也就是"idf.py build"的时候,会提示下,最好先清理下,然后重新编译。

(3)逻辑分析仪,需要跳变信号触发

如下,逻辑分析仪,在使用的时候,还是需要注意一下,它需要一个跳变信号,否则就会像下图一样,一直等待。

而且实际抓取信号,只后半部分,被拉高部分。

所以我们时间调试时,只要收到消息,先来个跳变信号触发下。

(4)逻辑分析仪,触发触发选择不点下面两个

实际想直接进行采集的,就把下面两个也点上了,实际测试应该是不选择下面两个

7、总结

如此一来,ESP32也有联合文章了。

相关推荐
岁岁岁平安1 分钟前
本机 MongoDB 注册系统服务、启用security认证
数据库·python·mongodb
lly20240615 分钟前
Kotlin 类和对象
开发语言
是苏浙21 分钟前
零基础入门C语言之C语言内存函数
c语言·开发语言
zhmhbest22 分钟前
Qt 全球峰会 2025:中国站速递 —— 技术中立,拥抱更大生态
开发语言·qt·系统架构
程序员大雄学编程22 分钟前
用Python来学微积分30-微分方程初步
开发语言·python·线性代数·数学·微积分
关于不上作者榜就原神启动那件事26 分钟前
模拟算法乒乓球
开发语言·c++·算法
88号技师1 小时前
2025年7月一区SCI优化算法-Logistic-Gauss Circle optimizer-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
再睡一夏就好1 小时前
【C++闯关笔记】unordered_map与unordered_set的底层:哈希表(哈希桶)
开发语言·c++·笔记·学习·哈希算法·散列表
potato_15541 小时前
现代C++核心特性——内存篇
开发语言·c++·学习
lly2024061 小时前
C# 继承
开发语言