在上一篇中,小编为大家简单介绍了LVGL库,并且介绍了如何实现lvgl和MicroPython的绑定,使得lvgl以MicroPython模块的形式供用户通过Python进行调用,方便开发。 本篇小编将继续承接上文,介绍如何添加输入/输出驱动,以将我们绘制的GUI界面显示到显示设备。同时,输入设备方便我们进行人机交互。既然要使用Python进行GUI开发,那么驱动当然也要注册为MicroPython模块,才像话嘛。同时,由于LVGL可以配置为使用不同的显示器和输入设备。这样一来,如果单纯的只提供C语言编写的驱动程序,每更换驱动就要重新将新的驱动程序替换到工程中,重新编译。考虑到注册驱动程序的本质,实际上就是调用注册函数(disp_drv_register),并将函数指针作为参数传递,函数指针指向用于访问真正的显示/输入设备。为了实现这一点,当在MicroPython中使用LVGL时,用C语言实现显示和输入驱动程序更有意义。但是,设备的注册是需要在MicroPython脚本中进行的,即前文所说的,驱动程序本身需要定义成对应的MicroPython模块。这样用户就可以轻松地选择和替换驱动程序,而无需构建项目和修改C文件。不过,从技术上讲,驱动程序不仅仅局限于C,也可以用纯纯的MicroPyhon,通过回调函数来编写。进行驱动注册的代码实现:# 所编写的模块驱动 import lvgl_helper
# 注册显示驱动.
disp_buf1 = lv.disp_buf_t() buf1_1 = bytes(480*10) # 声明lvgl绘制GUI的buffer,lvgl支持1-2个 # buffer disp_buf1.init(buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.buffer = disp_buf1 disp_drv.flush_cb = lvgl_helper.flush # 注册显示回调函数 disp_drv.hor_res = 480 disp_drv.ver_res = 320 disp_drv.register()
# 注册输入驱动
indev_drv = lv.indev_drv_t() indev_drv.init() indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = lvgl_helper.capture # 注册输入回调函数 indev_drv.register()
这里,我们定义了一个叫做lvgl_helper的模块,其中包括一个叫做flush的函数,负责将lvgl绘制好的GUI刷新到显示设备,另一个函数叫做capture,负责处理输入请求,获取用户输入。 接下来,让我们看看这两个函数是怎么实现的。 首先是lvgl_helper.flush函数,具有三个参数,作用就是将lvgl绘制的目标区域刷新到显示设备: STATIC mp_obj_t mp_flush(mp_obj_t disp_drv, mp_obj_t area, mp_obj_t color){ // 显示设备指针 lv_disp_drv_t *disp_ptr = GET_PTR_FROM_OBJ(lv_disp_drv_t, disp_drv); // 待刷新区域 lv_area_t *area_ptr = GET_PTR_FROM_OBJ(lv_area_t, area); // 待刷新目标地址指针 lv_color_t *color_ptr = GET_PTR_FROM_OBJ(lv_color_t, color); // 获取刷新区域宽和高 uint16_t w = lv_area_get_width(area_ptr); uint16_t h = lv_area_get_height(area_ptr); // 真正的刷新函数,根据不同硬件定制化实现 Update_FrameBuffer((void*)color_ptr, w, h, COLOR_DEPTH, NULL); // 很重要,在刷新完成后,需要通知lvgl,刷新完毕,可以继续绘制,否则会一直阻塞 // 直到刷新完毕 lv_disp_flush_ready(disp_ptr); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(mp_flush_obj, mp_flush);
与之对应的输入函数,看似简单一点,只有2个参数,其目的就是获取屏幕触摸坐标: STATIC mp_obj_t mp_capture(mp_obj_t indev_drv, mp_obj_t data){ // 输入设备指针 lv_indev_drv_t *indev_ptr = GET_PTR_FROM_OBJ(lv_indev_drv_t, indev_drv); // 存储获取的触摸位置坐标(x,y) lv_indev_data_t* data_ptr = GET_PTR_FROM_OBJ(lv_indev_data_t, data); // 触摸屏驱动,需要自行实现 DEMO_ReadTouch(indev_ptr, data_ptr, resolution.w, resolution.h); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mp_capture_obj, mp_capture);
有了显示和输入设备的驱动,就可以算的上万事具备了,不过,东风还没来。 lvgl规定,画面的刷新以及响应输入设备,是通过周期性的调用lv.task_handler()函数实现的,同时需要通过lv.tick_inc(x)函数提供内部时钟。而对于MicroPython,函数的周期性调用有点特殊,是通过周期性的调用mp_sched_schedule函数来实现的。 为了做到周期性调用这一硬性规定,推荐的做法是实现一个timer,软件/硬件的都可以,但是硬件时钟当然最好,并将周期函数以callback的形式注册到timer中: def timer_callback(self): lv.tick_inc(10) lv.task_handler() timer.init(50) # 刷新时间可以自行调整 timer.callback(timer_callback)
这样,一切就都准备就绪了,让我们来搭建一个简单的界面玩一下。 这次的小demo包括:按钮,滑动条,键盘,文本框以及一个图片控件。 先看下实际效果: 是不是界面很熟悉,是的,小编前面说过了,MicroPython环境依托于openART软件包,因此,我们可以使用openMV IDE进行代码的编写和下载,并通过预览窗口进行GUI预览。 下面逐段说明一下控件所对应的代码实现: 0) 初始化: import lv lv.init() scr = lv.obj() # declare the screen to show
btn = lv.btn(lv.scr_act()) # 对齐属性以及位置坐标 btn.align(lv.scr_act(), lv.ALIGN.IN_BOTTOM_LEFT, 10, -20) btn.toggle() # 翻转显示,蓝底白字/白底蓝字 label = lv.label(btn) # 控件名字 label.set_text('start')
2) 滑动条: slider = lv.slider(lv.scr_act()) slider.align(lv.scr_act(), lv.ALIGN.OUT_RIGHT_TOP, -50, -10) # 滑动条宽和高 slider.set_width(10) slider.set_height(300) # 滑动条范围 slider.set_range(10, 200) # 滑动条初始值 slider.set_value(100, 0)
3) 键盘: keyboard = lv.keyboard(lv.scr_act()) # 数字键盘 # keyboard.set_mode(keyboard.MODE.NUM) # 大写字母键盘 # keyboard.set_mode(keyboard.MODE.TEXT_UPPER) # 小写字母键盘 # keyboard.set_mode(keyboard.MODE.TEXT_LOWER) # 特殊符号键盘 # keyboard.set_mode(keyboard.MODE.SPECIAL) keyboard.align(lv.scr_act(), lv.ALIGN.IN_TOP_LEFT, 0, 0)
4) 文本框: text = lv.textarea(lv.scr_act()) text.align(lv.scr_act(), lv.ALIGN.IN_BOTTOM_LEFT, 0, 0) # 设置控件为可拖拽属性 text.drag(True)
5) 图片: # 读取图片数据 img_data = open('/sd/blue_flower_16.txt').read() img = lv.img(lv.scr_act()) img.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0) # 设置图像属性 img_dsc = lv.img_dsc_t( { 'header': {'always_zero': 0, 'w': 100, 'h': 75, 'cf': lv.img.CF.TRUE_COLOR}, 'data_size': len(img_data), 'data': img_data, } ) img.set_src(img_dsc)
尽管是几个简单的控件的使用,验证了我们的带MicroPython绑定的lvgl已经成功移植到了我们的板子上。
相信大家看完之后,已经跃跃欲试了,那就开始动手吧!
|