【雕爷学编程】MicroPython手册之 RP2040 特定端口库 rp2.StateMachine.tx_fifo()-程序员宅基地

技术标签: MicroPython手册  python  嵌入式硬件  MicroPython  RP2040 特定端口库  单片机  

在这里插入图片描述

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进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述

RP2040 是一款由树莓派公司设计的 32 位双核 ARM Cortex-M0+ 微控制器芯片,于 2021 年 1 月发布,作为树莓派 Pico 开发板的核心部件。RP2040 的特点是高性能、低成本、小封装、灵活的 I/O 和独特的可编程 I/O(PIO)子系统。RP2040 还支持 MicroPython、C/C++ 和 TensorFlow Lite 等编程语言和框架,适用于各种创意项目和机器学习应用。

MicroPython 的特定于 RP2040 的库包括以下模块:

rp2:包含特定于 RP2040 的函数和类,如 PIO 相关功能、Flash 类和 StateMachine 类。
machine:包含通用的硬件控制功能,如 Pin、Timer、UART、PWM、ADC 等。
utime:包含时间相关的函数,如 sleep、ticks_ms、ticks_diff 等。
uos:包含操作系统相关的函数,如 uname、mount、remove 等。

这些模块使得 MicroPython 可以充分利用 RP2040 的硬件特性,实现各种创意项目。

在这里插入图片描述
MicroPython 的 rp2.StateMachine.tx_fifo() 是一个用于返回状态机的 TX FIFO 中的字数的方法。状态机是 RP2040 芯片的一种特殊功能,它可以实现自定义的 I/O 行为,例如模拟 SPI、I2C、UART 等协议,或者实现位摇摆 (bit banging) 技术。状态机有两个实例,每个实例有四个编号为 0 到 3 的状态机,共计八个状态机。

rp2.StateMachine.tx_fifo() 的主要特点是:

它可以在任何时候调用,无论状态机是否已经初始化或启动。如果状态机未初始化,则该方法无效。
它可以返回一个整数,表示状态机的 TX FIFO 中的字数。如果返回值为 0,则表示 TX FIFO 为空;如果返回值等于或大于 4,则表示 TX FIFO 已满或溢出。

rp2.StateMachine.tx_fifo() 的应用场景是:

当需要在程序中检查状态机是否有数据可写时,例如在使用状态机模拟 UART、SPI、I2C 等协议时,检查 TX FIFO 中是否有空间写入要发送的数据。
当需要在程序中控制状态机的数据写入速度或频率时,例如在使用状态机模拟高速或高频的 I/O 行为时,根据 TX FIFO 中的字数来决定何时调用 StateMachine.put() 方法。
当需要在程序中处理状态机的数据满载或丢失情况时,例如在使用状态机模拟不可靠的通信协议时,检查 TX FIFO 中的字数是否达到了预期的范围。

rp2.StateMachine.tx_fifo() 的注意事项是:

使用 rp2.StateMachine.tx_fifo() 时,需要注意 TX FIFO 的容量和状态。如果 TX FIFO 为空,则表示没有数据可写;如果 TX FIFO 满了,则表示可能有数据满载或丢失。
使用 rp2.StateMachine.tx_fifo() 时,需要注意数据的格式和长度。如果向 TX FIFO 中写入的数据不符合预期的格式或长度,可能会导致错误或异常。
使用 rp2.StateMachine.tx_fifo() 时,需要注意数据的同步和时序。如果向 TX FIFO 中写入的数据与接收方或其他设备不同步或不匹配,可能会影响数据的传输或处理。

以下是 MicroPython 的 rp2.StateMachine.tx_fifo() 的几个实际运用程序参考代码案例:

案例一:使用状态机 0 实现一个简单的 UART (通用异步收发器) 发送器,并在每次发送一个字节时打印出来。

from machine import Pin
import rp2

# 定义一个 UART 发送程序
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW, sideset_init=(rp2.PIO.OUT_LOW,))
def uart_tx_prog():
    # 设置初始波特率为 9600
    set(x, 103) [31]
    # 设置初始数据位为 8
    set(y, 7) [31]
    label("uartloop")
    # 判断是否有数据要发送(从 TX FIFO 中读取数据)
    pull(block)
    mov(isr, osr)
    # 输出起始位(低电平,side set)
    out(x, 0) .side(0)
    # 等待一个周期
    nop() [31]
    label("outbit")
    # 输出一位数据到输出引脚(side set)
    out(x, 1) .side(isr)
    # 等待一个周期
    mov(x, isr)
    label("waitbit")
    jmp(x_dec, "waitbit")
    # 判断是否输出完所有数据位
    jmp(y_dec, "outbit")
    # 输出停止位(高电平,side set)
    out(x, 0) .side(1)
    # 等待一个周期
    nop() [31]
    # 跳转到循环开始处
    jmp("uartloop")

# 创建状态机 0,从 Pin(17) 发送 UART 数据
sm = rp2.StateMachine(0, uart_tx_prog, freq=1000000, out_base=Pin(17))

# 启动状态机 0
sm.active(1)

# 循环发送字节数据,并打印出来
for i in range(256):
    # 检查 TX FIFO 中的字数
    while sm.tx_fifo() >= 4:
        # 等待 TX FIFO 有空间
        pass
    # 向 TX FIFO 中写入一个字节数据
    sm.put(i)
    # 打印发送的字节数据
    print("UART sent:", i)

案例二:使用状态机 1 实现一个简单的 DAC (数模转换器) 功能,并在每次写入一个 10 位的数字值时将其转换为模拟值。

from machine import Pin
import rp2

# 定义一个 DAC 程序
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def dac_prog():
    # 设置初始输出周期为 1000
    set(x, 999) [31]
    # 设置初始数据位为 10
    set(y, 9) [31]
    label("dacloop")
    # 判断是否有数据要输出(从 TX FIFO 中读取数据)
    pull(block)
    mov(isr, osr)
    # 输出一位数据到输出引脚
    out(pins, 1)
    # 判断是否输出完所有数据位
    jmp(y_dec, "dacloop")
    # 跳转到循环开始处
    jmp("dacloop")

# 创建状态机 1,输出 DAC 数据到 Pin(25)
sm = rp2.StateMachine(1, dac_prog, freq=1000000, out_base=Pin(25))

# 启动状态机 1
sm.active(1)

# 循环写入数字值,并打印出来
for i in range(1024):
    # 检查 TX FIFO 中的字数
    while sm.tx_fifo() >= 4:
        # 等待 TX FIFO 有空间
        pass
    # 向 TX FIFO 中写入一个 10 位的数字值,并左移 6 位,将其转换为 16 位的模拟值
    sm.put(i, shift=6)

案例三:使用状态机 2 和状态机 3 实现一个简单的 SPI (串行外设接口) 主从模式,并在每次发送或接收一个字节时打印出来。这是一个利用状态机的 rp2.StateMachine.put() 方法来向 TX FIFO 中写入数据,以及 rp2.StateMachine.get() 方法来从 RX FIFO 中读取数据的例子。SPI 是一种常用的同步串行通信协议,它由一个主设备和一个或多个从设备组成,通过四根线(片选、时钟、主出从入、主入从出)进行数据的传输。

from machine import Pin
import rp2

# 定义一个 SPI 主机程序
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW, sideset_init=(rp2.PIO.OUT_LOW,))
def spi_master_prog():
    # 设置初始时钟分频为 250(4 MHz)
    set(x, 249) [31]
    # 设置初始数据位为 8
    set(y, 7) [31]
    label("spiloop")
    # 拉低片选引脚(side set)
    set(pindirs, 1) .side(0)
    # 判断是否有数据要发送(从 TX FIFO 中读取数据)
    pull(block)
    mov(isr, osr)
    label("outbit")
    # 输出一位数据到输出引脚(side set)
    out(x, 1) .side(1)
    # 等待半个周期
    nop() [31]
    # 输入一位数据到输入移位寄存器
    in_(pins, 1)
    # 输出另一位数据到输出引脚(side set)
    out(x, 1) .side(0)
    # 等待半个周期
    nop()
    # 判断是否输出完所有数据位
    jmp(y_dec, "outbit")
    # 拉高片选引脚(side set)
    set(pindirs, 1) .side(1)
    # 将输入移位寄存器的内容推送到 RX FIFO
    push()
    # 跳转到循环开始处
    jmp("spiloop")

# 定义一个 SPI 从机程序
@rp2.asm_pio(set_init=rp2.PIO.IN_LOW, sideset_init=(rp2.PIO.OUT_LOW,))
def spi_slave_prog():
    # 设置初始时钟分频为 250(4 MHz)
    set(x, 249) [31]
    # 设置初始数据位为 8
    set(y, 7) [31]
    label("spiloop")
    # 等待片选引脚为低电平
    wait(0, pin, 0)
    label("inbit")
    # 输入一位数据到输入移位寄存器
    in_(pins, 1)
    # 等待半个周期
    nop() [31]
    # 输出一位数据到输出引脚(side set)
    out(x, 1) .side(isr)

案例四:写入单个字节的数据:

import rp2

# 创建 PIO 对象
pio = rp2.PIO(0)

# 设置 PIO 引脚 0 和 1 为输出引脚
pio.set_pins(0, 1 << 0)
pio.set_pins(1, 1 << 1)

# 创建 PIO 状态机
sm = rp2.StateMachine(0, pio, freq=1000000, out_base=pio.base)

# 启动状态机
sm.active(1)

# 写入单个字节的数据
data = 0xAA
sm.tx_fifo(data)

这个示例创建了一个 PIO 对象,并使用 pio.set_pins() 方法将 PIO 引脚 0 和 1 配置为输出引脚。然后,使用 rp2.StateMachine() 创建了一个 PIO 状态机对象 sm。接着,通过调用 sm.active(1) 启动状态机。最后,通过调用 sm.tx_fifo(data) 方法将单个字节的数据写入状态机的发送 FIFO 中。

案例五:写入多个字节的数据:

import rp2

# 创建 PIO 对象
pio = rp2.PIO(0)

# 设置 PIO 引脚 0 和 1 为输出引脚
pio.set_pins(0, 1 << 0)
pio.set_pins(1, 1 << 1)

# 创建 PIO 状态机
sm = rp2.StateMachine(0, pio, freq=1000000, out_base=pio.base)

# 启动状态机
sm.active(1)

# 写入多个字节的数据
data = [0xAA, 0xBB, 0xCC, 0xDD]
for byte in data:
    sm.tx_fifo(byte)

这个示例创建了一个 PIO 对象,并使用 pio.set_pins() 方法将 PIO 引脚 0 和 1 配置为输出引脚。然后,使用 rp2.StateMachine() 创建了一个 PIO 状态机对象 sm。接着,通过调用 sm.active(1) 启动状态机。在循环中,通过遍历列表 data,并调用 sm.tx_fifo(byte) 方法将每个字节数据写入状态机的发送 FIFO 中。

案例六:使用循环连续写入数据:

import rp2
import time

# 创建 PIO 对象
pio = rp2.PIO(0)

# 设置 PIO 引脚 0 和 1 为输出引脚
pio.set_pins(0, 1 << 0)
pio.set_pins(1, 1 << 1)

# 创建 PIO 状态机
sm = rp2.StateMachine(0, pio, freq=1000000, out_base=pio.base)

# 启动状态机
sm.active(1)

# 使用循环连续写入数据
while True:
    # 写入单个字节的数据
    data = 0xAA
    sm.tx_fifo(data)

    # 等待一段时间
    time.sleep(0.1)

这个示例创建了一个 PIO 对象,并使用 pio.set_pins() 方法将 PIO 引脚 0 和 1 配置为输出引脚。然后,使用 rp2.StateMachine() 创建了一个 PIO 状态机对象 sm。接着,通过调用 sm.active(1) 启动状态机。在主循环中,通过调用 sm.tx_fifo(data) 方法将单个字节的数据写入状态机的发送 FIFO 中。然后,通过调用 time.sleep(0.1) 等待一段时间,可以根据实际需求调整等待时间。请注意,这是一个无限循环,如果需要退出循环,可以在适当的条件下使用 break 语句。

请注意,以上示例仅供参考,具体的使用方法可能因不同的硬件平台和MicroPython版本而有所差异。在实际编程中,你需要根据你所使用的硬件和具体需求进行适当的调整。

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41659040/article/details/133179462

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签