尝鲜DFRobot ESP32-C5开发板,玩转LVGL Micropython

2025-08-253215
精华项目
AI 快速预览详细 收起
DFRobot推出了全新的FireBeetle 2 ESP32-C5开发板,搭载ESP32-C5主控,支持5GHz Wi-Fi6。本文介绍了该开发板的硬件配置、Micropython编译及烧录方法,并提供了详细的代码示例,包括LED测试、联网测试以及LVGL图形界面开发。用户可以通过esptool工具进行固件烧录,并利用提供的代码示例快速上手。


近期,DFRobot 推出了全新开发板 FireBeetle 2 ESP32-C5。这块开发板搭载了 ESP32-C5 主控,集成 支持5GHz的Wi-Fi6(意思为可以连接5G网络),凭借强劲性能,令人眼前一亮。很荣幸能抢先体验这块开发板!
1.开发板介绍
FireBeetle 2 ESP32-C5有很多外设:
  • Type-C:USB接口
  • Charge:充电指示灯

    • 熄灭:未接入电源或已充满
    • 常亮: 充电中

  • 15/D13:板载LED引脚
  • RST:复位按键
  • 28/BOOT:IO28引脚/BOOT按键
  • BAT:锂电池接口,支持3.7~4.2V
  • lO1:电池电压检测引脚
  • 3V3_C:IO0控制3.3V电源输出,默认关闭,可高电平开启。
  • GDI:GDI显示屏接口
  • ESP32-C5:型号为ESP32-C5-WROOM-1模组

2.micropython编译
由于 MicroPython 官方尚未支持 ESP32-C5,支持尚需时日,我直接采用 GitHub PR 中某位大佬的半成品,稍作修改后,再集成到lvgl_micropython项目中,所以过程复杂,而且很多人并不想自行编译,所以这里,只放固件了(固件后期DF工作人员也会会放在文档中)。
3.烧录
建议使用esptool进行烧录,官方的工具现在无法擦除,所以用一下代码进行烧录(最后的固件名字自行修改):
  1. esptool --chip esp32c5 -p COM15 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 4MB --flash_freq 80m --erase-all 0x2000 firmware_eco1.bin
复制代码

4.正式体验
注意:因为扩展板有问题,在测试之前请把扩展板拔下来。
1.普通MicroPython部分
LED测试:
  1. from machine import Pin
  2. import time
  3. ​
  4. led=Pin(15,Pin.OUT)
  5. ​
  6. while True:
  7.     led.on()
  8.     time.sleep(0.5)
  9.     led.off()
  10.     time.sleep(0.5)
复制代码

联网测试:
  1. import network,time
  2. SSID = 'SSID'
  3. PWD = 'PWD'
  4. def connect():
  5.     wlan = network.WLAN(network.STA_IF)
  6.     wlan.active(True)
  7.     if not wlan.isconnected():
  8.         print('esp32c5正在联网',end="")
  9.         wlan.connect(SSID, PWD)
  10.         while not wlan.isconnected():
  11.             print(".",end="")
  12.             time.sleep(1)
  13.     print('\n网络信息为: ', wlan.ifconfig())
  14. ​
  15. connect()
复制代码


联网扩展测试(串口与AI对话):
  1. import network
  2. import time
  3. import urequests
  4. import ujson,micropython,select,sys
  5. from machine import reset
  6. ​
  7. # ====== 配置部分 ======
  8. SSID = 'SSID'
  9. PASSWORD = 'PWD'
  10. API_KEY = "API-KEY"
  11. API_URL = "https://api.siliconflow.cn/v1/chat/completions"
  12. ​
  13. def connect_wifi():
  14.     wlan = network.WLAN(network.STA_IF)
  15.     wlan.active(True)
  16.     if not wlan.isconnected():
  17.         print('esp32c5正在联网',end="")
  18.         wlan.connect(SSID, PASSWORD)
  19.         while not wlan.isconnected():
  20.             print(".",end="")
  21.             time.sleep(1)
  22.     print('网络信息为: ', wlan.ifconfig())
  23.     print("连接成功!")
  24.     return wlan
  25. ​
  26. def api_request():
  27.     headers = {
  28.         "Authorization": "Bearer sk-fzvjpoldzvziuvdrvrjiadercddliahbfyohdrnfnnaedjmt",
  29.         "Content-Type": "application/json"
  30.     }
  31.    
  32.     micropython.kbd_intr(-1)
  33.     print("您:",end="")
  34.     while True:
  35.         
  36.         while sys.stdin in select.select([sys.stdin],[],[],0)[0]:
  37.             #print("您:",end="")
  38.             sp= sys.stdin.readline().replace("\n", "").replace(" ", "")
  39.             if sp != "":
  40.                 #sp = str(input("您:"))
  41.                 #print("您:"+sp)
  42.                 payload = {
  43.                 "model": "Qwen/Qwen3-8B",
  44.                 "messages": [  # 必须包含消息内容
  45.                     {"role": "system", "content": "你是我的AI助手qwen,你必须用中文回答且字数不超过85个,思考时间不超过1秒"},
  46.                     {"role": "user", "content": sp}
  47.                 ],
  48.                 "enable_thinking":False,
  49.                
  50.             }
  51.                 print("AI正在思考中...")
  52.                 #print("Payload:", payload)
  53.                 start_time = time.time()
  54.                 response = urequests.post(
  55.                     API_URL,
  56.                     headers=headers,
  57.                     data=ujson.dumps(payload).encode('utf-8'),
  58.                     #timeout=20
  59.                 )
  60.                 response_time = time.time() - start_time
  61.                 print(f"AI思考了{response_time:.1f}s")
  62.                 #print(f"\n[Response] Status: {response.status_code}")
  63.                 if response.status_code == 200:
  64.                     json_resp = response.json()
  65.                     print("AI回复:", json_resp['choices'][0]['message']['content'].replace("\n", ""))
  66.                 else:
  67.                     print("Error Response:", response.text)
  68.                     
  69.                 response.close()
  70.                 print("您:",end="")
  71.         
  72.    
  73. ​
  74. ​
  75. print("=== 启动系统 ===")
  76. connect_wifi()
  77. api_request()
复制代码


2.LVGL+MicroPython部分
先把屏幕的驱动下载进板子里(命名为screen.py),这里以ILI9488+GT911为主,其它的屏幕DF工作人员正在撰写对应文档,如果更新了即可下载:
  1. import lcd_bus
  2. from micropython import const
  3. import machine
  4. import lcd_utils
  5. ​
  6. # 创建SPI总线对象
  7. spi_bus = machine.SPI.Bus(
  8.     host=1,
  9.     mosi=24,
  10.     miso=25,
  11.     sck=23,
  12. )
  13. ​
  14. # 创建显示屏的SPI通信对象
  15. display_bus = lcd_bus.SPIBus(
  16.     spi_bus=spi_bus,
  17.     freq=40000000,
  18.     dc=8,
  19.     cs=27,
  20. )
  21. ​
  22. import ili9488
  23. import lvgl as lv
  24. import task_handler
  25. ​
  26. # 创建显示屏对象
  27. display = ili9488.ILI9488(
  28.     data_bus=display_bus,
  29.     display_width=320,
  30.     display_height=480,
  31.     backlight_pin=15,
  32.     reset_pin=26,
  33.     reset_state=ili9488.STATE_LOW,
  34.     color_space=lv.COLOR_FORMAT.RGB888,
  35.     color_byte_order=ili9488.BYTE_ORDER_RGB,
  36.     rgb565_byte_swap=True,
  37. )
  38. ​
  39. import i2c
  40. import task_handler
  41. import gt911
  42. ​
  43. # 初始化显示屏
  44. display.init()
  45. ​
  46. # 定义触摸屏的I2C通信参数
  47. i2c_bus = i2c.I2C.Bus(host=0, scl=10, sda=9, freq=400000, use_locks=False)
  48. print(i2c_bus.scan())
  49. touch_dev = i2c.I2C.Device(bus=i2c_bus, dev_id=0x5D, reg_bits=gt911.BITS)
  50. ​
  51. # 创建触摸屏设备对象
  52. indev = gt911.GT911(touch_dev)
  53. ​
  54. # 启用输入优先级
  55. indev.enable_input_priority()
  56. ​
  57. # 旋转显示
  58. display.set_rotation(lv.DISPLAY_ROTATION._270)
  59. # 打开屏幕背光
  60. display.set_backlight(1)
  61. th = task_handler.TaskHandler()
复制代码


滑块测试:
  1. import screen
  2. import lvgl as lv
  3. ​
  4. ​
  5. scrn = lv.screen_active()# 获取当前激活的屏幕对象
  6. scrn.set_style_bg_color(lv.color_hex(0x000000), 0)# 设置屏幕的背景颜色为黑色
  7. ​
  8. slider = lv.slider(scrn)# 创建一个滑块
  9. slider.set_size(200, 50)# 设置滑块的大小为宽度300,高50
  10. slider.center()# 将滑块居中显示
  11. ​
  12. label = lv.label(scrn)# 创建一个标签
  13. label.set_text('HELLO LVGL_MICROPYTHON!')# 标签内容
  14. label.align(lv.ALIGN.CENTER, 0, -50)# 将标签对齐到屏幕中心,并向上偏移50
复制代码


打砖块测试:
  1. import screen
  2. import lvgl as lv
  3. ​
  4. ​
  5. scrn = lv.screen_active()# 获取当前激活的屏幕对象
  6. scrn.set_style_bg_color(lv.color_hex(0x000000), 0)# 设置屏幕的背景颜色为黑色
  7. ​
  8. slider = lv.slider(scrn)# 创建一个滑块
  9. slider.set_size(200, 50)# 设置滑块的大小为宽度300,高50
  10. slider.center()# 将滑块居中显示
  11. ​
  12. label = lv.label(scrn)# 创建一个标签
  13. label.set_text('HELLO LVGL_MICROPYTHON!')# 标签内容
  14. label.align(lv.ALIGN.CENTER, 0, -50)# 将标签对齐到屏幕中心,并向上偏移50import screen, math, gc
  15. import lvgl as lv
  16. SCREEN_W = 480
  17. SCREEN_H = 320
  18. on_pad = True          # 球是否还在板上
  19. # ---------------- 物理参数 ----------------
  20. BALL_R   = 8               # 小球半径
  21. MAT_W    = 80
  22. MAT_H    = 15              # 薄板
  23. VEL_Y0   = -6              # 初始向上速度
  24. # ---------------- 全局对象 ----------------
  25. scrn = lv.screen_active()
  26. scrn.set_style_bg_color(lv.color_hex(0x000000), 0)
  27. ​
  28. # 容器(避免坐标系混乱)
  29. root = lv.obj(scrn)
  30. root.remove_style_all()
  31. root.set_size(SCREEN_W, SCREEN_H)
  32. root.center()
  33. ​
  34. # 弹力板
  35. mat = lv.obj(root)
  36. mat.set_size(MAT_W, MAT_H)
  37. mat.set_style_bg_color(lv.palette_main(lv.PALETTE.GREEN), 0)
  38. mat.set_y(SCREEN_H - MAT_H - 5)           # 固定高度
  39. ​
  40. # 小球
  41. ball = lv.obj(root)        # 用 obj 比 led 更易控制
  42. ball.set_size(BALL_R*2, BALL_R*2)
  43. ball.set_style_radius(BALL_R, 0)
  44. ball.set_style_bg_color(lv.palette_main(lv.PALETTE.ORANGE), 0)
  45. ​
  46. # 砖块
  47. BRICK_W = 31
  48. BRICK_H = 15
  49. BRICK_GAP = 2
  50. BRICK_COLS = SCREEN_W // (BRICK_W + BRICK_GAP)
  51. BRICK_ROWS = 5
  52. bricks = []
  53. ​
  54. for r in range(BRICK_ROWS):
  55.     for c in range(BRICK_COLS):
  56.         b = lv.obj(root)
  57.         b.set_size(BRICK_W, BRICK_H)
  58.         b.set_style_bg_color(
  59.             lv.palette_main(lv.PALETTE.BLUE if r % 2 else lv.PALETTE.RED), 0)
  60.         b.set_pos(c*(BRICK_W+BRICK_GAP),
  61.                   5 + r*(BRICK_H+BRICK_GAP))
  62.         bricks.append(b)
  63. ​
  64. # ---------------- 物理量 ----------------
  65. ball_x  = SCREEN_W // 2
  66. ball_y  = SCREEN_H - 50
  67. vx      = 0
  68. vy      = VEL_Y0
  69. game_over = False
  70. ​
  71. def reset_ball():
  72.     global ball_x, ball_y, vx, vy, game_over, on_pad
  73.     ball_x = mat.get_x() + MAT_W // 2      # 直接按板子位置算
  74.     ball_y = mat.get_y() - BALL_R
  75.     vx = 0
  76.     vy = VEL_Y0
  77.     game_over = False
  78.     on_pad = True          # 复位后球在板上
  79.     ball.set_pos(int(ball_x - BALL_R), int(ball_y - BALL_R))
  80. ​
  81. # ---------------- 定时器 ----------------
  82. def update_timer(t):
  83.     global ball_x, ball_y, vx, vy, game_over, on_pad
  84. ​
  85.     if game_over:
  86.         return
  87. ​
  88.     # 如果球还在板上,先让球水平跟着板子
  89.     if on_pad:
  90.         ball_x = mat.get_x() + MAT_W // 2
  91.         ball_y = mat.get_y() - BALL_R
  92.         ball.set_pos(int(ball_x - BALL_R), int(ball_y - BALL_R))
  93.         return
  94.     else:
  95.         # 原来的物理运动
  96.         ball_x += vx
  97.         ball_y += vy
  98. ​
  99.         # 边界反弹
  100.         if ball_x - BALL_R < 0 or ball_x + BALL_R > SCREEN_W:
  101.             vx = -vx
  102.             ball_x = max(BALL_R, min(SCREEN_W - BALL_R, ball_x))
  103. ​
  104.         if ball_y - BALL_R < 0:
  105.             vy = -vy
  106.             ball_y = BALL_R
  107. ​
  108.         # 掉出底部
  109.         if ball_y + BALL_R > SCREEN_H:
  110.             reset_ball()
  111.             return
  112. ​
  113.         # 与板碰撞
  114.         mat_left  = mat.get_x()
  115.         mat_right = mat_left + MAT_W
  116.         if (ball_y + BALL_R >= mat.get_y() and
  117.             ball_y - BALL_R <= mat.get_y() + MAT_H and
  118.             ball_x + BALL_R >= mat_left and
  119.             ball_x - BALL_R <= mat_right and
  120.             vy > 0):                 # 必须正在下落才反弹
  121.             hit_pos = (ball_x - mat_left) / MAT_W
  122.             vx = (hit_pos - 0.5) * 10
  123.             vy = -abs(vy)
  124.             ball_y = mat.get_y() - BALL_R
  125. ​
  126.         # ---------------- 碰撞检测 ----------------
  127.         to_delete = []                   # 1. 先收集要删的砖块
  128. ​
  129.         for brick in bricks:
  130.             bx, by = brick.get_x(), brick.get_y()
  131.             bw, bh = BRICK_W, BRICK_H
  132.             if (ball_x + BALL_R > bx and
  133.                 ball_x - BALL_R < bx + bw and
  134.                 ball_y + BALL_R > by and
  135.                 ball_y - BALL_R < by + bh):
  136. ​
  137.                 # 计算最小重叠方向
  138.                 overlap_l = (ball_x + BALL_R) - bx
  139.                 overlap_r = (bx + bw) - (ball_x - BALL_R)
  140.                 overlap_t = (ball_y + BALL_R) - by
  141.                 overlap_b = (by + bh) - (ball_y - BALL_R)
  142.                 min_overlap = min(overlap_l, overlap_r, overlap_t, overlap_b)
  143. ​
  144.                 if min_overlap == overlap_t or min_overlap == overlap_b:
  145.                     vy = -vy
  146.                 else:
  147.                     vx = -vx
  148. ​
  149.                 to_delete.append(brick)   # 2. 只记录,不立即删
  150. ​
  151.         # 3. 统一删除并回收
  152.         for brick in to_delete:
  153.             brick.delete()
  154.             bricks.remove(brick)
  155.         gc.collect()                      # 立即释放已删对象
  156. ​
  157.     # 4. 统一刷新显示
  158.     ball.set_pos(int(ball_x - BALL_R), int(ball_y - BALL_R))
  159. ​
  160. ​
  161. # ---------------- 触摸回调 ----------------
  162. def touch_cb(e):
  163.     global on_pad, vx, vy, ball_x, ball_y
  164.    
  165.     code = e.get_code()
  166.     point = lv.point_t()
  167.     screen.indev.get_point(point)
  168.    
  169.     # 板子移动逻辑(所有触摸状态都处理)
  170.     new_x = point.x - MAT_W // 2
  171.     new_x = max(0, min(SCREEN_W - MAT_W, new_x))
  172.     mat.set_x(new_x)
  173.    
  174.     # 球在板上时的同步处理
  175.     if code == lv.EVENT.PRESSING:
  176.         if on_pad == 1:
  177.             ball_x = new_x + MAT_W // 2
  178.             ball_y = mat.get_y() - BALL_R
  179.         else:
  180.             ball_x += vx
  181.             ball_y += vy
  182.             # 边界反弹
  183.             if ball_x - BALL_R < 0 or ball_x + BALL_R > SCREEN_W:
  184.                 vx = -vx
  185.                 ball_x = max(BALL_R, min(SCREEN_W - BALL_R, ball_x))
  186. ​
  187.             if ball_y - BALL_R < 0:
  188.                 vy = -vy
  189.                 ball_y = BALL_R
  190. ​
  191.             # 掉出底部
  192.             if ball_y + BALL_R > SCREEN_H:
  193.                 reset_ball()
  194.                 return
  195. ​
  196.             # 与板碰撞
  197.             mat_left  = mat.get_x()
  198.             mat_right = mat_left + MAT_W
  199.             if (ball_y + BALL_R >= mat.get_y() and
  200.                 ball_y - BALL_R <= mat.get_y() + MAT_H and
  201.                 ball_x + BALL_R >= mat_left and
  202.                 ball_x - BALL_R <= mat_right and
  203.                 vy > 0):                 # 必须正在下落才反弹
  204.                 hit_pos = (ball_x - mat_left) / MAT_W
  205.                 vx = (hit_pos - 0.5) * 10
  206.                 vy = -abs(vy)
  207.                 ball_y = mat.get_y() - BALL_R
  208.             # ---------------- 碰撞检测 ----------------
  209.             to_delete = []                   # 1. 先收集要删的砖块
  210. ​
  211.             for brick in bricks:
  212.                 bx, by = brick.get_x(), brick.get_y()
  213.                 bw, bh = BRICK_W, BRICK_H
  214.                 if (ball_x + BALL_R > bx and
  215.                     ball_x - BALL_R < bx + bw and
  216.                     ball_y + BALL_R > by and
  217.                     ball_y - BALL_R < by + bh):
  218. ​
  219.                     # 计算最小重叠方向
  220.                     overlap_l = (ball_x + BALL_R) - bx
  221.                     overlap_r = (bx + bw) - (ball_x - BALL_R)
  222.                     overlap_t = (ball_y + BALL_R) - by
  223.                     overlap_b = (by + bh) - (ball_y - BALL_R)
  224.                     min_overlap = min(overlap_l, overlap_r, overlap_t, overlap_b)
  225. ​
  226.                     if min_overlap == overlap_t or min_overlap == overlap_b:
  227.                         vy = -vy
  228.                     else:
  229.                         vx = -vx
  230. ​
  231.                     to_delete.append(brick)   # 2. 只记录,不立即删
  232. ​
  233.             # 3. 统一删除并回收
  234.             for brick in to_delete:
  235.                 brick.delete()
  236.                 bricks.remove(brick)
  237.             gc.collect()                      # 立即释放已删对象
  238. ​
  239.         ball.set_pos(int(ball_x - BALL_R), int(ball_y - BALL_R))
  240.         
  241.     # 仅PRESSED事件触发发射
  242.     elif code == lv.EVENT.PRESSED and on_pad == 1:
  243.         hit_pos = (ball_x - mat.get_x()) / MAT_W
  244.         vx = (hit_pos - 0.5) * 10
  245.         vy = VEL_Y0
  246.         on_pad = False
  247.         # 发射后立即更新一次位置
  248.         ball.set_pos(int(ball_x - BALL_R), int(ball_y - BALL_R))
  249. ​
  250. ​
  251. ​
  252. # 启动定时器
  253. lv.timer_create(update_timer, 50, None)
  254. ​
  255. root.add_event_cb(touch_cb, lv.EVENT.PRESSED, None)
  256. root.add_event_cb(touch_cb, lv.EVENT.PRESSING, None)
  257. ​
  258. reset_ball()
复制代码


时间表盘测试:
  1. import screen
  2. import time,gc
  3. import lvgl as lv
  4. from machine import Pin, Timer
  5. import math
  6. ​
  7. scrn = lv.screen_active()
  8. scrn.set_style_bg_color(lv.color_hex(0x000000), 0)
  9. ​
  10. class AnalogClock:
  11.     def __init__(self, parent):
  12.         self.scale = None
  13.         self.second_hand = None
  14.         self.minute_hand = None
  15.         self.hour_hand = None
  16.         # 获取当前时间
  17.         now = time.localtime()
  18.         self.hour = now[3] % 12  # 转换为12小时制
  19.         self.minute = now[4]
  20.         self.second = now[5]
  21.         self.create_clock(parent)
  22.         self.start_timer()
  23. ​
  24.     def create_clock(self, parent):
  25.         """创建模拟时钟组件"""
  26.         # 创建表盘主体(保持120x120大小)
  27.         self.scale = lv.scale(parent)
  28.         self.scale.set_size(200, 200)
  29.         self.scale.set_mode(lv.scale.MODE.ROUND_INNER)
  30.         
  31.         # 设置表盘样式(保持不变)
  32.         self.scale.set_style_bg_opa(lv.OPA._60, 0)
  33.         self.scale.set_style_bg_color(lv.color_hex(0x222222), 0)
  34.         self.scale.set_style_radius(lv.RADIUS_CIRCLE, 0)
  35.         self.scale.set_style_clip_corner(True, 0)
  36.         self.scale.center()
  37. ​
  38.         # 配置刻度系统(保持不变)
  39.         self.scale.set_label_show(True)
  40.         hour_labels = ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", None]
  41.         self.scale.set_text_src(hour_labels)
  42.         self.scale.set_style_text_font(lv.font_montserrat_12, 0)
  43.         self.scale.set_total_tick_count(61)
  44.         self.scale.set_major_tick_every(5)
  45. ​
  46.         # 主刻度样式(保持不变)
  47.         style_indicator = lv.style_t()
  48.         style_indicator.init()
  49.         style_indicator.set_text_color(lv.color_hex(0xFFFFFF))
  50.         style_indicator.set_line_color(lv.color_hex(0xFFFFFF))
  51.         style_indicator.set_length(5)
  52.         style_indicator.set_line_width(2)
  53.         self.scale.add_style(style_indicator, lv.PART.INDICATOR)
  54. ​
  55.         # 次刻度样式(保持不变)
  56.         style_minor = lv.style_t()
  57.         style_minor.init()
  58.         style_minor.set_line_color(lv.color_hex(0xAAAAAA))
  59.         style_minor.set_length(3)
  60.         style_minor.set_line_width(1)
  61.         self.scale.add_style(style_minor, lv.PART.ITEMS)
  62. ​
  63.         # 表盘边框样式(保持不变)
  64.         style_main = lv.style_t()
  65.         style_main.init()
  66.         style_main.set_arc_color(lv.color_hex(0x222222))
  67.         style_main.set_arc_width(3)
  68.         self.scale.add_style(style_main, lv.PART.MAIN)
  69. ​
  70.         # 设置量程和角度(保持不变)
  71.         self.scale.set_range(0, 60)
  72.         self.scale.set_angle_range(360)
  73.         self.scale.set_rotation(270)
  74. ​
  75.         # 创建秒针(红色,长度90px,细线)
  76.         self.second_hand = lv.line(self.scale)
  77.         self.second_hand.set_style_line_width(1, 0)  # 更细的线宽
  78.         self.second_hand.set_style_line_rounded(True, 0)
  79.         self.second_hand.set_style_line_color(lv.color_hex(0xFFFFFF), 0)
  80. ​
  81.         # 创建分钟指针(蓝色,长度75px)
  82.         self.minute_hand = lv.line(self.scale)
  83.         self.minute_hand.set_style_line_width(3, 0)
  84.         self.minute_hand.set_style_line_rounded(True, 0)
  85.         self.minute_hand.set_style_line_color(lv.color_hex(0x00BFFF), 0)
  86. ​
  87.         # 创建小时指针(橙色,长度60px)
  88.         self.hour_hand = lv.line(self.scale)
  89.         self.hour_hand.set_style_line_width(5, 0)
  90.         self.hour_hand.set_style_line_rounded(True, 0)
  91.         self.hour_hand.set_style_line_color(lv.color_hex(0xFFA500), 0)
  92. ​
  93.         # 添加中心点(保持不变)
  94.         center = lv.obj(self.scale)
  95.         center.set_size(8, 8)  # 稍微减小中心点大小
  96.         center.center()
  97.         center.set_style_radius(lv.RADIUS_CIRCLE, 0)
  98.         center.set_style_bg_color(lv.color_hex(0xFFD700), 0)
  99.         center.set_style_bg_opa(lv.OPA.COVER, 0)
  100. ​
  101.         self.update_hands()
  102. ​
  103.     def update_hands(self):
  104.         """更新所有指针位置"""
  105.         # 秒针(90px长度)
  106.         lv.scale.set_line_needle_value(self.scale, self.second_hand, 90, self.second)
  107.         
  108.         # 分钟指针(75px长度)
  109.         lv.scale.set_line_needle_value(self.scale, self.minute_hand, 75, self.minute)
  110.         
  111.         # 小时指针(60px长度),考虑分钟偏移
  112.         hour_value = self.hour * 5 + (self.minute // 12)
  113.         lv.scale.set_line_needle_value(self.scale, self.hour_hand, 60, hour_value)
  114. ​
  115.     def timer_callback(self, timer):
  116.         """定时器回调(每秒更新)"""
  117.         # 获取当前时间
  118.         now = time.localtime()
  119.         self.hour = now[3] % 12
  120.         self.minute = now[4]
  121.         self.second = now[5]
  122.         
  123.         self.update_hands()
  124.         gc.collect()
  125. ​
  126.     def start_timer(self):
  127.         """启动硬件定时器(每秒触发)"""
  128.         self.timer = Timer(1)
  129.         self.timer.init(period=1000, mode=Timer.PERIODIC, callback=self.timer_callback)
  130. ​
  131. # 创建时钟实例
  132. clock = AnalogClock(scrn)
复制代码

5.效果



6.问题解答
尝鲜DFRobot ESP32-C5开发板,玩转LVGL Micropython图7

以上的问题是由于设备已经初始化一次了,不能重复初始化,将板子重启再次运行即可




创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -