差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
mp_ws2812b [2021/10/07 22:14]
gongyusu
mp_ws2812b [2021/10/07 23:36] (当前版本)
gongyusu [2. 一个真实的例子]
行 14: 行 14:
 ### 1. 数据输入和数据输出 ### 1. 数据输入和数据输出
  
-在本书中,我们讨论了使用MicroPython控制Pico上的引脚的方法。我们可以使用专用的SPI和I2C控制器打开和关闭它们,获取输入,甚至发送数据。然而,如果我们想要连接一个不使用SPI或I2C通信的设备,该怎么办?​如果它有自己的特殊协议呢?​+在本书中,我们讨论了使用MicroPython控制Pico上的引脚的方法。我们可以使用专用的SPI和I2C控制器打开和关闭它们,获取输入,甚至发送数据。然而,如果我们想要连接一个不使用SPI或I2C通信的设备,该怎么办?​ 如果它有自己的特殊协议呢?​
  
 有几种方法可以做到这一点。在大多数MicroPython设备上,你需要做一个叫做“位敲打”的过程,在这个过程中你在MicroPython中实现协议。使用此功能,您可以按正确的顺序打开或关闭引脚以发送数据。 有几种方法可以做到这一点。在大多数MicroPython设备上,你需要做一个叫做“位敲打”的过程,在这个过程中你在MicroPython中实现协议。使用此功能,您可以按正确的顺序打开或关闭引脚以发送数据。
  
-这样做有三个缺点。首先是它的速度很慢。MicroPython在某些方面做得非常好,但它的运行速度不如本地编译的代码快。+这样做有三个缺点。 
 +  * 首先是它的速度很慢。MicroPython在某些方面做得非常好,但它的运行速度不如本地编译的代码快。 
 +  * 第二,我们必须把这个和在微控制器上运行的其他代码混在一起。 
 +  * 第三,一些时间关键的代码可能很难可靠地实现。快速协议可能需要事情在非常精确的时间发生,而使用MicroPython,我们可以非常精确,但如果你试图每秒传输兆比特,你需要事情每毫秒或可能每几百纳秒发生、这在MicroPython中很难可靠地实现
  
-第二,我们必须把这个和在微控制器上运行的其他代码混在一起。 +Pico对此有一个解决方案:​可编程I/​O。有一些额外的真正剥离的处理核心,可以运行简单的程序来控制IO引脚。你不能用MicroPython对这些核心进行编程你必须为它们使用一种特殊的语言但你可以从MicroPython对它们进行编程。让我们来看一个例子
- +
-第三,一些时间关键的代码可能很难可靠地实现。快速协议可能需要事情在非常精确的时间发生,而使用MicroPython,我们可以非常精确,但如果你试图每秒传输兆比特,你需要事情每毫秒或可能每几百纳秒发生。这在MicroPython中很难可靠地实现。 +
- +
-Pico对此有一个解决方案:​可编程I/​O。有一些额外的真正剥离的处理核心,可以运行简单的程序来控制IO引脚。你不能用MicroPython对这些核心进行编程——你必须为它们使用一种特殊的语言——但你可以从MicroPython对它们进行编程。让我们来看一个例子+
 <code python> <code python>
 from rp2 import PIO, StateMachine,​ asm_pio ​ from rp2 import PIO, StateMachine,​ asm_pio ​
行 63: 行 62:
 </​code>​ </​code>​
  
-这里有三种方法,看起来都有点奇怪,但将板载LED设置为四分之一、一半和全亮度。它们看起来有点奇怪的原因是它们是用一种特殊的语言为Pico的PIO系统编写的。你大概可以猜到它们是做什么的-  ​以一种类似于我们如何使用PWM的方式快速打开和关闭LED。指令:​+这里有三种方法,看起来都有点奇怪,但将板载LED设置为四分之一、一半和全亮度。它们看起来有点奇怪的原因是它们是用一种特殊的语言为Pico的PIO系统编写的。你大概可以猜到它们是做什么的以一种类似于我们如何使用PWM的方式快速打开和关闭LED。指令:​
   * set(pins,0) 关闭GPIO引脚   * set(pins,0) 关闭GPIO引脚
   * set(pins,1) 打开GPIO引脚。   * set(pins,1) 打开GPIO引脚。
行 87: 行 86:
  
 ### 2. 一个真实的例子 ### 2. 一个真实的例子
-前面的示例有点做作,所以让我们通过一个实际示例来看看使用PIO的方法。WS2812B led(有时也被称为NeoPixels)是一种包含三个led(一个红、一个绿、一个蓝)和一个小微控制器的光。它们是由一根数据线控制的,该数据线有一个时间依赖协议,很难对数据进行实时控制。 +前面的示例有点做作,所以让我们通过一个实际示例来看看使用PIO的方法。WS2812B led(有时也被称为NeoPixels)是一种包含三个led(一个红、一个绿、一个蓝)和一个小微控制器的。它们是由一根数据线控制的,该数据线有一个时间依赖协议,很难对数据进行实时控制。
-LED条的布线很简单,如图C-1所示。取决于你的LED带的制造商,你可能已经有电线连接,你可能有一个插座,你可以推动头部电线,或你可能需要焊接他们自己。 +
- +
-你需要知道的一件事是潜在的电流吸引。虽然你可以在你的Pico上添加几乎无穷无尽的新像素系列,但你可以从Pico上的5v引脚获得的功率是有限的。在这里,我们将使用8个led,这是非常安全的,但如果你想使用更多的led,你需要了解其局限性,可能需要添加一个单独的电源。你可以把长条切成长度,led之间应该有切线,告诉你在哪里切。在hsmag.cc/​neopixelpower上有关于各种问题的很好的讨论+
  
-现在我们已经把led连接起来了,让我们看看如何用PIO来控制它:​+让我们看看如何用PIO来控制它:​
 <code python> <code python>
 import array, utime import array, utime
行 100: 行 96:
  
 # Configure the number of WS2812 LEDs.  # Configure the number of WS2812 LEDs. 
-NUM_LEDS = 10+NUM_LEDS = 12
  
 @asm_pio(sideset_init=PIO.OUT_LOW,​ out_shiftdir=PIO.SHIFT_LEFT,​ autopull=True,​ pull_thresh=24) @asm_pio(sideset_init=PIO.OUT_LOW,​ out_shiftdir=PIO.SHIFT_LEFT,​ autopull=True,​ pull_thresh=24)
行 106: 行 102:
     T1 = 2     T1 = 2
     T2 = 5     T2 = 5
-    T3 = 3 label("​bitloop"​) ​+    T3 = 3  
 +    ​label("​bitloop"​) ​
     out(x, 1)  .side(0) [T3 - 1]     out(x, 1)  .side(0) [T3 - 1]
     jmp(not_x, "​do_zero"​) .side(1) ​ [T1 - 1]     jmp(not_x, "​do_zero"​) .side(1) ​ [T1 - 1]
行 121: 行 118:
 </​code>​ </​code>​
  
-数据进入状态机有两个阶段。第一个是称为先进先出(FIFO)的存储器。这是我们的主Python程序发送数据的地方。第二个是输出移位寄存器(OSR)这是out()指令获取数据的地方。这两个是由pull指令连接的,从FIFO取数据,并把它放在OSR。然而,由于我们的程序设置autopull启用阈值为24,每次我们从OSR读取24位,它将从FIFO重新加载。+数据进入状态机有两个阶段。第一个是称为先进先出(FIFO)的存储器。这是我们的主Python程序发送数据的地方。第二个是输出移位寄存器(OSR)这是out()指令获取数据的地方。这两个是由pull指令连接的,从FIFO取数据,并把它放在OSR。然而,由于我们的程序设置autopull启用阈值为24,每次我们从OSR读取24位,它将从FIFO重新加载。
  
 指令out(x,​1)从OSR获取一位数据,并将其放入名为x的变量中(在PIO中只有两个可用变量:​x和y)。 指令out(x,​1)从OSR获取一位数据,并将其放入名为x的变量中(在PIO中只有两个可用变量:​x和y)。
行 195: 行 192:
  
 用于PIO状态机的语言非常稀疏,因此只有少量的指令。除了我们已经看过的,你还可以使用:​ 用于PIO状态机的语言非常稀疏,因此只有少量的指令。除了我们已经看过的,你还可以使用:​
-  * In() -在状态机中移动1到32位(类似于out(),但相反)。Push() -将数据发送到连接状态机和主机的内存中MicroPython程序。 +  * In( ) -在状态机中移动1到32位(类似于out(),但相反)。Push() -将数据发送到连接状态机和主机的内存中MicroPython程序。 
-  * pull() -从连接状态机和主MicroPython程序的内存块中获取数据。这里我们没有使用它,因为在我们的程序中包含了autopull=True,当我们使用out()时,它会自动发生。 +  * pull( ) -从连接状态机和主MicroPython程序的内存块中获取数据。这里我们没有使用它,因为在我们的程序中包含了autopull=True,当我们使用out()时,它会自动发生。 
-  * Mov() -在两个位置之间移动数据(例如x和y变量)。 +  * Mov( ) -在两个位置之间移动数据(例如x和y变量)。 
-  * Irq()——控制中断。如果您需要在程序的MicroPython端触发一个特定的东西来运行,则使用这些。 +  * Irq( )——控制中断。如果您需要在程序的MicroPython端触发一个特定的东西来运行,则使用这些。 
-  * wait() -暂停,直到某件事发生(例如IO引脚改变为设定值或中断发生)。+  * wait( ) -暂停,直到某件事发生(例如IO引脚改变为设定值或中断发生)。
  
 <WRAP center round tip 60%> <WRAP center round tip 60%>