首先,这个小 MCU 没有做很多事情。它没有大量的代码空间(1K 字),没有大量的 RAM(64 字节),甚至不进行硬件乘法。 它也没有从 ROM 加载数据的指令(尽管有一些方法可以解决这个问题 - 但这是另一篇文章的主题)。当然,您只能对其进行一次编程
PMS150C U06 不适合 SOIC8 突破
Padauk IDE“代码生成器”
那么..它能做什么?闪烁灯?嗯,是的……还有更多。
尽管它有其局限性,但实际上只需使用 8Mhz 微控制器进行 bitbanging 就可以做很多事情。正如您在下面 IDE 的屏幕截图中看到的,它实际上旨在与一堆外围设备一起工作 - 尽管其中任何一个都没有硬件支持。
Padauk IDE“代码生成器”
当然,EEVBlog 论坛上有一些非常聪明的人正在努力为这些芯片创建开放工具链,但我决定迫不及待地开始使用制造商 IDE、ICE 和程序员。
为了充分利用手头的工具,IDE 似乎希望您混合使用纯 C、宏和汇编指令,所有这些都混合在一些看起来非常有趣的代码中。我可能不会因为这样说而受到欢迎,但当你习惯它时,它实际上感觉非常直观。这很奇怪,但却很“有趣”。
在我最初的强制性“闪烁测试”之后,我决定尝试一些稍微有用的东西 - 控制 WS2812B LED。由于协议本身依赖于时间非常紧迫的位敲击,我认为这是一个很好的测试。
在我们继续之前,这里有剧透!成功:
但如何呢? Adafruit 的 Arduino 库为每个 LED 使用 3 字节 RAM,那么如何仅用 64 字节 RAM 运行 300 个 LED?
事实证明,这个问题有一个简单的解决方案:不要将每个 LED 都放入 RAM 中。
由于 WS2812B 的时序不是那么严格,因此在为每个 LED 发送 24 位值之间实际上有很多空闲周期的空间。基本上只是动态执行逻辑,而不是将每个 LED 存储在 RAM 中。唯一的缺点是您不能只更改单个 LED 值而保留其余部分。
一旦您了解了 LED 的控制逻辑,就会发现它非常简单。为每个 LED 发送 24 位,并以足够长的延迟结束以使数据锁存。在这种情况下,将每个位保持在 1.25uS 左右,“0”是短高,然后是“长”低,“1”是长高,然后是短低。简单来说:高->低 24 次。长高表示 1,短高表示 0。
以下是数据表中的片段:
对于我来说,+/- 150ns 有足够的余量,PMS150C 运行在 8mhz 下。每个位的+/- 600ns 的情况也是如此。我预计我可以轻松运行 3000 个 LED,而不是 300 个 – 但我没有电源来承受周围那么多的热量
Tim“cpldcpu”早在 2014 年就写了一篇详细的文章,但要么事情发生了变化,要么他弄错了细节,因为在我的测试中,RES 信号需要至少 50uS,当遇到故障时,复位信号越长,更好的。我有一种感觉,如果我没有看到Big Josh 的关于协议实际上有多么简单的帖子,
我永远不会完成这个项目,但遗憾的是他的代码需要一些认真的操作才能移植到 Padauk IDE,所以我最终完全重写了它从头开始,手里拿着 WorldSemi 数据表,对 BigJosh 做了什么有模糊的记忆。非常感谢 Tim 和 BigJosh 的启发!
Padauk PMS150C 成功驱动 300 个 WS2812B LED
那么..代码呢?
下面是我用来与 LED 串对话的最小代码。还有优化的空间,如果您习惯在 AVR 上看到纯 C 项目,我确信其中很多看起来很有趣。首先,Padauk IDE 在数据类型方面有点模糊。不存在“long”这样的东西,在我看来,默认情况下所有类型都是无符号的——尽管我还没有彻底研究过这一点。
Padauk IDE 中唯一可用的数据类型是:
位(1 位)
字节(8 位)
整数(8 位(!))
字(16 位)
EWORD(24 位)
双字(32 位)
不过,关于类型的方便之处在于,可以通过宏访问各个位和字节,而无需对它们进行移位进行任何模糊处理。
例如:
mybyte.4 = 0; //清除mybyte的位4
myEWORD$1 = mybyte; //设置24位EWORD的中间字节
此外,内置宏也非常方便。请参阅下面的代码。控制 WS2812B 所需的所有代码都包含在宏“send1”、“send0”和函数 SendRGB() 中;
SendRGB() 函数是 Padauk IDE 怪异的一个典型例子,包含汇编指令、宏和普通的旧 C。但我能说什么呢:它有效。我可能可以在 while 循环中移动 rgb EWORD x(比 24 个宏 if 更有效),但我决定尝试一下该宏,它对于此目的来说已经足够高效了。其余的代码(我没有在这里包含)是 r、g 和 b 值的基本操作,后跟 show();设置正确的颜色。如果你想看请发表评论,我会把完整的项目放在github上。
根据大众的需求,完整的源代码可以在这里找到:
https://github.com/AndersBNielsen/pms150c-projects
byte red, green, blue; //Could save these three RAM bytes by using the rgb EWORD directly ( rgb$0, rgb$1, rgb$2)
EWORD rgb;
word pixels; //Only has to be a word if number of pixels > 255
define definedPIXELS 300;send1 MACRO
SET1 LED;
.DELAY 5; //Around 0.85uS
$ LED low; //Same as SET0 LED;
// .DELAY 1; //Going around is enough delay 1.25uS in total
ENDM
send0 MACRO
SET1 LED;
.DELAY 2; //Around 0.40uS
$ LED low;
.DELAY 2; //With the loop around 0.85uS
ENDM
void SendRGB (void) {
DISGINT; //Let’s not get interrupted
.FOR bitno, <23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0> //Regular for() loop doesn't work, but at least the compiler can do the hard work
if (rgb.bitno == 0) {
send0;
} else {
send1;
}
.ENDM
ENGINT;
}
void show (void) {
rgb$0 = blue; //I lost track of MSB, LSB and endians.. This is what works.
rgb$1 = red;
rgb$2 = green;
SendRGB();
}
void clearLED (void) {
rgb = 0;
pixels = definedPIXELS;
do {
SendRGB();
} while (–pixels);
.delay 2000; //If you want to make sure the LED-reset is caught, use a longer one.
}
字节红、绿、蓝; //可以直接使用rgb EWORD保存这三个RAM字节(rgb$0, rgb$1, rgb$2)
EWORD rgb;
文字像素; //仅当像素数> 255时才必须是一个单词
定义defineedPIXELS 300;
发送 1 宏
设置 1 LED;
.延迟5; //大约 0.85uS
$ LED 低电平; //与SET0 LED相同;
// .延迟1; //绕一圈就足够
ENDM总共延迟1.25uS
发送 0 宏
设置 1 LED;
.延迟2; //大约 0.40uS
$ LED 低电平;
.延迟2; //循环大约0.85uS
ENDM
无效SendRGB (无效) {
DISGINT; //我们不要被打扰
.FOR bitno, <23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0> //Regular for() loop doesn't work, but at least the compiler can do the hard work
if (rgb.bitno == 0) {
send0;
} else {
send1;
}
.ENDM
ENGINT;
}
void show (void) {
rgb$0 = 蓝色; //我失去了 MSB、LSB 和字节序的踪迹。这就是有效的。
rgb$1 = 红色;
rgb$2 = 绿色;
发送RGB();
}
无效clearLED (void) {
rgb = 0;
像素=定义的PIXELS;
执行 {
SendRGB();
while (-像素);
.延迟2000; //如果你想确保 LED 复位被捕获,请使用更长的。
}
那么.. 为什么我会选择这个而不是大品牌的MCU?
显然,该微控制器的主要卖点是价格。每个 3 美分,比 Pic 同类产品(3000 MOQ)便宜十倍 - pic10f200(34 美分)或 ATtiny10(28 美分 @ 4500 MOQ)。 //Digikey
另外,客户服务也很不错——我在 12 小时内就收到了 Padauk 的电子邮件回复。
PMS150c 的缺点是 OTP 性质、有限的指令集以及有时令人好奇且看似随机的 IDE 文档 - 仅部分翻译成英文。 (虽然从 0.84 到 0.86,每个版本都会变得更好)
如果您正在考虑制作一个带有 ATTiny10 的玩具,并且它不需要做大量繁重的数学运算 – 这可能能够为成本的十分之一。这并不意味着我会很高兴在起搏器中看到它。
它还能做什么?
我的猜测是:比你想象的要多。我有一种感觉,我的下一个项目可能涉及控制nrf24L01+SI24R01 2.4Ghz 无线电模块或经济型 Raspberry Pi 模块。
不管怎样,请告诉我你的想法,指出我的错误,并在评论中让我知道你希望我将来如何处理这件事