树莓派48/100 - 深入研究WS2812彩灯PIO汇编程序
关于树莓派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汇编程序相关推荐
- arduino彩灯计时器电路_用树莓派或 Arduino 制造 LED 矩阵彩灯
MAKER:maketvee/译:趣无尽 Cherry(转载请注明出处) 之前我们介绍过一款非常炫酷的<熔岩特效灯>.这期教程中我将为大家介绍一款更易上手的灯. 这款 LED 矩阵彩灯使用 ...
- 使用树莓派控制led灯板 ws2812
使用树莓派控制led灯板ws2812 推荐一个库 Adafruit_NeoPixel 这里是地址:https://github.com/adafruit/Adafruit_NeoPixel 这个原本是 ...
- 读债务危机0901:第三部分48个案例研究概要-核心术语表 1、国际收支差额:一个国家/货币区的个人或机构与世界其他地区之间进行的所有交易的余额。 2、国际收支危机:经济危机的一种,表现为一国的国际收
graph TD; A–>读债务危机0901:第三部分48个案例研究概要-核心术语表 1.国际收支差额:一个国家/货币区的个人或机构与世界其他地区之间进行的所有交易的余额. 2.国际收支危机:经 ...
- 最简单DIY基于ESP8266的智能彩灯⑦(APP通过彩虹调色板和WIFI控制WS2812彩灯)
ESP8266和ESP32智能彩灯开发系列文章目录 第一篇:最简单DIY基于ESP8266的智能彩灯①(在网页用按钮点亮普通RGB灯) 第二篇:最简单DIY基于ESP8266的智能彩灯②(在网页用按键 ...
- 08.ESP8266驱动WS2812彩灯
本篇介绍ESP8266使用NeoPixel库来驱动IOT Kit板载WS2812彩灯. 1. WS2812彩灯介绍 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,外型与5050LE ...
- 树莓4派开机动画_树莓派的 100 种玩法 2 - 树莓派 4 更新 EEPROM
树莓派 4 自带了 EEPROM (4MBits/512KB) 用于启动系统. 安装比较新的系统或安装 ESXi 需要更新树莓派 4 的 EEPROM. 本文教大家如何更新树莓派4 的EEPROM. ...
- 树莓派40/100 - Pico控制WS2812B,一根信号线实现多种LED灯光效果(1)
从某多平台花了15元钱买了一米长的WS2812B彩灯,用于我的Pico编程试验,这种灯的神奇之处在于只需一根信号线,能够控制串联在一起的30颗LED灯珠(好像能长达1024颗灯),实现各种彩灯效果. ...
- 树莓派32/100 - Pico连接温湿度传感器
DHT11是一个廉价的温湿度传感器,它只有1平方厘米大小,加上一个小转接板,也没多大,接线也简单,除了正负极之外,只需再接一根信号线. 我一开始以为它要用到ADC,所以把信号线接到了Pico的GP26 ...
- 树莓派56/100 - 用Pico连接蜂鸣器演奏音乐,用来纪念儿时玩的超级玛丽游戏
在第18篇文章里,介绍了有源和无源蜂鸣器,通过控制蜂鸣器的频率,也可以发出简单的音乐,这篇文章里介绍了简单的乐理知识,可惜我五音不全,只能把这些频率数据抄下来,更精确的频率数据见这里. 也大概学习了十 ...
- 树莓派44/100 - 先让Pico小车跑起来再说
这两天从某多平台买的小车底盘配件.电池.电源输出模块陆续到货,终于把我的Pico小车组装起来了,先晒图: 配件清单: 1)Pico,32元,如果自己焊针,只要30元 2)400孔小面包板,3.7元,为 ...
最新文章
- request.getparameter特殊字符变成?号问号_15 个不可不知的 Linux 特殊字符,你懂几个?...
- 关于Matconvnet中Conv-ReLU-Pool-NormBatch的总结与思考
- OpenWrt——配置L2TP客户端
- 个人计算机与手机的区别,手机与电脑的CPU是一回事吗?一共有六大区别,看看你知道多少!...
- 我的HTML学习之路02
- 雷军:小米生死靠技术!
- Linux系统启动流程图
- Gulp模块报错:Did you forget to signal async completion? 处理
- Python学习-2.安装IDE
- SQLserver数据库还原后显示正在还原
- 项目管理知识体系指南 (五)
- 从购买服务器到网站搭建成功保姆级教程~超详细
- 解决U盘文件变成快捷方式的最佳方法
- 近红外光谱分析仪的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- Python中的base64、base32实例
- CCF-201409-5-拼图
- 精品软件 推荐 酷我音乐 一个可以下载320k 音质的音乐播放软件
- ARTS-第二周(2019.07.08)
- DOM的绑定事件事件
- 13、backbone实战:webchat(二)详细设计
热门文章
- 能力素质有所欠缺_任职资格体系之七:员工能力评价模型
- 5ic计算机考试考卷读取错误,北京自考出现错误试卷
- 测试串口和串口线是否正常, 能否正常收发数据 !
- 彻底弄懂 Nginx location 匹配
- java界面加入图片_JAVA界面设计怎么插入背景图片。
- 无法获取 vmci 驱动程序版本句柄无效解决办法
- 分享一个python连接zookeeper的坑:句柄无效
- vue2使用element UI中Descriptions组件的遍历问题
- 北京科技大学计算机考研考试科目,2020考研北京科技大学计算机考研考试科目...
- Vue项目JS脚本错误捕获