lvgl会闪屏,帮我看一下

Viewed 101

问题描述


我用lvgl做应用,发现闪屏很严重,在IDE上和液晶屏上都会闪屏,我把代码发上来,帮我看一下是什么问题,我发了一个你们可以直接运行的代码。

复现步骤


import time
import lvgl as lv
import uctypes
from media.display import *
from media.media import *

print("=== LVGL 闪屏测试程序 (官方版) ===")

DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 480

虚拟显示

Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
lv.init()

双缓冲

disp_imgs = [image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565) for _ in range(2)]
disp_drv = lv.disp_create(DISPLAY_WIDTH, DISPLAY_HEIGHT)
disp_drv.set_color_format(lv.COLOR_FORMAT.RGB565)
disp_drv.set_draw_buffers(disp_imgs[0].bytearray(), disp_imgs[1].bytearray(),
disp_imgs[0].size(), lv.DISP_RENDER_MODE.FULL)

def flush_cb(disp_drv, area, color):
if disp_drv.flush_is_last():
ptr = uctypes.addressof(color.dereference())
for img in disp_imgs:
if img.virtaddr() == ptr:
Display.show_image(img)
break
disp_drv.flush_ready()

disp_drv.set_flush_cb(flush_cb)

模拟触摸输入(不依赖硬件)

class SimTouch:
def init(self):
self.indev = lv.indev_create()
self.indev.set_type(lv.INDEV_TYPE.POINTER)
self.indev.set_read_cb(self.callback)
self.pressed = False
self.x = 0
self.y = 0

def callback(self, driver, data):
    data.point.x = self.x
    data.point.y = self.y
    data.state = lv.INDEV_STATE.PRESSED if self.pressed else lv.INDEV_STATE.RELEASED

def set_touch(self, x, y, pressed):
    self.x = x
    self.y = y
    self.pressed = pressed

sim_touch = SimTouch()

主屏幕

scr = lv.scr_act()
scr.set_style_bg_color(lv.color_hex(0x1A2A3A), 0)

标题

title = lv.label(scr)
title.set_text("LVGL Flicker Test")
title.set_style_text_color(lv.color_hex(0xFFFFFF), 0)
title.align(lv.ALIGN.TOP_MID, 0, 20)

创建 6 个卡片

cards = []
card_colors = [0x2A3A4A, 0x3A4A5A, 0x4A5A6A, 0x5A6A7A, 0x6A7A8A, 0x7A8A9A]

for i in range(6):
card = lv.obj(scr)
card.set_size(220, 160)
card.set_pos(40 + (i % 3) * 260, 70 + (i // 3) * 190)
card.set_style_bg_color(lv.color_hex(card_colors[i]), 0)
card.set_style_radius(10, 0)

temp_label = lv.label(card)
temp_label.set_text("45.2°C")
temp_label.set_style_text_color(lv.color_hex(0x00FF00), 0)
temp_label.align(lv.ALIGN.CENTER, 0, -20)

target_label = lv.label(card)
target_label.set_text("Target: 100°C")
target_label.set_style_text_color(lv.color_hex(0xAAAAAA), 0)
target_label.align(lv.ALIGN.CENTER, 0, 20)

cards.append(temp_label)

创建进度条

bar = lv.bar(scr)
bar.set_size(300, 20)
bar.align(lv.ALIGN.BOTTOM_MID, 0, -50)
bar.set_range(0, 100)

创建按钮

btn = lv.btn(scr)
btn.set_size(120, 50)
btn.align(lv.ALIGN.BOTTOM_RIGHT, -20, -50)
btn_label = lv.label(btn)
btn_label.set_text("Click")
btn_label.center()

def btn_cb(evt):
if evt.get_code() == lv.EVENT.CLICKED:
print("Button clicked")

btn.add_event(btn_cb, lv.EVENT.CLICKED, None)

print("开始测试,数据每 0.5 秒更新一次")
print("观察 IDE 显示窗口是否有闪屏现象")
print("可用鼠标点击按钮测试交互")

count = 0
last_update = time.ticks_ms()

模拟鼠标移动

mouse_x = 400
mouse_y = 300
mouse_dir = 1

while True:
lv.timer_handler()

# 模拟鼠标移动(测试刷新)
mouse_x += mouse_dir * 10
if mouse_x > 700 or mouse_x < 100:
    mouse_dir = -mouse_dir
sim_touch.set_touch(mouse_x, mouse_y, False)

now = time.ticks_ms()
if now - last_update > 500:
    # 更新所有卡片温度
    for i, label in enumerate(cards):
        val = 45 + (count % 50) / 10
        label.set_text(f"{val:.1f}°C")
    
    # 更新进度条
    bar.set_value(count % 101, lv.ANIM.OFF)
    
    count += 1
    last_update = now

time.sleep_ms(20)
3 Answers

你好,请使用编辑框里的代码标记,现在的格式无法查看。

重新发上去了

代码看了吗

我想问一下,你们有看到我的问题吗,有帮忙在检查问题吗

import time
import lvgl as lv
import uctypes
from media.display import *
from media.media import *

print("=== LVGL 闪屏测试程序 (官方版) ===")

DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 480

虚拟显示
Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
lv.init()

双缓冲
disp_imgs = [image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565) for _ in range(2)]
disp_drv = lv.disp_create(DISPLAY_WIDTH, DISPLAY_HEIGHT)
disp_drv.set_color_format(lv.COLOR_FORMAT.RGB565)
disp_drv.set_draw_buffers(disp_imgs[0].bytearray(), disp_imgs[1].bytearray(),
disp_imgs[0].size(), lv.DISP_RENDER_MODE.FULL)

def flush_cb(disp_drv, area, color):
if disp_drv.flush_is_last():
ptr = uctypes.addressof(color.dereference())
for img in disp_imgs:
if img.virtaddr() == ptr:
Display.show_image(img)
break
disp_drv.flush_ready()

disp_drv.set_flush_cb(flush_cb)

模拟触摸输入(不依赖硬件)
class SimTouch:
def init(self):
self.indev = lv.indev_create()
self.indev.set_type(lv.INDEV_TYPE.POINTER)
self.indev.set_read_cb(self.callback)
self.pressed = False
self.x = 0
self.y = 0

def callback(self, driver, data):
    data.point.x = self.x
    data.point.y = self.y
    data.state = lv.INDEV_STATE.PRESSED if self.pressed else lv.INDEV_STATE.RELEASED

def set_touch(self, x, y, pressed):
    self.x = x
    self.y = y
    self.pressed = pressed
sim_touch = SimTouch()

主屏幕
scr = lv.scr_act()
scr.set_style_bg_color(lv.color_hex(0x1A2A3A), 0)

标题
title = lv.label(scr)
title.set_text("LVGL Flicker Test")
title.set_style_text_color(lv.color_hex(0xFFFFFF), 0)
title.align(lv.ALIGN.TOP_MID, 0, 20)

创建 6 个卡片
cards = []
card_colors = [0x2A3A4A, 0x3A4A5A, 0x4A5A6A, 0x5A6A7A, 0x6A7A8A, 0x7A8A9A]

for i in range(6):
card = lv.obj(scr)
card.set_size(220, 160)
card.set_pos(40 + (i % 3) * 260, 70 + (i // 3) * 190)
card.set_style_bg_color(lv.color_hex(card_colors[i]), 0)
card.set_style_radius(10, 0)

temp_label = lv.label(card)
temp_label.set_text("45.2°C")
temp_label.set_style_text_color(lv.color_hex(0x00FF00), 0)
temp_label.align(lv.ALIGN.CENTER, 0, -20)

target_label = lv.label(card)
target_label.set_text("Target: 100°C")
target_label.set_style_text_color(lv.color_hex(0xAAAAAA), 0)
target_label.align(lv.ALIGN.CENTER, 0, 20)

cards.append(temp_label)
创建进度条
bar = lv.bar(scr)
bar.set_size(300, 20)
bar.align(lv.ALIGN.BOTTOM_MID, 0, -50)
bar.set_range(0, 100)

创建按钮
btn = lv.btn(scr)
btn.set_size(120, 50)
btn.align(lv.ALIGN.BOTTOM_RIGHT, -20, -50)
btn_label = lv.label(btn)
btn_label.set_text("Click")
btn_label.center()

def btn_cb(evt):
if evt.get_code() == lv.EVENT.CLICKED:
print("Button clicked")

btn.add_event(btn_cb, lv.EVENT.CLICKED, None)

print("开始测试,数据每 0.5 秒更新一次")
print("观察 IDE 显示窗口是否有闪屏现象")
print("可用鼠标点击按钮测试交互")

count = 0
last_update = time.ticks_ms()

模拟鼠标移动
mouse_x = 400
mouse_y = 300
mouse_dir = 1

while True:
lv.timer_handler()

# 模拟鼠标移动(测试刷新)
mouse_x += mouse_dir * 10
if mouse_x > 700 or mouse_x < 100:
    mouse_dir = -mouse_dir
sim_touch.set_touch(mouse_x, mouse_y, False)

now = time.ticks_ms()
if now - last_update > 500:
    # 更新所有卡片温度
    for i, label in enumerate(cards):
        val = 45 + (count % 50) / 10
        label.set_text(f"{val:.1f}°C")
    
    # 更新进度条
    bar.set_value(count % 101, lv.ANIM.OFF)
    
    count += 1
    last_update = now

time.sleep_ms(20)

你好,请使用以下脚本,我这边测试不会闪烁。

import time
import lvgl as lv
import uctypes
from media.display import *
from media.media import *

print("=== LVGL 闪屏测试程序 (官方版) ===")

DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 480

# 虚拟显示
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
lv.init()

# 双缓冲
disp_imgs = [image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565) for _ in range(2)]

disp_drv = lv.disp_create(DISPLAY_WIDTH, DISPLAY_HEIGHT)

disp_drv.set_color_format(lv.COLOR_FORMAT.RGB565)

disp_drv.set_draw_buffers(disp_imgs[0].bytearray(), disp_imgs[1].bytearray(),
                         disp_imgs[0].size(), lv.DISP_RENDER_MODE.FULL)

def flush_cb(disp_drv, area, color):
    if disp_drv.flush_is_last():
        ptr = uctypes.addressof(color.__dereference__())
        for img in disp_imgs:
            if img.virtaddr() == ptr:
                Display.show_image(img)
                # Small delay to ensure display update completes
#                time.sleep_ms(5)  # Adjust this value
                break
    disp_drv.flush_ready()

disp_drv.set_flush_cb(flush_cb)

# 模拟触摸输入(不依赖硬件)
class SimTouch:
    def __init__(self):
        self.indev = lv.indev_create()
        self.indev.set_type(lv.INDEV_TYPE.POINTER)
        self.indev.set_read_cb(self.callback)
        self.pressed = False
        self.x = 0
        self.y = 0

    def callback(self, driver, data):
        data.point.x = self.x
        data.point.y = self.y
        data.state = lv.INDEV_STATE.PRESSED if self.pressed else lv.INDEV_STATE.RELEASED

    def set_touch(self, x, y, pressed):
        self.x = x
        self.y = y
        self.pressed = pressed

sim_touch = SimTouch()

# 主屏幕
scr = lv.scr_act()
scr.set_style_bg_color(lv.color_hex(0x1A2A3A), 0)

# 标题
title = lv.label(scr)
title.set_text("LVGL Flicker Test")
title.set_style_text_color(lv.color_hex(0xFFFFFF), 0)
title.align(lv.ALIGN.TOP_MID, 0, 20)

# 创建 6 个卡片
cards = []
card_colors = [0x2A3A4A, 0x3A4A5A, 0x4A5A6A, 0x5A6A7A, 0x6A7A8A, 0x7A8A9A]

for i in range(6):
    card = lv.obj(scr)
    card.set_size(220, 160)
    card.set_pos(40 + (i % 3) * 260, 70 + (i // 3) * 190)
    card.set_style_bg_color(lv.color_hex(card_colors[i]), 0)
    card.set_style_radius(10, 0)
    
    temp_label = lv.label(card)
    temp_label.set_text("45.2°C")
    temp_label.set_style_text_color(lv.color_hex(0x00FF00), 0)
    temp_label.align(lv.ALIGN.CENTER, 0, -20)
    
    target_label = lv.label(card)
    target_label.set_text("Target: 100°C")
    target_label.set_style_text_color(lv.color_hex(0xAAAAAA), 0)
    target_label.align(lv.ALIGN.CENTER, 0, 20)
    
    cards.append(temp_label)

# 创建进度条
bar = lv.bar(scr)
bar.set_size(300, 20)
bar.align(lv.ALIGN.BOTTOM_MID, 0, -50)
bar.set_range(0, 100)

# 创建按钮
btn = lv.btn(scr)
btn.set_size(120, 50)
btn.align(lv.ALIGN.BOTTOM_RIGHT, -20, -50)
btn_label = lv.label(btn)
btn_label.set_text("Click")
btn_label.center()

def btn_cb(evt):
    if evt.get_code() == lv.EVENT.CLICKED:
        print("Button clicked")

btn.add_event(btn_cb, lv.EVENT.CLICKED, None)

print("开始测试,数据每 0.5 秒更新一次")
print("观察 IDE 显示窗口是否有闪屏现象")
print("可用鼠标点击按钮测试交互")

count = 0
last_update = time.ticks_ms()

# 模拟鼠标移动
mouse_x = 400
mouse_y = 300
mouse_dir = 1

while True:
    lv.timer_handler()
    
    # 模拟鼠标移动(测试刷新)
    mouse_x += mouse_dir * 10
    if mouse_x > 700 or mouse_x < 100:
        mouse_dir = -mouse_dir
    sim_touch.set_touch(mouse_x, mouse_y, False)
    
    now = time.ticks_ms()
    if now - last_update > 500:
        # 更新所有卡片温度
        for i, label in enumerate(cards):
            val = 45 + (count % 50) / 10
            label.set_text(f"{val:.1f}°C")
        
        # 更新进度条
        bar.set_value(count % 101, lv.ANIM.OFF)
        
        count += 1
        last_update = now
    
    time.sleep_ms(20)

我用这个代码测试过了,我发现闪屏的规律,只有用Display.ST7701才会不闪屏,用VIRT或者LT9611都会闪屏

这个是因为vo 输出时序的问题,后续会优化virt的。

LT9611呢,我需要用到HDMI屏幕