【雕爷学编程】MicroPython手册之 ESP32 特定端口库 esp32.ULP.load_binary()

在这里插入图片描述

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的esp是指针对ESP8266和ESP32芯片的MicroPython固件和相关软件库。ESP8266和ESP32是一类广泛应用于物联网和嵌入式系统的低成本、低功耗的Wi-Fi和蓝牙模块。MicroPython的esp为这两种芯片提供了高级的脚本编程环境,使开发者能够使用Python语言进行快速原型设计和开发。

ESP8266:是一款低成本、低功耗的Wi-Fi模块/芯片,由Espressif Systems开发。它内置了TCP/IP协议栈,可以用于连接互联网,并具备较强的处理能力。MicroPython的esp提供了针对ESP8266的固件和相关软件库,使开发者可以使用MicroPython语言进行ESP8266应用的开发。

ESP32:是Espressif Systems推出的一款高度集成的Wi-Fi和蓝牙模块/芯片,与ESP8266相比,它具备更强大的处理能力、更多的外设接口和更多的内存。MicroPython的esp也提供了针对ESP32的固件和相关软件库,使开发者可以使用MicroPython语言进行ESP32应用的开发。

MicroPython的esp固件:是专门针对ESP8266和ESP32芯片的MicroPython固件版本。这些固件经过了针对性的优化,使得它们可以在ESP8266和ESP32上运行,并提供了与硬件交互、网络通信和外设控制等功能的API。

软件库:MicroPython的esp还提供了一系列与ESP8266和ESP32硬件相关的软件库,用于简化和加速开发过程。这些软件库提供了丰富的功能接口,涵盖了Wi-Fi、蓝牙、GPIO(通用输入输出)、I2C、SPI、PWM等常用的硬件和通信协议,使开发者可以方便地访问和控制硬件资源。
在这里插入图片描述
MicroPython的esp32.ULP.load_binary()是一个用于加载二进制文件到ULP(Ultra Low-Power)协处理器内存中的方法。它有以下主要特点、应用场景和注意事项:

主要特点:

esp32.ULP.load_binary()是一个esp32.ULP类的方法,它可以作用于任何一个ULP协处理器的对象。
esp32.ULP.load_binary()的功能是将一个字节对象,即一个包含ULP机器码的二进制文件,加载到ULP协处理器内存中的指定地址。
esp32.ULP.load_binary()的返回值是None,表示加载成功。
esp32.ULP.load_binary()的参数有两个,第一个是一个整数,表示加载地址,范围为0-409512。第二个是一个字节对象,表示要加载的二进制文件。
esp32.ULP.load_binary()的默认参数是0和空字节对象,表示不加载任何内容。

应用场景:

esp32.ULP.load_binary()的功能可以用于在ESP32上直接编译或下载ULP汇编程序,并将其加载到ULP协处理器内存中,准备运行。
esp32.ULP.load_binary()的功能可以用于在ESP32上动态修改或替换ULP协处理器内存中的程序,实现不同的功能或逻辑。
esp32.ULP.load_binary()的功能还可以用于在ESP32上保存或恢复ULP协处理器内存中的程序,实现持久化或备份。

注意事项:

esp32.ULP.load_binary()的功能需要注意与其他占用ULP协处理器或引脚的功能的冲突,例如SPI、I2C、UART等。
esp32.ULP.load_binary()的功能需要注意与其他占用共享内存或中断信号的功能的影响,例如网络通信、文件系统、垃圾回收等。
esp32.ULP.load_binary()的功能需要注意与其他需要中断服务或定时器服务的功能的协调,例如机器定时器、机器中断等。

以下是几个使用MicroPython的esp32.ULP.load_binary()方法的实际运用程序案例:

案例一:使用esp32.ULP.load_binary()来加载一个由py-esp32-ulp编译生成的二进制文件,该文件实现了一个简单的计数器功能,并将结果存储在共享内存中。

# 导入必要的模块
import esp32
import machine
import py_esp32_ulp

# 定义一个计数器程序的源代码,使用py-esp32-ulp提供的汇编语法
counter_src = """
data: .long 0
entry: move r3, data
loop:  add r3, r3, 1
       move r0, r3
       store r0, r3, 0
       wait 1000
       jump loop
"""

# 使用py_esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
counter_bin = py_esp32_ulp.assemble(counter_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为0,表示不唤醒主CPU
esp32.ULP.set_wakeup_period(0)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, counter_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 使用machine.deepsleep()函数来让主CPU进入深度睡眠模式,ULP协处理器继续运行
machine.deepsleep()

# 使用esp32.ULP.mem_read()函数来读取共享内存中的数据,地址为0,返回一个整数
counter = esp32.ULP.mem_read(0)

# 打印出计数器的值
print(counter)

案例二:使用esp32.ULP.load_binary()来加载一个由micropython-esp32-ulp编译生成的二进制文件,该文件实现了一个简单的温度传感器功能,并将结果存储在共享内存中。

# 导入必要的模块
import esp32
import machine
import esp32_ulp

# 定义一个温度传感器程序的源代码,使用esp32_ulp提供的汇编语法
temp_src = """
data: .long 0
entry: tsens r0, 850 # 读取温度传感器的值,延迟850个周期
       move r3, data # 将数据地址存入r3寄存器
       store r0, r3, 0 # 将温度值存入数据地址
       halt # 停止执行
"""

# 使用esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
temp_bin = esp32_ulp.assemble(temp_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为1000000,表示每隔1秒唤醒一次主CPU
esp32.ULP.set_wakeup_period(0, 1000000)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, temp_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 定义一个循环,每隔1秒打印出温度值,并让主CPU重新进入睡眠模式
while True:
    # 使用esp32.ULP.mem_read()函数来读取共享内存中的数据,地址为0,返回一个整数
    temp = esp32.ULP.mem_read(0)
    # 打印出温度值,单位为摄氏度
    print(temp / 2 - 40)
    # 使用machine.lightsleep()函数来让主CPU进入轻度睡眠模式,等待下一次唤醒
    machine.lightsleep()

案例三:使用esp32.ULP.load_binary()来加载一个由binutils-esp32ulp编译生成的二进制文件,该文件实现了一个简单的PWM(脉冲宽度调制)功能,并将结果输出到引脚上。

# 导入必要的模块
import esp32
import machine
import py_esp32_ulp

# 定义一个LED灯闪烁程序的源代码,使用py-esp32-ulp提供的汇编语法
led_src = """
data: .long 0
entry: move r3, data # 将数据地址存入r3寄存器
       load r0, r3, 0 # 将数据值加载到r0寄存器
       move r1, 18 # 将引脚号18存入r1寄存器
       i2c_rd r2, r1, 28, 1 # 读取GPIO_OUT寄存器的值,存入r2寄存器
       xor r2, r2, r0 # 将r2和r0做异或运算,得到反转后的值,存入r2寄存器
       i2c_wr r2, r1, 28, 1 # 将r2的值写入GPIO_OUT寄存器,控制LED灯的状态
       store r2, r3, 0 # 将r2的值存回数据地址,更新数据值
       wait 1000000 # 等待1000000个周期(约为1秒)
       jump entry # 跳转到entry标签,重复执行
"""

# 使用py_esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
led_bin = py_esp32_ulp.assemble(led_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为0,表示不唤醒主CPU
esp32.ULP.set_wakeup_period(0)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, led_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 此时,ESP32的第18号引脚会每隔1秒反转一次电平,从而控制LED灯的闪烁

案例四:加载ULP程序二进制代码:

import esp32
with open('ulp_code.bin', 'rb') as f:
bin_data = f.read()
esp32.ULP.load_binary(bin_data)

案例五:从Flash读出ULP代码加载:

import esp32
buf = esp32.flash_read(addr, size)
esp32.ULP.load_binary(buf)

案例六:删除已加载的ULP程序:

import esp32
esp32.ULP.load_binary(b'')

第一个示例从文件读取二进制数据并加载到ULP。第二个示例从Flash加载ULP代码。第三个示例清除之前加载的ULP程序。此函数用于加载预编译好的ULP二进制代码。通过它可以实现ULP程序的动态加载,常用于固件升级场景。与Flash读写配合可以实现ULP程序的灵活管理。

案例七:加载 ULP 程序的二进制代码:

import esp32

# 定义 ULP 程序的二进制代码
ulp_binary_code = b'\x00\x00\x00\x00\x00\x00\x00\x00'  # 请替换为实际的二进制代码

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

这个示例程序展示了如何使用 load_binary() 方法将 ULP 程序的二进制代码加载到 ULP 协处理器中。

案例八: 从文件加载 ULP 程序的二进制代码:

import esp32

# 从文件中读取 ULP 程序的二进制代码
with open('ulp_program.bin', 'rb') as file:
    ulp_binary_code = file.read()

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

这个示例程序展示了如何从文件中读取 ULP 程序的二进制代码,并使用 load_binary() 方法将其加载到 ULP 协处理器中。请确保将实际的二进制代码文件路径替换为 “ulp_program.bin”。

案例九:使用 ULP 程序生成工具加载 ULP 程序的二进制代码:

import esp32
import ulptool

# 使用 ULP 程序生成工具生成 ULP 程序的二进制代码
ulp_source_code = """
    .section .ulp_text
    .global function_entry
    function_entry:
        # ULP 程序代码,请根据实际需求编写
"""

ulp_binary_code = ulptool.assemble(ulp_source_code)

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

这个示例程序展示了如何使用 ulptool 模块中的 ULP 程序生成工具,通过编写 ULP 程序的源代码并使用 assemble() 方法生成二进制代码,然后使用 load_binary() 方法将其加载到 ULP 协处理器中。请根据实际需求编写 ULP 程序代码。

这些示例程序展示了如何使用 esp32.ULP.load_binary() 方法在 ESP32 的 ULP 协处理器上加载二进制代码。您可以将二进制代码直接提供给方法,从文件中读取代码,或使用 ULP 程序生成工具生成代码。请确保提供的二进制代码符合 ULP 协处理器的要求,并正确加载到 ULP 协处理器中。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41659040/article/details/132944049