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

在这里插入图片描述

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是一个用于控制和编程ESP32的ULP(Ultra Low-Power)协处理器的模块。它有以下主要特点、应用场景和注意事项:

主要特点:

esp32.ULP模块提供了一些函数和常量,用于加载、运行、停止和监视ULP协处理器上的程序。
esp32.ULP模块还提供了一些函数和常量,用于访问和修改ULP协处理器和主CPU之间的共享内存。
esp32.ULP模块可以与py-esp32-ulp或micropython-esp32-ulp等第三方模块配合使用,实现在MicroPython环境下编写和编译ULP汇编程序 。
应用场景:

esp32.ULP模块的功能可以用于在ESP32的低功耗模式下,执行一些简单的任务,例如监测传感器、控制外设、唤醒主CPU等。
esp32.ULP模块的功能可以用于在主CPU处于正常工作模式时,协助完成一些需要高速或精确时序的任务,例如PWM(脉冲宽度调制)、PPM(脉冲位置调制)、PCM(脉冲编码调制)等。
esp32.ULP模块的功能还可以用于在主CPU和ULP协处理器之间实现数据的交换和同步,例如通过共享内存或中断信号等。

注意事项:

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

以下是几个使用MicroPython的esp32.ULP模块的实际运用程序案例:

案例一:使用esp32.ULP模块来加载和运行一个由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模块来加载和运行一个由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(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模块来加载和运行一个由binutils-esp32ulp编译生成的二进制文件,该文件实现了一个简单的PWM(脉冲宽度调制)功能,并将结果输出到引脚上。

# 导入必要的模块
import esp32

# 定义一个PWM程序的二进制文件,使用binutils-esp32ulp编译生成,保存在ESP32的文件系统中,文件名为pwm.bin

# 使用open()函数来打开二进制文件,并读取其内容,返回一个字节对象
with open('pwm.bin', 'rb') as f:
    pwm_bin = f.read()

# 使用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, pwm_bin)

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

# 此时,ESP32的第18号引脚会输出一个PWM信号,可以用示波器或LED灯观察效果

案例四:加载 ULP 程序并运行:

import esp32

# 定义 ULP 程序
ulp_program = esp32.ULP()

# 将 ULP 程序加载到 ULP 协处理器中
ulp_program.begin()

# 运行 ULP 程序
ulp_program.run()

这个示例程序展示了如何将 ULP 程序加载到 ULP 协处理器中,并开始运行该程序。

案例五: 设置 ULP GPIO 引脚模式和电平:

import esp32

# 定义 ULP 程序
ulp_program = esp32.ULP()

# 设置 ULP GPIO 引脚模式
ulp_program.gpio_pin_mode(0, esp32.ULP.GPIO_MODE_INPUT)

# 设置 ULP GPIO 引脚电平
ulp_program.gpio_pin_write(0, esp32.ULP.GPIO_LEVEL_LOW)

这个示例程序展示了如何使用 gpio_pin_mode() 方法来设置 ULP GPIO 引脚的模式,并使用 gpio_pin_write() 方法来设置 ULP GPIO 引脚的电平。

案例六: 从 ULP 协处理器读取数据:

import esp32

# 定义 ULP 程序
ulp_program = esp32.ULP()

# 从 ULP 协处理器读取数据
data = ulp_program.read_memory(0x20000000, 4)

这个示例程序展示了如何使用 read_memory() 方法从 ULP 协处理器的内存中读取数据。在示例中,它从地址 0x20000000 开始读取 4 字节的数据。

案例七:请注意,使用ULP需要对ESP32进行额外的配置和编程,并且与MicroPython的主要执行环境略有不同。ULP程序需要使用ULP汇编语言进行编写,并通过特定的工具链进行编译和加载。下面是一个示例ULP程序的代码片段,演示了如何在MicroPython中使用ULP来定期唤醒ESP32:

import machine
import esp32

# 加载ULP程序
ulp_code = """
.macro delay_cycles, count
    sub r3, r3, \count
    bge r3, zero, \delay_cycles
.endm

    .section .ulp_main
    .global ulp_main
ulp_main:
    mov r3, 1000000  // 延时1秒
    delay_cycles 1
    sleep
"""

# 配置ULP唤醒定时器
ulp_timer = machine.ULPTimer()
ulp_timer.init(period=5000, mode=machine.ULP_TIMER_ONE_SHOT)

# 配置ULP程序
ulp = machine.ULP()
ulp.load_binary(0, ulp_code)

# 启动ULP
ulp.run()

# 进入深度睡眠模式
machine.deepsleep()

# 唤醒后执行的代码
print("Wake up!")

# 其他操作...

在这个示例程序中,我们首先定义了一个ULP程序的汇编代码。ULP程序使用delay_cycles宏来延时1秒,然后进入睡眠状态。接下来,我们使用machine.ULPTimer()来配置ULP的唤醒定时器,设置为每5秒唤醒一次。然后,我们使用machine.ULP()来配置ULP并加载ULP程序。最后,我们调用machine.deepsleep()进入深度睡眠模式。当ULP定时器触发时,ULP将唤醒ESP32并执行ULP程序。在唤醒后,程序将打印"Wake up!",然后执行其他操作。

这些示例程序展示了如何使用 esp32.ULP 模块与 ESP32 的 ULP 协处理器进行交互。通过加载 ULP 程序、设置 GPIO 引脚模式和电平,以及从 ULP 协处理器读取数据,您可以利用 ULP 协处理器执行一些低功耗的任务,并与主 CPU 进行交互。请注意,ULP 功能在 MicroPython 中的支持程度有限,具体能力和限制请参考官方文档和相关资料。

在这里插入图片描述

猜你喜欢

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