一、项目概述本文介绍如何使用ESP32微控制器驱动ST7789 TFT液晶屏和XPT2046触摸芯片,通过LVGL图形库实现主题切换功能,并开发一个实用的触摸屏示波器应用。项目包含两大核心功能:
引用:
- LVGL多主题切换:支持8种不同风格的UI主题
- 示波器功能:
模拟/数字信号采集、触摸控制面板、光标测量系统、自动频率检测
二、硬件准备组件型号说明
主控零知ESP32双核240MHz处理器
屏幕ST7789 2.4寸240×320分辨率
触摸芯片XPT2046电阻式触摸控制器
接线SPI使用硬件SPI接口
接线图
三、环境搭建1. 安装库
引用: lv_arduino v3.0.1
TFT_eSPI
XPT2046_Touchscreen
2. TFT_eSPI配置(User_Setup.h):
-
- #define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
- #define TFT_WIDTH 240 // ST7789 240 x 240
- #define TFT_HEIGHT 320 // ST7789 240 x 320
- #define TFT_MISO 19
- #define TFT_MOSI 23
- #define TFT_SCLK 18
- #define TFT_CS 15 //Chip select control pin
- #define TFT_DC 2 //Data Command control pin
- #define TFT_RST 4 //Reset pin (could connect to RST pin)
四、核心代码解析
4.1 LVGL主题设置-
- // 主题初始化
- void setup() {
- lv_test_theme(); // 默认主题
- // 可选主题:
- // lv_test_theme_1(lv_theme_night_init(210, NULL));
- // lv_test_theme_1(lv_theme_material_init(210, NULL));
- }
- // 显示驱动回调
- void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
- tft.setAddrWindow(area->x1, area->y1, area->x2, area->y2);
- for(int y=area->y1; y<=area->y2; y++){
- for(int x=area->x1; x<=area->x2; x++){
- tft.writeColor(color_p->full, 1);
- color_p++;
- }
- }
- lv_disp_flush_ready(disp);
- }
4.2 触摸驱动(带消抖)
-
- bool my_touchpad_read(lv_indev_drv_t *indev, lv_indev_data_t *data) {
- static lv_coord_t last_x = 0, last_y = 0;
- bool is_touched = ts.touched();
-
- if(is_touched){
- TS_Point p = ts.getPoint();
- // 坐标转换与校准
- last_x = map(p.x, cal_x_min, cal_x_max, 0, 320);
- last_y = map(p.y, cal_y_max, cal_y_min, 0, 240);
-
- // 滑动检测
- if(abs(last_x - prev_x) >5 || abs(last_y - prev_y) >5){
- is_sliding = true;
- }
-
- // 消抖处理
- if(!is_sliding && (millis()-last_touch_time)>CLICK_DEBOUNCE_MS){
- last_touch_time = millis();
- }
- }
- data->point.x = last_x;
- data->point.y = last_y;
- return false;
- }
4.3 简易示波器核心逻辑波形采样:
-
- void takeSample() {
- if(!digitalMode){ // 模拟模式
- uint16_t raw = analogRead(ADC_PIN);
- samplesBuffer[sampleIndex] = raw * amplitudeScale;
- }else{ // 数字模式
- bool state = digitalRead(DIGITAL_PIN);
- samplesBuffer[sampleIndex] = state ? 4095 : 0;
- }
- sampleIndex = (sampleIndex+1) % MAX_SAMPLES;
- }
波形绘制:
[code]
void updateWaveform() {
waveSprite.fillSprite(BG_COLOR);
// 绘制网格
for(int x=0; x