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的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。
使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。
总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
MicroPython的readinto方法是用于从一个文件对象中读取内容并写入到一个字节缓冲区中的方法,它返回实际读取的字节数。
它的主要特点有:
它接受一个必需的参数,表示要写入的字节缓冲区。字节缓冲区可以是一个字节数组、字节串或内存视图等对象,它们都支持修改其中的元素。
它可以从不同类型的文件中读取内容,如文本文件、二进制文件、图片文件等。如果读取的是文本文件,可以指定编码方式,如utf-8、gbk等。如果读取的是二进制文件,可以使用b标志来表示,如rb、wb等。
它会根据文件对象的当前位置来读取内容,并且每次读取后,会将文件对象的位置向后移动相应的字节数。可以使用seek和tell方法来改变或获取文件对象的位置。
它会根据字节缓冲区的大小来确定要读取的字节数。如果文件中的可用数据小于字节缓冲区的大小,它会读取所有的数据并返回实际的字节数。如果文件中的可用数据大于或等于字节缓冲区的大小,它会读取和字节缓冲区相同大小的数据并返回该大小。
MicroPython的readinto方法的应用场景有:
读取固定长度的数据:可以使用readinto方法来从一个已存在的文件中读取固定长度的数据,并存储在一个预先定义好大小的字节缓冲区中。例如,可以从一个二进制文件中每次读取4个字节,并转换为整数,或者从一个图片文件中每次读取16个像素,并在屏幕上显示。
读取网络数据:可以使用readinto方法来从一个网络套接字对象中读取数据,并写入到一个预先定义好大小的字节缓冲区中。例如,可以从一个TCP套接字中每次读取1024个字节,并解析为HTTP响应数据,或者从一个UDP套接字中每次读取512个字节,并解析为DNS查询数据。
优化内存使用:可以使用readinto方法来减少内存分配和复制的开销,提高性能和效率。例如,可以使用一个全局或局部的字节缓冲区来重复地从不同的文件或网络对象中读取数据,并进行处理或分析。
MicroPython的readinto方法需注意事项有:
读取文件时需要指定正确的模式和编码方式,否则可能会出现错误或乱码。
读取文件时需要考虑文件和缓冲区的大小和类型,否则可能会导致数据丢失或错误。
读取文件时可能会出现异常,需要使用try-except语句来捕获和处理。
MicroPython的readinto方法几个实际运用程序案例如下:
案例1:从一个二进制文件中每次读取4个字节,并转换为整数,并打印出来::
import uos
# 打开一个二进制文件,二进制只读模式
f = uos.open('data.bin', 'rb')
# 创建一个大小为4的字节数组,作为缓冲区
buffer = bytearray(4)
# 循环直到文件结束
while True:
# 每次从文件中读取4个字节,并写入到缓冲区中
n = f.readinto(buffer)
# 如果没有数据,跳出循环
if n == 0:
break
# 将缓冲区中的数据转换为小端序整数
value = int.from_bytes(buffer, 'little')
# 打印整数值
print(value)
# 关闭文件
f.close()
案例2:从一个TCP套接字中每次读取1024个字节,并解析为HTTP响应数据,并打印出来::
import uos
import usocket
# 创建一个TCP套接字对象
s = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
# 连接到一个HTTP服务器,端口为80
s.connect(('example.com', 80))
# 发送一个HTTP请求,获取根目录的内容
s.send(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
# 创建一个大小为1024的字节数组,作为缓冲区
buffer = bytearray(1024)
# 创建一个空的字节对象,用于存储响应数据
response = b''
# 循环直到套接字关闭
while True:
# 每次从套接字中读取1024个字节,并写入到缓冲区中
n = s.readinto(buffer)
# 如果没有数据,跳出循环
if n == 0:
break
# 将缓冲区中的数据追加到响应数据中
response += buffer[:n]
# 关闭套接字
s.close()
# 查找头部和正文的分隔符
index = response.find(b'\r\n\r\n')
# 如果找到了分隔符
if index != -1:
# 获取头部数据,并解码为字符串
header = response[:index].decode('utf-8')
# 获取正文数据,并解码为字符串
body = response[index + 4:].decode('utf-8')
# 打印头部和正文数据
print(header)
print(body)
案例3:从一个图片文件中每次读取16个像素,并在屏幕上显示::
import uos
from machine import Pin, SPI
import st7789
# 创建SPI对象,连接到引脚13, 14, 15, 16
spi = SPI(1, baudrate=20000000, polarity=1, phase=0, sck=Pin(13), mosi=Pin(14), miso=Pin(15))
# 创建ST7789对象,连接到引脚17, 18, 19
tft = st7789.ST7789(spi, 240, 240, reset=Pin(17), cs=Pin(18), dc=Pin(19))
# 打开一张图片文件,二进制只读模式
f = uos.open('image.jpg', 'rb')
# 读取图片的宽度和高度
width = int.from_bytes(f.read(2), 'little')
height = int.from_bytes(f.read(2), 'little')
# 创建一个大小为16*3的字节数组,作为缓冲区
buffer = bytearray(16 * 3)
# 初始化x和y坐标
x = 0
y = 0
# 循环直到文件结束
while True:
# 每次从文件中读取16个像素,每个像素3个字节,并写入到缓冲区中
n = f.readinto(buffer)
# 如果没有数据,跳出循环
if n == 0:
break
# 遍历每个像素
for i in range(0, n, 3):
# 获取RGB值
r = buffer[i]
g = buffer[i + 1]
b = buffer[i + 2]
# 在屏幕上显示像素
tft.pixel(x, y, st7789.color565(r, g, b))
# 更新x坐标,如果超过宽度,换行
x += 1
if x >= width:
x = 0
y += 1
# 关闭文件
f.close()
案例4:读取二进制文件到字节数组:
# 打开二进制文件
with open('data.bin', 'rb') as file:
# 读取文件内容到字节数组
buffer = bytearray(1024) # 创建一个1024字节的字节数组
size = file.readinto(buffer)
# 打印读取的字节数和内容
print('读取了', size, '字节')
print(buffer[:size])
在这个示例中,我们使用open()函数以二进制读取模式打开一个名为data.bin的文件。然后,使用readinto()方法将文件内容读取到一个预先创建的字节数组buffer中(这里创建了一个1024字节的数组)。readinto()函数返回实际读取的字节数,并将内容存储在buffer中。最后,我们打印读取的字节数和字节数组的内容。
案例5:读取并解析二进制数据结构:
import struct
# 打开二进制文件
with open('data.bin', 'rb') as file:
# 定义数据结构格式
format_string = 'i f'
# 创建缓冲区
buffer = bytearray(struct.calcsize(format_string))
# 读取二进制数据到缓冲区
bytes_read = file.readinto(buffer)
# 解析数据
data = struct.unpack(format_string, buffer)
# 打印解析的数据
print("解析数据:", data)
在这个示例中,我们使用open()函数以二进制读取模式打开一个名为data.bin的文件。然后,我们定义了一个数据结构的格式字符串,这里使用i代表整数和f代表浮点数。接下来,我们使用struct.calcsize()函数计算出格式字符串对应的缓冲区大小,并创建一个相应大小的字节数组buffer来存储读取的数据。使用readinto()方法将二进制数据读取到缓冲区,并返回实际读取的字节数。最后,我们使用struct.unpack()函数解析缓冲区中的数据,并将其存储在变量data中。最终,我们打印解析的数据。
案例6:读取串口数据到字节数组::
import machine
# 打开串口
uart = machine.UART(0, 9600)
uart.init(9600, bits=8, parity=None, stop=1)
# 创建字节数组
buffer = bytearray(64)
while True:
# 读取串口数据到字节数组
bytes_read = uart.readinto(buffer)
# 打印读取的字节数和数据
print("读取字节数:", bytes_read)
print("数据:", buffer[:bytes_read])
在这个示例中,我们使用machine.UART()函数打开一个串口,并初始化其参数,如波特率、数据位数、校验位和停止位。然后,我们创建一个长度为64的字节数组buffer来存储从串口读取的数据。在一个循环中,使用readinto()方法将串口数据读取到字节数组中,并返回实际读取的字节数。最后,我们打印读取的字节数和存储在字节数组中的数据。这个示例展示了如何使用readinto()函数读取串口数据到字节数组,用于实时数据采集和处理。
案例7:从文件读取二进制数据到缓冲区
import array
filename = "data.bin"
buffer_size = 1024
# 创建缓冲区
buffer = array.array("B", [0] * buffer_size)
# 打开文件以读取数据
file = open(filename, "rb")
bytes_read = file.readinto(buffer)
file.close()
print("Bytes read:", bytes_read)
print("Data:", buffer[:bytes_read])
在这个例子中,我们创建了一个指定大小的缓冲区,然后使用 readinto() 方法将文件中的二进制数据读取到缓冲区中。readinto() 方法返回实际读取的字节数。最后,我们打印读取的字节数和缓冲区中的数据。
案例8:读取串口数据到缓冲区
import machine
uart = machine.UART(0, 115200) # 假设使用 UART0,波特率为 115200
buffer_size = 128
# 创建缓冲区
buffer = bytearray(buffer_size)
# 从串口读取数据到缓冲区
bytes_read = uart.readinto(buffer)
print("Bytes read:", bytes_read)
print("Data:", buffer[:bytes_read])
在这个例子中,我们使用 MicroPython 的 machine.UART 类来初始化串口对象。然后,我们创建了一个指定大小的缓冲区,并使用 readinto() 方法从串口读取数据到缓冲区中。readinto() 方法返回实际读取的字节数。最后,我们打印读取的字节数和缓冲区中的数据。
案例9: 从网络套接字读取数据到缓冲区
import usocket
buffer_size = 1024
# 创建缓冲区
buffer = bytearray(buffer_size)
# 连接到远程服务器
sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
sock.connect(("example.com", 80))
# 从套接字读取数据到缓冲区
bytes_read = sock.recv_into(buffer)
print("Bytes read:", bytes_read)
print("Data:", buffer[:bytes_read])
# 关闭套接字连接
sock.close()
在这个例子中,我们使用 MicroPython 的 usocket 模块创建套接字对象,并连接到远程服务器(假设是 “example.com” 的 80 端口)。然后,我们创建了一个指定大小的缓冲区,并使用 recv_into() 方法从套接字读取数据到缓冲区中。recv_into() 方法返回实际读取的字节数。最后,我们打印读取的字节数和缓冲区中的数据。
这些实际运用程序案例展示了如何使用MicroPython的readinto()函数进行不同场景下的数据读取操作。您可以根据具体需求,将读取的数据存储到字节数组中,进行数据解析、处理或实时数据采集等操作。请注意,在使用readinto()函数时,要确保缓冲区的大小足够容纳要读取的数据,并适当处理读取的字节数和读取的数据。