MicroPython 是为了在嵌入式系统中运行 Python 3 编程语言而设计的轻量级版本解释器。与常规 Python 相比,MicroPython 解释器体积小(仅100KB左右),通过编译成二进制 Executable 文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分 Python 标准库,以适应资源限制的微控制器。
MicroPython 主要特点包括:
1、语法和功能与标准 Python 兼容,易学易用。支持 Python 大多数核心语法。
2、对硬件直接访问和控制,像 Arduino 一样控制 GPIO、I2C、SPI 等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快 10-100 倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell 交互环境为开发测试提供便利。
7、内置 I/O 驱动支持大量微控制器平台,如 ESP8266、ESP32、STM32、micro:bit、掌控板和 pyBoard 等。有活跃的社区。
MicroPython 的 framebuf 模块是一个用于创建和操作位图图像的接口。它可以将一个字节数组作为一个像素缓冲区,然后使用不同的颜色格式和绘图方法来绘制像素、线条、矩形、文本等图形。它可以用于为显示器生成输出,或者将图像数据发送给其他设备。
framebuf 模块的主要特点有:
它基于著名的 BerkelyDB 库,版本 1.xx,具有成熟和稳定的性能。
它尽可能地模仿标准的 dict 类型的接口,方便用户使用。不过需要注意的是,键和值都必须是 bytes 类型的对象(如果要存储其他类型的对象,需要先序列化为 bytes)。
它支持多种不同的颜色格式,如单色、灰度、RGB565 等。不同的颜色格式有不同的位数和布局,影响着图像的质量和大小。
它支持一些高级的参数和方法,用于调整图像的操作,如页面大小、缓存大小、最小键数等。
framebuf 模块可以用于以下一些应用场景:
显示控制:利用 framebuf 模块,可以实现对显示器的控制和显示。例如,可以使用 framebuf 模块来显示一些文本、图标、动画等,并根据需要进行滚动、旋转、缩放等变换。
图像处理:利用 framebuf 模块,可以实现对图像的处理和转换。例如,可以使用 framebuf 模块来裁剪、旋转、缩放、镜像、反色等操作,并将结果保存为新的图像文件或发送给其他设备。
图形绘制:利用 framebuf 模块,可以实现对图形的绘制和生成。例如,可以使用 framebuf 模块来绘制一些简单的几何图形、曲线、填充等,并将结果显示在屏幕上或保存为新的图像文件。
使用 framebuf 模块时,需要注意以下事项:
在使用该模块上的任何其他方法之前,必须先调用 FrameBuffer 类的构造函数来创建一个 FrameBuffer 对象。创建时,需要传入一个字节数组作为缓冲区,以及指定图像的宽度、高度、颜色格式等参数。
在对图像进行修改操作后(如添加、删除或更新像素或图形),需要调用 flush 方法来将修改写入到缓冲区中。否则,修改可能会丢失或不一致。
在处理数据时,需要注意数据类型和长度的限制和转换。键和值都必须是 bytes 类型的对象,且长度不能超过 255 字节。如果要存储其他类型的对象,需要先序列化为 bytes 类型。
以下是一些使用 MicroPython 的 framebuf 模块的实际运用程序案例。
案例1:文本显示
这是一个使用 framebuf 模块来显示一些文本,并根据用户输入进行滚动或清除的程序案例。
# 导入 framebuf 和 machine 模块 import framebuf import machine # 创建一个字节数组作为缓冲区 buffer = bytearray(128 * 64 // 8) # 创建一个 FrameBuffer 对象,使用单色垂直最低有效位格式 fbuf = framebuf.FrameBuffer(buffer, 128, 64, framebuf.MONO_VLSB) # 填充整个 FrameBuffer 为黑色 fbuf.fill(0) # 在 FrameBuffer 上写入文本 "Hello, MicroPython!" ,使用白色 fbuf.text("Hello, MicroPython!", 0, 0, 1) # 创建一个 SPI 对象,连接到 SSD1306 OLED 显示器 spi = machine.SPI(1, baudrate=10000000, polarity=0, phase=0) # 创建一个 Pin 对象,用于控制显示器的数据/命令选择 dc = machine.Pin(2) # 创建一个 Pin 对象,用于控制显示器的复位 rst = machine.Pin(4) # 创建一个 Pin 对象,用于控制显示器的片选 cs = machine.Pin(15) # 创建一个 SSD1306_SPI 对象,用于控制显示器 oled = framebuf.SSD1306_SPI(128, 64, spi, dc, rst, cs) # 将 FrameBuffer 的内容显示在 OLED 上 oled.blit(fbuf, 0, 0) # 刷新 OLED oled.show() # 创建一个 Pin 对象,用于接收用户的按键输入 button = machine.Pin(0, machine.Pin.IN) # 定义一个变量,用于记录文本的水平偏移量 offset = 0 # 定义一个无限循环,用于处理用户的输入 while True: # 如果用户按下了按键 if button.value() == 1: # 将文本的水平偏移量增加 8 像素 offset += 8 # 如果文本的水平偏移量超过了 FrameBuffer 的宽度 if offset >= fbuf.width: # 将文本的水平偏移量重置为 0 offset = 0 # 填充整个 FrameBuffer 为黑色 fbuf.fill(0) # 在 FrameBuffer 上写入文本 "Hello, MicroPython!" ,使用白色,并根据偏移量进行滚动 fbuf.text("Hello, MicroPython!", -offset, 0, 1) # 将 FrameBuffer 的内容显示在 OLED 上 oled.blit(fbuf, 0, 0) # 刷新 OLED oled.show()
案例2:图像转换
这是一个使用 framebuf 模块来将一个 BMP 图像文件转换为 RGB565 格式,并将结果保存为新的 BMP 图像文件的程序案例。
# 导入 framebuf 和 ubinascii 模块 import framebuf import ubinascii # 定义一个函数,用于读取 BMP 图像文件的头部信息,并返回宽度、高度和颜色格式等参数 def read_bmp_header(filename): # 打开 BMP 图像文件,以二进制模式读取 with open(filename, "rb") as f: # 跳过前两个字节(文件类型标识符) f.read(2) # 读取四个字节(文件大小),并转换为整数类型 file_size = int.from_bytes(f.read(4), "little") # 跳过四个字节(保留字段) f.read(4) # 读取四个字节(数据偏移量),并转换为整数类型 data_offset = int.from_bytes(f.read(4), "little") # 跳过四个字节(信息头大小) f.read(4) # 读取四个字节(图像宽度),并转换为整数类型 width = int.from_bytes(f.read(4), "little") # 读取四个字节(图像高度),并转换为整数类型 height = int.from_bytes(f.read(4), "little") # 跳过两个字节(颜色平面数) f.read(2) # 读取两个字节(颜色位数),并转换为整数类型 bit_count = int.from_bytes(f.read(2), "little") # 返回图像文件的参数 return file_size, data_offset, width, height, bit_count # 定义一个函数,用于将 RGB888 颜色格式转换为 RGB565 颜色格式,并返回转换后的颜色值 def rgb888_to_rgb565(color): # 将颜色值分解为三个分量:红、绿、蓝 r, g, b = color[0], color[1], color[2] # 将红色分量右移 3 位,保留最低 5 位 r = r >> 3 # 将绿色分量右移 2 位,保留最低 6 位 g = g >> 2 # 将蓝色分量右移 3 位,保留最低 5 位 b = b >> 3 # 将三个分量合并为一个 16 位的整数,按照 RGB565 的布局 rgb565 = (r << 11) | (g << 5) | b # 返回转换后的颜色值 return rgb565 # 定义一个函数,用于将 RGB565 颜色格式转换为 RGB888 颜色格式,并返回转换后的颜色值 def rgb565_to_rgb888(color): # 将颜色值分解为三个分量:红、绿、蓝 r = (color >> 11) & 0x1F g = (color >> 5) & 0x3F b = color & 0x1F # 将红色分量左移 3 位,补齐最高位 r = r << 3 | r >> 2 # 将绿色分量左移 2 位,补齐最高位 g = g << 2 | g >> 4 # 将蓝色分量左移 3 位,补齐最高位 b = b << 3 | b >> 2 # 将三个分量合并为一个 3 字节的 bytes 对象,按照 RGB888 的布局 rgb888 = bytes([r, g, b]) # 返回转换后的颜色值 return rgb888 # 定义一个函数,用于将一个 BMP 图像文件转换为 RGB565 格式,并将结果保存为新的 BMP 图像文件 def convert_bmp_to_rgb565(in_file, out_file): # 读取输入文件的头部信息,获取宽度、高度和颜色格式等参数 file_size, data_offset, width, height, bit_count = read_bmp_header(in_file) # 打开输入文件和输出文件,以二进制模式读写 with open(in_file, "rb") as fin, open(out_file, "wb") as fout: # 将输入文件的前 data_offset 个字节(包括头部信息)复制到输出文件中 fout.write(fin.read(data_offset)) # 创建一个字节数组作为缓冲区,大小为 width * height * 2(每个像素占 2 字节) buffer = bytearray(width * height * 2) # 创建一个 FrameBuffer 对象,使用 RGB565 格式 fbuf = framebuf.FrameBuffer(buffer, width, height, framebuf.RGB565) # 填充整个 FrameBuffer 为黑色 fbuf.fill(0) # 根据输入文件的颜色格式,进行不同的处理 if bit_count == 24: # 如果是 RGB888 格式 # 从第 data_offset 个字节开始,循环读取输入文件中的数据,每次读取 width * 3 个字节(一行像素) for y in range(height): row = fin.read(width * 3) # 遍历每一行像素中的每个像素 for x in range(width): # 获取当前像素的颜色值(3 字节) color = row[x * 3 : x * 3 + 3] # 将颜色值转换为 RGB565 格式 color = rgb888_to_rgb565(color) # 在 FrameBuffer 上绘制当前像素,注意 y 坐标需要反转 fbuf.pixel(x, height - y - 1, color) elif bit_count == 16: # 如果是 RGB565 格式 # 直接将输入文件中的数据复制到缓冲区中 buffer[:] = fin.read() else: # 如果是其他格式,不支持转换 raise ValueError("Unsupported bit count: {}".format(bit_count)) # 将缓冲区中的数据写入输出文件中 fout.write(buffer) # 调用函数,将一个 BMP 图像文件转换为 RGB565 格式,并将结果保存为新的 BMP 图像文件 convert_bmp_to_rgb565("in.bmp", "out.bmp")
案例3:LCD 显示屏
import framebuf # 定义屏幕尺寸和颜色模式 width = 128 height = 64 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_VLSB) # 在屏幕上绘制图形 fb.fill(0) # 清空屏幕 fb.rect(10, 10, 50, 30, 1) # 绘制矩形 fb.line(0, 0, width - 1, height - 1, 1) # 绘制线条 fb.text("Hello", 20, 40, 1) # 绘制文本 # 将图形显示在LCD屏幕上 lcd = LCD() # 假设已经初始化了LCD对象 lcd.show_framebuffer(fb) print("图形显示成功!")
在这个例子中,我们使用 framebuf.FrameBuffer() 函数创建一个帧缓冲对象,用于在 LCD 显示屏上绘制图形。可以使用 fill() 方法清空屏幕,rect() 方法绘制矩形,line() 方法绘制线条,text() 方法绘制文本。最后,使用 lcd.show_framebuffer() 方法将图形显示在 LCD 屏幕上。
案例4:LED 矩阵显示
import framebuf # 定义LED矩阵尺寸和颜色模式 width = 8 height = 8 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_HLSB) # 在LED矩阵上绘制图案 fb.fill(0) # 清空LED矩阵 fb.pixel(3, 3, 1) # 设置像素点 fb.line(0, 0, width - 1, height - 1, 1) # 绘制线条 fb.text("Hi", 1, 4, 1) # 绘制文本 # 将图案显示在LED矩阵上 led_matrix = LEDMatrix() # 假设已经初始化了LEDMatrix对象 led_matrix.show_framebuffer(fb) print("图案显示成功!") 在这个例子中,我们使用 framebuf.FrameBuffer() 函数创建一个帧缓冲对象,用于在 LED 矩阵上绘制图案。可以使用 fill() 方法清空 LED 矩阵,pixel() 方法设置像素点,line() 方法绘制线条,text() 方法绘制文本。最后,使用 led_matrix.show_framebuffer() 方法将图案显示在LED矩阵上。
案例5:游戏开发
import framebuf # 定义游戏窗口尺寸和颜色模式 width = 128 height = 64 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_VLSB) # 游戏循环 while True: fb.fill(0) # 清空屏幕 # 在屏幕上绘制游戏图形和角色 # 处理用户输入 # 更新游戏状态 # 显示更新后的图像 lcd = LCD() # 假设已经初始化了LCD对象 lcd.show_framebuffer(fb)
在这个例子中,我们使用 framebuf.FrameBuffer() 函数创建一个帧缓冲对象,用于在游戏窗口上绘制游戏图形和角色。在游戏循环中,可以使用 fill() 方法清空屏幕,绘制游戏图形和角色,处理用户输入,更新游戏状态,并使用 lcd.show_framebuffer() 方法将更新后的图像显示在屏幕上。
案例6:显示文本
使用 framebuf 模块在屏幕上显示文本信息。
import framebuf # 创建帧缓冲区 width = 128 height = 64 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_VLSB) # 清空屏幕 fb.fill(0) # 设置字体和颜色 font = framebuf.FONT8x8 color = 1 # 在屏幕上绘制文本 fb.text("Hello, World!", 0, 0, color, font) # 显示帧缓冲区内容 display.show(fb)
案例7:绘制图形
使用 framebuf 模块在屏幕上绘制简单的图形,如线条、矩形和圆形。
import framebuf # 创建帧缓冲区 width = 128 height = 64 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_VLSB) # 清空屏幕 fb.fill(0) # 设置颜色 color = 1 # 绘制线条 fb.line(0, 0, 127, 63, color) # 绘制矩形 fb.rect(10, 10, 50, 30, color) # 绘制圆形 fb.circle(64, 32, 20, color) # 显示帧缓冲区内容 display.show(fb)
案例8:显示图像
使用 framebuf 模块加载和显示图像文件。
import framebuf # 加载图像文件 with open('image.pbm', 'rb') as f: f.readline() # 读取PBM文件头 f.readline() # 读取图像尺寸 data = bytearray(f.read()) # 创建帧缓冲区 width = 128 height = 64 buf = bytearray(width * height // 8) fb = framebuf.FrameBuffer(buf, width, height, framebuf.MONO_VLSB) # 清空屏幕 fb.fill(0) # 在帧缓冲区中绘制图像 fb.blit(data, 0, 0, width, height, 0, 0) # 显示帧缓冲区内容 display.show(fb)
这些案例展示了 MicroPython 的 framebuf 模块的一些实际运用程序。通过使用 framebuf 模块,可以在 MicroPython 设备上显示文本、绘制图形和显示图像等操作。你可以根据具体的应用需求进一步扩展和优化这些案例。请注意,在使用 framebuf 模块时,需要根据具体的硬件和显示设备进行相应的配置和适配。
转自:https://blog.csdn.net/weixin_41659040/article/details/132835872
发表评论