
本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 1 p# o x2 ]& r9 I; O 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 ![]() 1 n- F3 |7 B- |; r3 D 仔细一看发现 WS2812一个bit 周期是: * o, k% ?. V7 K3 H% W+ b3 C+ D TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。 SPI=0x8 等于 WS2812的 0% t5 O* b) E* ~7 f5 w3 ~4 B SPI=0xE 等于 WS2812的 1$ ?# `! o5 Z8 a 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte" j3 n3 p* e9 [; n& a SPI速度及极性配置:2 w9 T8 y- H( F0 |/ H ![]() ) u! l9 l3 Q; ~0 j- y6 m/ v. Z SPI只需要配置主机只发模式,这样可以节省一个IO口 ![]() 3 N% K1 C; C/ Y1 m7 B! X9 d 驱动整盘WS2812都很轻松' k$ I) M! c' Q5 O1 h. p* Y2 k; i ![]() ![]() 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,; L) J) x b& }; X5 i$ P 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 ![]() 7 z% Q, D8 t p2 p- l |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1200
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b) c# `+ x+ R) Y8 {, i" ^) [
{
uint8_t newBrightness = b + 1;
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value5 J c4 c6 O( v3 Q
uint32_t c;
uint16_t scale,i;
if(newBrightness != swObj->Brightness) 2 g! K$ q0 h$ t/ s! `6 d9 w0 i
{ // Compare against prior value) _4 p; [/ M$ x; L7 V1 @2 w
// Brightness has changed -- re-scale existing data in RAM
if(oldBrightness == 0) . l" e: I. L+ g
scale = 0; // Avoid /0
else if(b == 255) , `3 h0 ]+ g2 L; ^2 C
scale = 65535 / oldBrightness;& R' Z7 b8 e/ z/ r
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;- s+ n7 j# U) J ?/ e, ~; ~( Y/ X
) f9 B4 @ w8 [& `7 h
for(i=0; i<swObj->PixelLen; i++)3 R' H6 [6 p1 c- W8 r0 k
{+ H p' e% k: w0 W
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 2 j! x/ E/ f4 b
c = Sw28_ScaleColor(scale, c);' i# K& O1 h `
Sw28_SetPixelsColor(swObj,i,c);//设置颜色8 ~3 P E: b* z8 [* a. B& E9 T4 y
}6 Z+ l' [6 G) M; r5 ^! f
swObj->Brightness = newBrightness;" E: _1 h/ F$ f0 |. n; n
}# D/ e$ Q7 c* v! D Z
}
h: {% T: y9 v" R
: V- ^; K+ P# s6 t
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色2 I F, a' s% I1 E
按照G R B 传输 为 0x00 0xFF 0x00 1 V j8 ?0 D2 T: s0 |
& v [. h* t; m4 x: S6 J9 `) Q
转换为二进制6 b% }7 Z# H3 o4 |, |0 F
001 001 001 001 001 001 001 001 001 001 001
110 110 110 110 110 110 110 110 110 110 1108 K* q+ Y1 O9 ]5 Y& i
001 001 001 001 001 001 001 001 001 001 001
( q7 f; z# A( Y# E% Q
SPI数据为:8 Q9 _4 c5 P6 s+ l( ^% P- y. e$ ?
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001 / s6 t4 r2 W- G+ |% j, {) |
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110" ]0 o3 Z/ L1 R. r
0x24 0x92 0x492 I" M2 S% `! C8 ~0 m8 F9 O
0010 0100 1001 0010 0100 1001
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。