- #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;
- }
波形绘制:
- void updateWaveform() {
- waveSprite.fillSprite(BG_COLOR);
- // 绘制网格
- for(int x=0; x<GRAPH_WIDTH; x+=32){
- waveSprite.drawFastVLine(x,0,GRAPH_HEIGHT,GRID_COLOR);
- }
- // 绘制波形
- for(int i=0; i<visibleSamples; i++){
- uint16_t y = map(samplesBuffer[i],0,4095,GRAPH_HEIGHT,0);
- waveSprite.drawPixel(i*2, y, WAVE_COLOR);
- }
- // 绘制光标
- if(cursorMode){
- waveSprite.drawFastVLine(cursor1Pos,0,GRAPH_HEIGHT,CURSOR1_COLOR);
- waveSprite.drawFastVLine(cursor2Pos,0,GRAPH_HEIGHT,CURSOR2_COLOR);
- }
- waveSprite.pushSprite(0, GRAPH_TOP);
- }
五、触摸控制面板实现
- void create_ui(){
- // 创建选项卡式控制面板
- lv_obj_t *tabview = lv_tabview_create(rightPanel, NULL);
- lv_obj_t *timeTab = lv_tabview_add_tab(tabview, "时基");
-
- // 时基选择滚轮
- lv_obj_t *timebaseRoller = lv_roller_create(timeTab);
- lv_roller_set_options(timebaseRoller, "0.5ms\n1.0ms\n2.0ms", LV_ROLLER_MODE_NORMAL);
-
- // 幅度控制滑块
- lv_obj_t *ampSlider = lv_slider_create(ampTab);
- lv_slider_set_range(ampSlider, 0, 400);
-
- // 模式切换开关
- modeSwitch = lv_switch_create(controlPanel);
- lv_obj_set_event_cb(modeSwitch, mode_switch_event_cb);
- }
六、性能优化技巧
- 双缓冲机制:使用TFT_eSPI的Sprite功能减少闪烁
- 异步采样:在loop()中分离采样和显示逻辑
- 动态刷新:根据时基自动调整刷新率
- 内存管理:
- static lv_color_t buf[LV_HOR_RES_MAX * 10]; // LVGL缓冲区
- TFT_eSprite waveSprite = TFT_eSprite(&tft); // 波形缓冲
七、实测效果7.1 LVGL不同主题切换
演示视频:
7.2示波器触控界面效果
演示视频:
参数 | 性能指标 |
最大采样率 | 20KSPS |
电压范围 | 0-3.3V |
时基范围 | 0.5-25ms/div |
触控响应 | <50ms |
八、常见问题解决触摸校准异常
修改cal_x_min/max和cal_y_min/max值
使用校准例程获取实际参数
LVGL内存不足
- // 修改lv_conf.h配置
- #define LV_MEM_SIZE (48*1024)
- #define LV_DISP_DEF_REFR_PERIOD 30
完整代码获取:
Github仓库
https://github.com/Leeri1y/esp32-st7789
或者
百度网盘
https://pan.baidu.com/s/19TVS2PBJpYqExxsannnH3w?pwd=epyd
互动交流: 欢迎在评论区留言讨论,遇到问题可提交Issues
附录:关键函数速查表函数功能调用示例
lv_btn_create()创建按钮lv_obj_t * btn = lv_btn_create(parent, NULL);
lv_sw_get_state()获取开关状态bool state = lv_sw_get_state(sw);
lv_roller_set_options()设置滚轮选项lv_roller_set_options(roller, "1\n2\n3", true);
waveSprite.pushSprite()刷新显示waveSprite.pushSprite(0, 0);
ts.touched()检测触摸if(ts.touched()) { ... }
✅ 动手实践建议
先运行基础显示示例验证硬件连接
逐步添加功能模块(先显示后触摸)
使用串口监视器调试输出
保存不同版本的代码备份