本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 8 k1 I6 p9 P! N7 W1 }- N7 G 仔细一看发现 WS2812一个bit 周期是: 5 @& Q3 H* _" q, V3 o0 T4 ~ 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 SPI=0xE 等于 WS2812的 1$ Q |% _+ F( f& l0 ^ 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte 8 j! g2 ~$ b. J* y* t1 H SPI速度及极性配置: - t* }5 a! I5 ?# H, G& Y* P/ | SPI只需要配置主机只发模式,这样可以节省一个IO口 ; x2 b) u& W- D5 H6 u) Z 驱动整盘WS2812都很轻松 驱动库说明:2 L4 \9 c, {+ n 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,* Y5 C4 {7 {. X* Q 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 # R; V- |5 F. b6 O |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps; x. R) y: h' w" T3 _- H
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。! `0 b3 D& o5 U4 f
- G, ]7 N' {( Z; C
- C, x6 j% r) m0 E
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{
uint8_t newBrightness = b + 1;
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c;6 W5 m; W! q0 \/ j# ^ p
uint16_t scale,i; v( y W9 x+ k( |; ~: X" a
if(newBrightness != swObj->Brightness) 5 E7 w5 e- F7 {( j* E
{ // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
if(oldBrightness == 0)
scale = 0; // Avoid /0
else if(b == 255) + H1 q) H- s2 {+ p0 p7 x
scale = 65535 / oldBrightness;- j! e5 k8 ^" `( }( x) |& t
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;- K# F5 p* D: g# F# a O& A. Y8 i
for(i=0; i<swObj->PixelLen; i++)
{6 ?/ a* ~* a4 y; W
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 2 ]1 R. |, D6 l4 x( ?
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色* x% i$ Z/ C+ j* h' T; ?
}) d7 O0 {/ V0 p+ ^5 o" @' Z
swObj->Brightness = newBrightness;- t+ u( Z: z6 \5 D
}2 l+ c' f6 b3 K' f0 O
}
/ V, p+ i6 {7 v- G
5 ?- v" A% U% |
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code 4 z' v* i" B: y
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00
转换为二进制$ D9 R. x9 X3 _: {$ t
001 001 001 001 001 001 001 001 001 001 001
110 110 110 110 110 110 110 110 110 110 110
001 001 001 001 001 001 001 001 001 001 001
# z C# Z8 G( k% U) U5 C# g2 i
SPI数据为:0 \7 i" z! u! i7 v
0x24 0x92 0x49# \2 e; [& I- v$ z; U9 }
0010 0100 1001 0010 0100 1001 $ R( i) B7 o/ {- r; J( O; ^
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110$ Y! I' o: b9 }" C* _& ]
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001 # d0 M- t0 L$ a6 J6 [
( F& U: [3 ?$ Z5 O; z5 E
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG 3 N# ^, @% B! ]" u: {" l
mdk的,论坛里有人分享过了,你可以搜一下
好方法。