关于树莓派Pico里的PIO(Programmed I/O)编程,前面写过4篇文章:

  • 初识Pico里的PIO,更高级的办法让小灯闪烁

  • 深入研究PIO中的指令周期

  • 看懂PWM里的汇编代码

  • 用PIO的out指令控制七段数码管

以前的WS2812彩灯程序感觉像天书,根本看不懂,现在可以揭开它神秘的面纱了。

import machine
import utime
import array
import rp2@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,autopull=True, pull_thresh=24)
def ws2812():T1 = 2T2 = 5T3 = 3wrap_target()label("bitloop")out(x, 1)               .side(0)    [T3 - 1]jmp(not_x, "do_zero")   .side(1)    [T1 - 1]jmp("bitloop")          .side(1)    [T2 - 1]label("do_zero")nop()                   .side(0)    [T2 - 1]wrap()# 建立状态机,设置输出针的编号
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=machine.Pin(15))
sm.active(1)NUM_LEDS = 30
ar = array.array("I", [0 for _ in range(NUM_LEDS)])while True:for j in range(NUM_LEDS):(r, g, b) = (0, 0, 0)if(j%3 == 0): r = 11if(j%3 == 1): g = 11if(j%3 == 2): b = 11ar[j] = g << 16 | r << 8 | bsm.put(ar, 8)utime.sleep_ms(20)

为了研究pioasm程序的汇编代码,我简化了主程序,只让30个灯依次显示红、绿、蓝三色。

先要了解WS2812特殊的信号机制,与平常的高电位为1、低电位为0的方式不一样,它的协议按高、低电位持续时间的长短来表示0和1,见下图:

如果高电平持续时间小于低电平持续时间,表示0;低电平持续时间长,表示1。持续时间也有严格的范围,以微秒来计。我查到的WS2812B中文手册与国外论坛里看到了指标参数有点差别。


主程序里pioasm状态机的频率为8M赫兹,这样一个汇编指令周期为1/8000000=0.125 us(微秒),看代码里的T1、T2和T3分别为2、5、3,也就对应着0.25 us、0.625 us和0.375 us。

这三个时间的含义如下图:


T0L=T2+T3=1.0us,在指标范围(0.58us ~ 1.6us)内,T1H=T1+T2=0.875,也在指标范围(0.58us ~ 1.6us)内。在T1时间段里永远是高电位,在T3段永远是低电位,T2时间内的电位对应着表示的数据:0或1。

现在可以看汇编代码了,out_shiftdir=rp2.PIO.SHIFT_LEFT 表示OSR里的数据向左移位,autopull=True, pull_thresh=24 表示自动从OSR里取数,而且只取24位(对应着RGB值)。

out(x, 1) 表示从OSR里移出1位数据,放入X寄存器里,后面的.side(0)设置低电位,[T3-1]补满T3指令周期。

jmp(not_x, “do_zero”)的意思是当X为0时跳到 do_zero 位置的代码,当X不为0时,继续执行下面的语句。

x不为0时,执行到 jmp(“bitloop”) 这一句,准备跳转到程序的最开始,跳转前捎带着完成 side(1),因为x不为0,所以side(1),逻辑正确,总延迟时间为T2。

x为0的时候,执行 nop().side(0) 指令,总延迟时间也是T2。

主程序用 array.array(“I”, list) 初始化一个数组,现代计算机的 int 类型一般都是4字节(32位)的整数,用来设置灯组的RGB值(24位)。

sm.put(ar, 8) 用于快速把数组中的所有数据送到状态机的FIFO队列里,第二个参数8表示数据先左移8位,再送到FIFO里。一组彩灯刷新周期里,24位的GRB值(注意顺序是:绿、红、蓝)要一个紧接着一个快速发出去,如果稍有延迟,会被认为是下一组彩灯刷新周期。


我看了一下WS2812B的规格参数,T1=T2=T3=0.375时,也符合各项指标要求,应该也是可以工作的,所以我把程序简化了一下,状态机仍工作在8M Hz频率下,运行完全没问题:

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,autopull=True, pull_thresh=24)
def ws2812():label("bitloop")out(x, 1)               .side(0)    [2]jmp(not_x, "do_zero")   .side(1)    [2]jmp("bitloop")          .side(1)    [2]label("do_zero")nop()                   .side(0)    [2]

如果让状态机工作在2.7M频率下,那么延迟参数也可以省了:

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,autopull=True, pull_thresh=24)
def ws2812():label("bitloop")out(x, 1)               .side(0)    jmp(not_x, "do_zero")   .side(1)    jmp("bitloop")          .side(1)    label("do_zero")nop()                   .side(0)    sm = rp2.StateMachine(0, ws2812, freq=2_700_000, sideset_base=machine.Pin(15))
sm.active(1)

修改的代码在我的WS2812B工作正常,但不知道在旧款的2812上能否正常工作。

推荐阅读:
树莓派Pico开发系列文章

树莓派48/100 - 深入研究WS2812彩灯PIO汇编程序相关推荐

  1. arduino彩灯计时器电路_用树莓派或 Arduino 制造 LED 矩阵彩灯

    MAKER:maketvee/译:趣无尽 Cherry(转载请注明出处) 之前我们介绍过一款非常炫酷的<熔岩特效灯>.这期教程中我将为大家介绍一款更易上手的灯. 这款 LED 矩阵彩灯使用 ...

  2. 使用树莓派控制led灯板 ws2812

    使用树莓派控制led灯板ws2812 推荐一个库 Adafruit_NeoPixel 这里是地址:https://github.com/adafruit/Adafruit_NeoPixel 这个原本是 ...

  3. 读债务危机0901:第三部分48个案例研究概要-核心术语表 1、国际收支差额:一个国家/货币区的个人或机构与世界其他地区之间进行的所有交易的余额。 2、国际收支危机:经济危机的一种,表现为一国的国际收

    graph TD; A–>读债务危机0901:第三部分48个案例研究概要-核心术语表 1.国际收支差额:一个国家/货币区的个人或机构与世界其他地区之间进行的所有交易的余额. 2.国际收支危机:经 ...

  4. 最简单DIY基于ESP8266的智能彩灯⑦(APP通过彩虹调色板和WIFI控制WS2812彩灯)

    ESP8266和ESP32智能彩灯开发系列文章目录 第一篇:最简单DIY基于ESP8266的智能彩灯①(在网页用按钮点亮普通RGB灯) 第二篇:最简单DIY基于ESP8266的智能彩灯②(在网页用按键 ...

  5. 08.ESP8266驱动WS2812彩灯

    本篇介绍ESP8266使用NeoPixel库来驱动IOT Kit板载WS2812彩灯. 1. WS2812彩灯介绍 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,外型与5050LE ...

  6. 树莓4派开机动画_树莓派的 100 种玩法 2 - 树莓派 4 更新 EEPROM

    树莓派 4 自带了 EEPROM (4MBits/512KB) 用于启动系统. 安装比较新的系统或安装 ESXi 需要更新树莓派 4 的 EEPROM. 本文教大家如何更新树莓派4 的EEPROM. ...

  7. 树莓派40/100 - Pico控制WS2812B,一根信号线实现多种LED灯光效果(1)

    从某多平台花了15元钱买了一米长的WS2812B彩灯,用于我的Pico编程试验,这种灯的神奇之处在于只需一根信号线,能够控制串联在一起的30颗LED灯珠(好像能长达1024颗灯),实现各种彩灯效果. ...

  8. 树莓派32/100 - Pico连接温湿度传感器

    DHT11是一个廉价的温湿度传感器,它只有1平方厘米大小,加上一个小转接板,也没多大,接线也简单,除了正负极之外,只需再接一根信号线. 我一开始以为它要用到ADC,所以把信号线接到了Pico的GP26 ...

  9. 树莓派56/100 - 用Pico连接蜂鸣器演奏音乐,用来纪念儿时玩的超级玛丽游戏

    在第18篇文章里,介绍了有源和无源蜂鸣器,通过控制蜂鸣器的频率,也可以发出简单的音乐,这篇文章里介绍了简单的乐理知识,可惜我五音不全,只能把这些频率数据抄下来,更精确的频率数据见这里. 也大概学习了十 ...

  10. 树莓派44/100 - 先让Pico小车跑起来再说

    这两天从某多平台买的小车底盘配件.电池.电源输出模块陆续到货,终于把我的Pico小车组装起来了,先晒图: 配件清单: 1)Pico,32元,如果自己焊针,只要30元 2)400孔小面包板,3.7元,为 ...

最新文章

  1. request.getparameter特殊字符变成?号问号_15 个不可不知的 Linux 特殊字符,你懂几个?...
  2. 关于Matconvnet中Conv-ReLU-Pool-NormBatch的总结与思考
  3. OpenWrt——配置L2TP客户端
  4. 个人计算机与手机的区别,手机与电脑的CPU是一回事吗?一共有六大区别,看看你知道多少!...
  5. 我的HTML学习之路02
  6. 雷军:小米生死靠技术!
  7. Linux系统启动流程图
  8. Gulp模块报错:Did you forget to signal async completion? 处理
  9. Python学习-2.安装IDE
  10. SQLserver数据库还原后显示正在还原
  11. 项目管理知识体系指南 (五)
  12. 从购买服务器到网站搭建成功保姆级教程~超详细
  13. 解决U盘文件变成快捷方式的最佳方法
  14. 近红外光谱分析仪的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  15. Python中的base64、base32实例
  16. CCF-201409-5-拼图
  17. 精品软件 推荐 酷我音乐 一个可以下载320k 音质的音乐播放软件
  18. ARTS-第二周(2019.07.08)
  19. DOM的绑定事件事件
  20. 13、backbone实战:webchat(二)详细设计

热门文章

  1. 能力素质有所欠缺_任职资格体系之七:员工能力评价模型
  2. 5ic计算机考试考卷读取错误,北京自考出现错误试卷
  3. 测试串口和串口线是否正常, 能否正常收发数据 !
  4. 彻底弄懂 Nginx location 匹配
  5. java界面加入图片_JAVA界面设计怎么插入背景图片。
  6. 无法获取 vmci 驱动程序版本句柄无效解决办法
  7. 分享一个python连接zookeeper的坑:句柄无效
  8. vue2使用element UI中Descriptions组件的遍历问题
  9. 北京科技大学计算机考研考试科目,2020考研北京科技大学计算机考研考试科目...
  10. Vue项目JS脚本错误捕获