|
本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 , R8 v Y: T# }' O) q6 ^( E : ~- K& x y X% \: y 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html9 ^" O/ e% f# e5 g 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。
) c, u. \; z! _/ h 仔细一看发现 WS2812一个bit 周期是: , M& P( H% g. v1 q" r5 a! r! Z0 S TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns: B1 I- L/ @1 f. ~2 |# }4 S; r 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。 SPI=0x8 等于 WS2812的 0" o( f& N. X7 a5 ? SPI=0xE 等于 WS2812的 1) Q9 @& U6 w) h3 {# a2 z8 I 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte/ I3 H% j. F6 G- Z6 c+ r( T/ f* } ! @2 l8 L: ?' N, m# q5 m SPI速度及极性配置:
u, N; Y$ x4 p SPI只需要配置主机只发模式,这样可以节省一个IO口
" N3 l( \. j9 m9 E% X) S 驱动整盘WS2812都很轻松8 C: I% U7 p. T+ I6 D. a' H" B% j
驱动库说明:. {! E* Y. ?5 @0 n. R1 v% l$ h 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程, L/ G! _& \5 ]! z6 a 程序移植了Adafruit NeoPixel库函数, 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上,4 r3 I$ _) z" V) N, f; C, J8 m& d/ m: p 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。7 L' O: ~0 @/ y* U
+ A6 Y' h: Z- X+ W |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1202
驱å¨åº
微信公众号
手机版
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps1 m7 ^" r5 ^1 o3 l5 B7 W
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。$ X' b! |5 e0 v0 i# j- H E
+ t& {) c) L% x, H/ H. {8 O
* D9 J$ z( n: g' { X( v/ `3 x
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)* O: c( v+ _& T9 P2 X3 c
{( S4 {& f7 E3 A3 t
uint8_t newBrightness = b + 1; C% _1 U; U6 f6 z+ d4 V
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c; A& }6 l# C) |' h( R$ t
uint16_t scale,i;
if(newBrightness != swObj->Brightness)
{ // Compare against prior value1 S4 A6 i3 F }/ c
// Brightness has changed -- re-scale existing data in RAM
if(oldBrightness == 0) ! r6 r: p6 B- K( _
scale = 0; // Avoid /0' [6 }9 G; ]+ r F
else if(b == 255) # n1 ~ T. L/ p4 Q! d, Z
scale = 65535 / oldBrightness;: G/ R. \* K5 h9 e3 c
else $ n4 }$ H% f* d2 c2 u
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;: E7 U) S) e8 s+ G
for(i=0; i<swObj->PixelLen; i++) B, `% p5 r5 Q. T6 g5 c; z
{9 L" ~; i$ Q0 m
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 8 W& D+ `! }% @% Q, p; D. ?( I
c = Sw28_ScaleColor(scale, c);& r. l9 ^( u+ g, J( f& [
Sw28_SetPixelsColor(swObj,i,c);//设置颜色7 S& f% G# d/ R% o/ {
}
swObj->Brightness = newBrightness;
}' X* u) k( E _
}) g/ Z* s! c/ B
- s; L e% {7 D; m' z, J2 c
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色' x6 z1 @9 G6 z! g: c* K5 y
按照G R B 传输 为 0x00 0xFF 0x00
, c' D2 Z* s C6 x. d
转换为二进制. J& [! F; L- J, }; q
001 001 001 001 001 001 001 001 001 001 0014 y" z. `; o' E3 E
110 110 110 110 110 110 110 110 110 110 110
001 001 001 001 001 001 001 001 001 001 001
SPI数据为:
0x24 0x92 0x49) l3 \7 m6 o& S% e' D1 f2 d
0010 0100 1001 0010 0100 1001 + h# _6 M" u1 a0 i
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110& \4 N, [* m: q6 T3 {! h
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001 9 I$ M2 _7 l+ R2 w
/ ? ~* E- J2 v# S3 C C3 j; x
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。