MicroPython Zephyr 端口 `zephyr.Display` 类完全指南:复用 Zephyr Display API 驱动 LCD/OLED 显示屏

📅 发布时间:2026/9/20 16:39:44
MicroPython Zephyr 端口 `zephyr.Display` 类完全指南:复用 Zephyr Display API 驱动 LCD/OLED 显示屏
MicroPython Zephyr 端口zephyr.Display类完全指南复用 Zephyr Display API 驱动 LCD/OLED 显示屏【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython导读zephyr.Display是 MicroPython Zephyr 端口ports/zephyr为上层 Python 代码提供的显示屏访问类它通过封装 Zephyr RTOS 原生 Display 驱动接口让开发者可以用 MicroPython 直接驱动由 Zephyr devicetree 描述zephyr,display/zephyr,displayschosen 节点的 LCD、OLED、电子墨水屏等显示设备。读完本文你将掌握Display对象的构造方式、像素格式与朝向管理、write()/rgb()等核心方法、capabilities()返回的能力元组解析以及如何借助as_framebuf()把显示屏无缝接入 MicroPython 的framebuf绘图体系。本文以 docs/library/zephyr.Display.rst 为骨架并结合 ports/zephyr/zephyr_display.c、ports/zephyr/modzephyr.c 等源码展开说明。一、模块背景与启用条件1.1 什么是zephyr.Display在 Zephyr 生态中显示设备的底层能力由 Zephyr 的 Display API 提供。MicroPython 的 Zephyr 端口并没有为每种屏幕重新实现一套驱动而是把 Zephyr 已有的驱动基础设施直接暴露给 Python显示设备在 devicetree 中通过 chosen 节点指定zephyr,display单个显示节点或zephyr,displays带displays属性的显示列表节点zephyr.Display类通过一个复刻 Zephyr 的 API 来访问这些显示设备文档原话即write()、clear()、blanking()、orientation()等方法的语义与 Zephyr C API 一一对应。1.2 编译期开关Display类并非在所有固件中都存在它依赖两个编译开关见 ports/zephyr/zephyr_display.c开关作用CONFIG_DISPLAY启用 Zephyr 显示子系统Display类仅在定义该 Kconfig 时编译并注册到zephyr模块见 modzephyr.cMICROPY_PY_FRAMEBUF启用 MicroPython 的framebuf模块只有开启后as_framebuf()方法才可用见 zephyr_display.c也就是说import zephyr后能否使用zephyr.Display取决于构建固件时板级配置如ports/zephyr/boards/下的.conf文件是否打开了CONFIG_DISPLAY。1.3 设备从哪里来源码中设备的发现顺序zephyr_display.c优先枚举 compatible 为zephyr,displays的节点中的displays属性得到设备数组zephyr_display_devices[]否则回退到 chosen 节点zephyr,display指向的单个设备若两者都没有则设备数组为空此时用整数id构造会抛出ValueError: Invalid display ID。因此板子上有哪些可用屏幕完全由 devicetree 决定MicroPython 侧只是读取这份静态描述。二、构造函数Display(id)Display(id)获取一个用于访问由id标识的显示设备的对象。id有两种形式整数0、1…按zephyr,displays属性中的位置索引。越界小于 0 或大于等于Display.display_count会抛ValueError: Invalid display ID源码字符串如ssd13063c通过节点标识符node label / devicetree 名字查找设备底层调用zephyr_device_find()ports/zephyr/zephyr_device.c内部先device_get_binding()若开启CONFIG_DEVICE_DT_METADATA还会尝试按 node label 匹配找不到则抛ValueError: device xxx not found。另外如果设备未就绪device_is_ready()失败会抛RuntimeError: Display is not readyzephyr_display.c。源码还额外暴露了一个文档未列出的类属性Display.display_count值为DT_ZEPHYR_DISPLAYS_COUNT见 zephyr_display.c可用于遍历所有屏幕from zephyr import Display print(Display.display_count) # 当前固件可用屏幕数量 d Display(0) # 按位置取第一个屏幕 print(d) # 输出形如 Display(ssd13063c)三、方法详解3.1write(buf, x0, y0, size_xNone, size_yNone)—— 向屏幕写入像素数据Display.write(buf[, x[, y[, size_x[, size_y]]]])把缓冲区协议对象bytearray、bytes等按显示器的当前像素格式写入屏幕。x、y为写入区域左上角坐标size_x、size_y为写入区域的宽高均可省略源码默认行为见 zephyr_display.c默认x 0、y 0默认size_x取capabilities.x_resolution屏幕完整一行宽度默认size_y len(buf) / (size_x * 每像素字节数)即按当前像素格式从缓冲区长度反推高度。缓冲区长度必须不小于size_x * size_y * 每像素字节数否则抛ValueError: Buffer is shorter than size requires。写入失败底层display_write()返回负值抛RuntimeError: Couldnt write to display。# 以 RGB565 屏幕为例填充一整屏128x64 单色屏则除以 8 得每行 16 字节 import zephyr d zephyr.Display(0) caps d.capabilities() w, h caps[0], caps[1] buf bytearray(w * h * 2) # RGB565 每像素 2 字节 d.write(buf) # 整屏写入 d.write(buf, 10, 10, 32, 32) # 只写入 10,10 开始的 32x32 区域3.2rgb(r, g, b)—— 颜色到像素格式的转换Display.rgb(r, g, b)把0..255的 RGB 三通道颜色转换为当前像素格式对应的整数。转换规则zephyr_display.c当前像素格式转换结果MONO01任一通道 127 →0xFF否则0x00MONO10任一通道 127 →0x00否则0xFF极性反转RGB_5650xF800、0x07E0、0x001F掩码组合字节序交换MP_BSWAP16RGB_565X同上但不交换字节序L_8(r g b) / 3灰度L_4若支持灰度右移 4 位若当前格式无法映射到 framebuf 像素格式抛ValueError: Not a framebuf pixel format。# 在 RGB565 屏幕上把红色转换为 2 字节像素值 red d.rgb(255, 0, 0)3.3capabilities()—— 查询屏幕能力Display.capabilities()返回一个 7 元组格式为(X Size, Y Size, Supported PFs, Current PF, Current Orientation, Misc Characteristics, Current PF as framebuf format)各元素含义对应 zephyr_display.c索引含义说明0X 分辨率整数如1281Y 分辨率整数如642支持的像素格式整数元组每个元素是一个格式位掩码如1 i3当前像素格式整数对应下方常量4当前朝向整数对应ORIENTATION_*常量5杂项特性字符串元组可含VTILED、MSB_FIRST、EPD、DOUBLE_BUFFER、X_ALIGNMENT_WIDTH等6当前格式对应的 framebuf 格式整数供as_framebuf()/ 手工创建framebuf.FrameBuffer使用x_size, y_size, pfs, cur_pf, orient, misc, fb_fmt d.capabilities() print(f{x_size}x{y_size}, PF{cur_pf:#x}, fb{fb_fmt}, misc{misc})像素格式 → framebuf 格式的映射由zephyr_display_framebuf_current_format_helper()完成zephyr_display.c单色MONO01/MONO10依据VTILED/MSB_FIRST特性映射为MVLSB(0)、MHMSB(4)或MHLSB(3)RGB_565/RGB_565X→RGB565(1)L_8→GS8(6)L_4→GS4_HMSB(2)。若VTILED与MSB_FIRST同时出现对应 framebuf 不支持的 VMSB 布局会抛ValueError: Not a framebuf pixel format。3.4format([format])—— 读取 / 设置像素格式Display.format([format])不带参数返回当前像素格式整数带参数尝试调用 Zephyr 的display_set_pixel_format()切换格式失败抛ValueError: Invalid pixel format成功后再返回新的当前格式zephyr_display.c。注意目标格式必须包含在capabilities()[2]支持列表中否则底层会拒绝。print(hex(d.format())) # 例如 0x1100 (RGB565) d.format(Display.FORMAT_MONO01) # 切换到单色格式若支持3.5blanking(value)—— 屏幕消隐开关Display.blanking(value)value为真值时调用display_blanking_on()否则调用display_blanking_off()失败抛RuntimeError: Couldnt set blankingzephyr_display.c。适合实现省电或熄屏效果。d.blanking(True) # 熄屏 d.blanking(False) # 亮屏3.6clear()—— 清屏Display.clear()调用 Zephyr 的display_clear()。若底层驱动未实现清屏返回-ENOSYS抛RuntimeError: Clearing is not supported by the display其他失败抛Couldnt clear displayzephyr_display.c。电子墨水屏等设备通常支持清屏。3.7set_brightness(value)/set_contrast(value)—— 亮度与对比度Display.set_brightness(value) # 0..255 Display.set_contrast(value) # 0..255参数会被CLAMP限定在0..255区间。若底层驱动不支持-ENOSYS分别抛RuntimeError: Setting brightness/contrast is not supported by the displayzephyr_display.c。对带背光的 LCD 或支持对比度调节的 OLED如 SSD1306 的set_contrast非常实用。d.set_brightness(200) # 调低背光 d.set_contrast(128) # 调整 OLED 对比度3.8orientation([orientation])—— 读取 / 设置屏幕朝向Display.orientation([orientation])不带参数返回当前朝向整数带参数先校验0 arg 270越界抛ValueError: Invalid orientation然后调用display_set_orientation()失败时按-ENOSYS抛Setting orientation is not supported by the display否则抛Couldnt set orientation最后返回新的当前朝向zephyr_display.c。建议使用源码提供的四个类常量而非裸数字print(d.orientation()) d.orientation(Display.ORIENTATION_90) # 旋转 90 度3.9as_framebuf()—— 无缝接入 framebuf 绘图Display.as_framebuf()仅当固件启用了MICROPY_PY_FRAMEBUF时可用。它返回一个framebuf.FrameBuffer实例的增强版一个匿名子类实例除继承framebuf.FrameBuffer的全部绘图方法fill、line、rect、text、blit等外还额外带有show()方法调用show()即把当前缓冲区内容按当前设置的配置直接写入屏幕zephyr_display.c。其实现要点缓冲区大小按x_resolution * y_resolution * 每像素字节数分配并清零帧缓冲格式取自capabilities()[6]当前像素格式对应的 framebuf 格式show()内部通过display.write(buf)把整个缓冲区交给显示器zephyr_display.c。from zephyr import Display d Display(0) fb d.as_framebuf() fb.fill(0) # 清屏写 0 fb.text(Hello MicroPython, 0, 0, 1) fb.rect(10, 20, 50, 20, 1) fb.show() # 一次性刷新到屏幕配合 extmod/modframebuf.c 中定义的 framebuf 格式常量MVLSB0、RGB5651、GS4_HMSB2、MHLSB3、MHMSB4、GS86你还可以手工构造与屏幕匹配的FrameBuffer实现双缓冲或局部刷新。四、像素格式与朝向常量zephyr.Display类上还暴露了一批常量zephyr_display.c与 Zephyr 的PIXEL_FORMAT_*/DISPLAY_ORIENTATION_*枚举值一一对应朝向常量常量值Display.ORIENTATION_NORMAL0Display.ORIENTATION_901Display.ORIENTATION_1802Display.ORIENTATION_2703像素格式常量部分常量说明Display.FORMAT_RGB_88824 位 RGBDisplay.FORMAT_MONO01/FORMAT_MONO10单色两种极性Display.FORMAT_ARGB_888832 位 ARGBDisplay.FORMAT_RGB_565/FORMAT_RGB_565X16 位 RGB565字节序差异Display.FORMAT_L_88 位灰度Display.FORMAT_L_4/FORMAT_I_44 位灰度/索引色Zephyr 4.4Display.FORMAT_AL_88、FORMAT_XRGB_8888、FORMAT_BGR_888、FORMAT_ABGR_8888、FORMAT_RGBA_8888、FORMAT_BGRA_8888视 Zephyr 版本条件编译注意源码针对 Zephyr 4.4 做了兼容处理——Zephyr 4.4 将PIXEL_FORMAT_BGR_565更名为PIXEL_FORMAT_RGB_565X若旧头文件缺失PANEL_PIXEL_FORMAT_RGB_565X定义会用PANEL_PIXEL_FORMAT_BGR_565补齐zephyr_display.c保证跨版本可编译。五、端到端示例在支持显示器的板子上点亮屏幕以检测到屏幕 → 查询能力 → 绘图并刷新的完整流程为例from zephyr import Display # 1. 确认固件带有显示设备 if Display.display_count 0: raise SystemExit(No display in devicetree) # 2. 获取显示器并查看能力 d Display(0) # 或 Display(ssd13063c) print(d) w, h, _, pf, orient, misc, _ d.capabilities() print(fresolution{w}x{h} pf{pf:#x} orient{orient} misc{misc}) # 3. 清屏、设置亮度/对比度按设备能力选择 d.clear() try: d.set_contrast(180) except RuntimeError as e: print(contrast unsupported:, e) # 4. 用 framebuf 绘图并刷新固件需启用 MICROPY_PY_FRAMEBUF fb d.as_framebuf() fb.fill(0) fb.text(Zephyr, 0, 0, 1) fb.hline(0, 12, w, 1) fb.show()若当前像素格式不是 framebuf 可直接映射的格式如RGB_888as_framebuf()会抛ValueError: Not a framebuf pixel format此时可先尝试d.format(Display.FORMAT_RGB_565)切换或直接用d.write()手工组包。六、异常速查表场景异常整数id越界ValueError: Invalid display ID字符串id找不到设备ValueError: device xxx not found设备未就绪RuntimeError: Display is not readywrite()缓冲区比所需短ValueError: Buffer is shorter than size requireswrite()底层失败RuntimeError: Couldnt write to displayrgb()/as_framebuf()格式无法映射ValueError: Not a framebuf pixel formatformat()设置非法格式ValueError: Invalid pixel formatorientation()参数越界ValueError: Invalid orientation驱动未实现某功能返回-ENOSYSRuntimeError: ... not supported by the display七、延伸阅读类文档docs/library/zephyr.Display.rstzephyr模块总览docs/library/zephyr.rst核心实现ports/zephyr/zephyr_display.c设备枚举、方法绑定、framebuf 映射设备查找辅助ports/zephyr/zephyr_device.c模块注册与CONFIG_DISPLAY开关ports/zephyr/modzephyr.c、ports/zephyr/modzephyr.hframebuf 格式常量与绘图实现extmod/modframebuf.cZephyr 端口构建与板级配置ports/zephyr/README.md、ports/zephyr/boards如 rpi_pico.overlay 展示了 devicetree 覆盖文件的写法总而言之zephyr.Display是连接 MicroPython 脚本层与 Zephyr 显示驱动栈的薄封装一方面它完整复刻了 Zephyr Display API 的语义写入、格式、朝向、消隐、亮度/对比度、清屏另一方面通过as_framebuf()与 MicroPython 原生framebuf绘图体系打通使得在 Zephyr 支持的任意带屏开发板上用几行 Python 完成绘图与刷新成为可能。【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考