MicroPython 开发
本章节包含以下部分,请按需阅读:
MicroPython 入门教程
初次接触 Pico MicroPython 开发,想要快速上手?我们为您准备了一套通用的入门教程。此教程旨在帮助开发者快速熟悉 Thonny IDE 并上手开发。教程内容涵盖环境搭建、项目创建、组件使用及外设编程等,帮助您迈出 MicroPython 编程的第一步。
配置开发环境
请参考 安装和配置 Thonny IDE 教程 下载安装 Thonny IDE。
示例程序
MicroPython 示例程序位于 示例程序包 的 examples\MicroPython 目录中。
| 示例程序 | 基础例程说明 | 依赖库 |
|---|---|---|
| 01_GUI | 液晶 GUI 显示程序 | - |
| 02_SD | 挂载 SD 卡 | - |
| 03_IMU | 获取六轴传感器数据 | - |
| 04_LVGL | 液晶 LVGL 显示程序 | LVGL V9.3 |
01_GUI
【程序说明】
- 使用 SPI 与 液晶通讯,并通过 GUI 实现液晶显示触摸轨迹。
【硬件连接】
- 使用 USB 线把板子接入电脑
【代码分析】
lcd = LCD_1inch54():创建 LCD 对象。touch = Touch_CST816T():初始化触摸对象。touch_gesture():手势测试。touch_hand_writing():画点并显示在液晶。
【运行效果】
-
通过 thonny 将
01_GUI文件下的所有 py 文件上传到开发板中,运行 RP2350-Touch-LCD-1.54.py 程序。
02_SD
【程序说明】
- 使用 SPI 与 SD 卡通讯,并将 SD 卡挂载到开发板,挂载成功后,可通过 Thonny 查看和修改 SD 卡中的内容。
【硬件连接】
- 插入 SD 卡
- 使用 USB 线把板子接入电脑
【代码分析】
sdcard.SDCard(spi, cs, baudrate):创建 SD 卡对象,并将初始化的 SPI 接口与 CS 引脚绑定到 SD 卡驱动中。uos.mount(sd, '/sd'):将 SD 卡文件系统挂载到/sd目录下。挂载成功后,用户即可通过/sd路径对 SD 卡进行文件读写操作,例如创建、读取或删除文件。
【运行效果】
-
通过 thonny 将
02_SD文件下的所有 py 文件上传到开发板中,并复位。开发板复位后会根据 boot.py 的程序,自动将 SD 挂载到sd目录下。
03_IMU
【程序说明】
- 使用 I2C 与 板载六轴传感器通讯,读取六轴传感器数据。
【硬件连接】
- 使用 USB 线把板子接入电脑
【代码分析】
IMU = QMI8658():创建 IMU 对象。IMU.Read_XYZ():读取六轴传感器数据。
【运行效果】
-
使用 thonny 运行
03_IMU文件下的 py 文件。
04_LVGL
【程序说明】
- 使用 SPI 与液晶通讯,并通过 LVGL 实现显示文本和图片等功能。使用的版本号为 9.3,LVGL V9 的开发文档中没有提供 Python 示例,具体开发请参考 LVGL 开发文档。
【硬件连接】
- 使用 USB 线把板子接入电脑
【编译运行】
-
操作步骤
-
按住板上的 boot 按键,通过 USB 线将板子接到电脑的 USB 接口,然后松开按键,电脑会将开发板识别为一个可移动盘,将例程
firmware\MicroPython目录下的XXX-LVGL.uf2文件复制到开发板中 -
打开 Thonny,将例程中的
examples、lib目录上传至开发板
-
打开
examples目录下的文件XXX_LVGL_test.py,参考下图步骤运行程序
-
-
构建固件
-
构建环境:Ubuntu 22.04
-
Github:lv_micropython
-
编译固件:参考 Raspberry Pi Pico port 部分内容
-
固件路径:
lv_micropython\ports\rp2\build-XXX\firmware.uf2
-
【代码分析】
源码结构
-
LVGL 库的源码请参考 lv_micropython
-
LVGL 库的相关设置在
lv_micropython\lib\lv_bindings\lv_conf.h文件中,可以设置显示刷新频率、系统占用数据等。 -
LVGL 库的应用代码位于工程文件夹的
examples\LVGL_example.py、lib\LVGL.py。
LVGL 初始化
在使用 LVGL 图像库之前,您需要导入 LVGL 库
-
导入 LVGL 库
代码位置:
lib\LVGL.py实现功能:导入 LVGL 库,并使用别名
lv以方便调用其功能。import lvgl as lv -
LVGL 初始化
代码位置:
lib\LVGL.py代码说明:LVGL 核心初始化位于 LVGL 类的初始化函数,在创建 LVGL 对象时自动调用。
if not lv.is_initialized(): lv.init() -
创建 LVGL 对象
代码位置:
examples\XXX_LVGL_test.py实现功能:创建 LVGL 对象,并传入 LCD 和 TSC 对象作为参数。
# Init LVGLLVGL(LCD=LCD,TSC=TSC)
LVGL 运行
LVGL 库定时调用心跳接口函数 lv.tick_inc 来通知 LVGL 过去的时间,以便 LVGL 能够更新其内部的时间状态,处理与时间相关的任务,例如动画、定时器等。此外还需要调用 lv.task_handler 函数,以便 LVGL 及时处理事件和任务,保证用户界面的响应和刷新。
-
LVGL 运行接口
代码位置:
lib\LVGL.py实现方式:创建一个
event_loop对象。在该类的初始化函数中,我们创建一个定时器。该定时器会在设定的时间间隔内自动调用心跳接口函数和事件处理函数。调用的时间间隔可以通过传递freq参数调节,例如lv_utils.event_loop(freq=200),默认为 40 ms。# Create event loop if not yet presentif not lv_utils.event_loop.is_running(): self.event_loop=lv_utils.event_loop() -
LVGL 心跳接口
代码位置:
lib\lv_utils.py实现方式:需要确保
lv.task_handler的优先级低于lv.tick_inc的优先级,所以在本例中,lv.tick_inc在定时器回调函数中调用。# 每 5ms 调用一次定时器回调函数self.timer.init(mode=Timer.PERIODIC, period=self.delay, callback=self.timer_cb) # 本例中 self.delay = 5def timer_cb(self, t):lv.tick_inc(self.delay)if self.scheduled < self.max_scheduled:try:micropython.schedule(self.task_handler_ref, 0)self.scheduled += 1 # 正在处理的任务数增加except:pass -
LVGL 任务处理器
代码位置:
lib\lv_utils.py实现方式:要处理 LVGL 的任务,需要定期调用
lv.task_handler,本例在定时器回调函数中调用lv.tick_inc之后再进行调用。def task_handler(self, _):try:if lv._nesting.value == 0:lv.task_handler()if self.refresh_cb: self.refresh_cb()self.scheduled -= 1 # 正在处理的任务数减少except Exception as e:if self.exception_sink:self.exception_sink(e)
LVGL 显示
要实现 LVGL 显示,必须初始化一个显示驱动,并设置显示驱动的各个属性,例如,颜色格式、绘制缓冲区、渲染模式以及显示回调函数。在每个 LV_DEF_REFR_PERIOD(在 lv_conf.h 中设置),LVGL 会检测 UI 上是否发生了一些需要重绘的事情。例如,按下按钮、更改图表、发生动画等。需要重新绘制时,LVGL 调用显示回调函数完成图像在刷新区的绘制。
-
LVGL 显示刷新率设置
代码位置:
lv_micropython\lib\lv_bindings\lv_conf.h设置方式:在
lv_conf.h中可以修改LV_DEF_REFR_PERIOD来改变屏幕的刷新时间。#define LV_DEF_REFR_PERIOD 10 // 单位:ms,这里为10ms -
LVGL 显示相关变量定义
代码位置:
lib\LVGL.py实现功能:
buf0和buf1大小设置为屏幕显示面积的 50% 是为了实现 LVGL 双缓冲机制,能够在降低大面积刷屏锯齿的同时有效提高屏幕刷新率。# Init LVGL displaybuf1 = lv.draw_buf_create(self.LCD.width, self.LCD.height // 2 , color_format, 0)buf2 = lv.draw_buf_create(self.LCD.width, self.LCD.height // 2 , color_format, 0) -
LVGL 显示设备注册
代码位置:
lib\LVGL.py实现功能:根据设计需求完善 LVGL 库核心结构体变量,初始化显示驱动
disp_drv,并设置绘制缓冲区,该缓冲区是 LVGL 用来渲染屏幕内容的简单数组。一旦渲染准备就绪,绘制缓冲区的内容将使用显示驱动程序中设置的disp_drv_flush_cb函数发送到显示器。self.disp_drv = lv.display_create(self.LCD.width, self.LCD.height) # 创建显示驱动器对象,并设置宽度和高度self.disp_drv.set_color_format(color_format) # 设置颜色格式为 RGB565self.disp_drv.set_draw_buffers(buf1, buf2) # 设置绘制缓冲区self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # 设置渲染模式为部分刷新模式self.disp_drv.set_flush_cb(self.disp_drv_flush_cb) # 设置显示回调函数 -
LVGL 显示回调函数
代码位置:
lib\LVGL.py实现功能:主要完成图像在刷新区的绘制。
def disp_drv_flush_cb(self,disp_drv,area,color_p)参数:disp_drv : 显示驱动结构体指针,包含了与显示相关的信息和函数指针。该参数常用于通知刷新完成area : 区域结构体指针,包含待刷新区域的位置信息。在本例中,用于创建 TFT 显示的窗口color_p : 颜色结构体指针,表示要在刷新区域内显示的颜色数据。在本例中,作为DMA输入读取地址将数据传输到SPI总线,完成图像的绘制 -
LVGL 显示回调函数实现
代码位置:
lib\LVGL.py实现方式:在本例中为了最大化降低处理器的利用率,使用 DMA 来进行颜色数据的传输,设置
color_p作为读地址,SPI 总线的输出数据寄存器为写地址。代码较长仅展示部分,完整代码请下载示例查看。def disp_drv_flush_cb(self,disp_drv,area,color_p):self.rp2_wait_dma() # 等待 DMA 空闲......self.rgb565_swap_func(data_view, size) # 转换颜色格式self.LCD.setWindows(area.x1, area.y1, area.x2+1, area.y2+1) # 设置 LVGL 界面显示位置...... # DMA 配置self.rp2_dma.enable() # 使能 DMAself.rp2_wait_dma() # 等待 DMA 空闲self.disp_drv.flush_ready() # 通知 LVGL 数据传输完成
LVGL 输入
在 LVGL 中,允许用户注册输入设备,如触摸板、鼠标、键盘或编码器等设备。用户可以通过这些输入设备控制用户界面,实现更好的交互。
-
LVGL 调用输入设备回调函数的频率设置
代码位置:
lv_micropython\lib\lv_bindings\lv_conf.h设置方式:与屏幕的刷新时间使用的是相同的宏,每 10ms 调用一次输入设备回调函数来更新输入设备所触发的事件,可通过修改
LV_DEF_REFR_PERIOD定义进行设置。#define LV_DEF_REFR_PERIOD 10 // 单位:ms,这里为 10ms -
LVGL 输入设备注册
代码位置:
examples\LVGL_example.py设置方式:注册触摸屏设备
indev_drv并初始化。# Init touch screen as input deviceself.indev_drv = lv.indev_create() # 创建对象self.indev_drv.set_type(lv.INDEV_TYPE.POINTER) # 注册触摸屏设备self.indev_drv.set_read_cb(self.indev_drv_read_cb) # 设置回调函数 -
LVGL 的输入设备回调函数
代码位置:
lib\LVGL.py实现功能:主要用于更新输入事件。
def indev_drv_read_cb(indev_drv, data)参数:indev_drv : LVGL 中的输入设备驱动结构体指针。在本例中,该结构体为触摸屏输入设备驱动data : LVGL 中的输入设备数据结构体指针。在本例中,该结构体用于存储输入设备的状态和数据,包括当前的触摸状态(按下或释放)以及触摸点的坐标 -
触摸屏输入设备的回调函数实现
代码位置:
lib\CST816T.py、lib\LVGL.py实现方式:主要是通过触摸中断更新触摸屏的触摸状态和触摸点坐标。
def Int_Callback(self,pin):if self.Mode == 0 :self.Gestures = self._read_byte(0x01)elif self.Mode == 1 :self.Flag = 1self.get_point()elif self.Mode == 2 :self.Flag = 1self.get_point()self.Gestures = self._read_byte(0x01)def indev_drv_read_cb( self, indev_drv, data):self.rp2_wait_dma()data.point.x = self.TSC.X_pointdata.point.y = self.TSC.Y_pointdata.state = 1 if self.TSC.Flag == 1 else 0self.TSC.Flag = 0
LVGL 控件布局
在 LVGL 中,我们能够建立各种不同的用户界面。界面的基本组成部分是对象,也称为控件(Widgets),比如按钮(Button)、标签(Label)、图像(Image)、列表(List)、图表或文本区域。在一个界面中,可以同时创建多个控件,并且我们可以设置它们的位置、尺寸、父对象、样式以及事件处理程序等基本属性。
-
创建 LVGL 界面对象
代码位置:
examples\LVGL_example.py实现功能:创建 LVGL 界面对象,并传入 LCD 、 TSC 、 IMU 对象作为参数。
# Init WIDGETSWIDGETS(LCD=LCD,TSC=TSC,IMU=IMU) -
LVGL 创建图块
代码位置:
examples\LVGL_example.py实现功能:Tile 视图是一个容器对象,其元素(称为图块)可以按网格形式排列。用户可以通过滑动来在各个图块之间导航。使用 Tile 视图对象调用
add_tile(tileview, row_id, col_id, dir)在第row_id行和第col_id列上创建一个新图块。dir可传入lv.DIR.LEFT/RIGHT/TOP/BOTTOM/HOR/VER/ALL等参数,以便通过滑动移动到给定方向的相邻图块。# 在 (0,0) 创建一个图块,支持向下滑动到 (0,1)self.tv = lv.tileview(self.scr)self.tile1 = self.tv.add_tile(0, 0, lv.DIR.BOTTOM) -
LVGL 创建控件
代码位置:
examples\LVGL_example.py实现功能:创建控件,不同控件需要使用不同的函数接口,可以选择父对象进行创建。
# 创建一个 table 控件,其中 tile2 为该控件的父对象,可以替换为 list、title 等可以有子对象的控件self.table_imu_data = lv.table(self.tile2) -
LVGL 控件的对齐定位
代码位置:
examples\LVGL_example.py实现功能:使控件能够基于参考点进行偏移定位。控件对齐偏移的参考点控件的中心。
对齐标准: LVGL 库具备内部对齐和外部对齐两种方式。默认以左上角作为原点,向左为水平方向的正方向,向下为垂直方向的正方向。
# 将控件定位在中心点右偏移15个像素self.table_imu_data.align(lv.ALIGN.CENTER, 15 ,0) -
LVGL 控件切换字体大小
代码位置:
lv_micropython\lib\lv_bindings\lv_conf.h、examples\LVGL_example.py实现功能:在实际运用时一个界面可能需要运用多种字体大小,可以在
lv_conf.h中使能多种字体大小,且可以设置默认字体大小。设置字体大小时需要对控件风格化,使控件能够按照设置的风格进行渲染。利用add_style函数可以实现对控件各个部位在不同状态下的渲染。// lv_micropython\lib\lv_bindings\lv_conf.h#define LV_FONT_MONTSERRAT_16 1 // 使能16号字体#define LV_FONT_MONTSERRAT_18 1 // 使能18号字体#define LV_FONT_DEFAULT &lv_font_montserrat_18 // 设置默认字体大小为18号# examples\LVGL_example.pytable_imu_data= lv.style_t() # 创建对象table_imu_data.init() # 初始化table_imu_data.set_text_font(lv.font_montserrat_16) # 设置字体大小为16self.table_imu_data.add_style(style_imu_table, 0) # 设置风格 -
LVGL 控件事件处理
代码位置:
examples\LVGL_example.py实现功能:在 LVGL 中,可以给控件添加事件处理回调函数,使控件发生被点击、滚动、重绘等事件时,触发事件从而进入事件处理回调函数。在程序中调用
obj.add_event_cb(event_cb, filter, None)函数,为控件obj添加事件filter的处理函数event_cb,当控件obj触发filter事件时,系统会自动调用event_cb函数。最后一个参数是指向事件中可用的任何自定义数据的指针。# 为控件 sw 添加事件 LV_EVENT_VALUE_CHANGED 的处理函数 sw_event_cbself.sw.add_event_cb(self.sw_event_cb, lv.EVENT.VALUE_CHANGED, None)
【运行效果】
-
使用 thonny 运行
04_LVGL\examples目录下的LCD_1in54_LVGL_test.py文件。