本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 # O a! Y/ g% n2 m/ }1 j# X" o 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 # U& V% N+ p, a 仔细一看发现 WS2812一个bit 周期是: " d5 V3 G( p# n1 t4 A3 m TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns1 S1 Y5 s; G) v( `3 m 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。+ f. e; u3 k- M/ V+ j6 F( i SPI=0x8 等于 WS2812的 0) |; I3 I2 T( m/ I( s SPI=0xE 等于 WS2812的 1 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte) c% U+ x: ^& F v$ Q8 o' ^! @ 9 L& z" D* r$ h: ]# v+ E ! A+ Q/ i5 E; d1 j2 a$ o SPI速度及极性配置: SPI只需要配置主机只发模式,这样可以节省一个IO口 驱动整盘WS2812都很轻松 / i2 T/ ]# a h9 B O G: E! z 驱动库说明:' L2 \4 v7 s$ l5 e 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 W" [$ l& w- @6 i0 e6 J B9 y: ]( G 程序移植了Adafruit NeoPixel库函数,1 u- O$ m" B% w$ `9 i: n( D" @ 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上,% Q& R' t) m* G* R 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 5 y! K* N7 W @4 A' L( x 9 x7 Z/ E0 o! C. C0 n0 V" J |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps: f$ l: G: G# X. K9 w
1 y' N) ]4 a( D. v
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{6 O5 v6 u/ `! E" q
uint8_t newBrightness = b + 1;: S4 E) m( W0 x3 J
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value+ a7 l. H2 ^9 k Y2 L8 Y
uint32_t c; |8 W- i( S" [8 J0 D
uint16_t scale,i;
if(newBrightness != swObj->Brightness) 7 F& |# e" X; M5 A, N* Q! Z
{ // Compare against prior value+ }- D$ `. i$ N% S
// Brightness has changed -- re-scale existing data in RAM7 L% @2 T$ c. e0 I' o7 R
7 A2 ] a7 x) G% F
if(oldBrightness == 0) " z) [1 }% L" M9 {# R3 G) Y* J/ N$ B
scale = 0; // Avoid /0
else if(b == 255) 1 c$ N) R3 g. [5 r6 X
scale = 65535 / oldBrightness;' a* P; ^! h( @" I _; ^4 y0 l
else , [* U3 C _% g( W
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
for(i=0; i<swObj->PixelLen; i++)
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色
c = Sw28_ScaleColor(scale, c);. y h8 f: |* y0 r5 ~( X n/ f
Sw28_SetPixelsColor(swObj,i,c);//设置颜色* G/ M4 K" R& Z0 ?+ x$ s
}$ |+ d' y9 v3 t# X
swObj->Brightness = newBrightness;5 I6 D4 V* I3 ^5 r; R
}7 |* m+ q7 F9 O1 v( `
}
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色" {7 K/ j) q0 W% w( \
按照G R B 传输 为 0x00 0xFF 0x00 ; @3 M2 L6 n: s/ F' p1 k
/ L8 B5 `: q% l2 z8 v/ Z. L
转换为二进制/ a7 K% e0 j& E7 S! R
001 001 001 001 001 001 001 001 001 001 001
110 110 110 110 110 110 110 110 110 110 1105 v1 Q2 T* ^' [# z* B
001 001 001 001 001 001 001 001 001 001 001 ' p/ P% ^& B Y6 g' j, i" u
SPI数据为:
0x24 0x92 0x49! ^7 L5 h6 Q, i s) @" b3 e* |
0010 0100 1001 0010 0100 1001 - S4 e6 c0 t# s' l7 }0 ?
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110& m+ {& h. N) W$ V4 P3 s/ b( o
0x24 0x92 0x49 p# z+ U! N2 ^5 s
0010 0100 1001 0010 0100 1001
# A2 o9 e D9 N4 P/ g: S
! L) o6 U4 E* p8 C8 H$ E" k+ U# M
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。