本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html9 Q0 `, F z6 D 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 仔细一看发现 WS2812一个bit 周期是: " h; K& A7 Z0 B$ N, V& F K$ z7 ` TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。2 b# d' U1 Z% C7 W SPI=0x8 等于 WS2812的 0 SPI=0xE 等于 WS2812的 1 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte& {* i& r! p7 @0 J) ~$ e& D $ ^9 m' c0 F: ^% c" u SPI速度及极性配置: SPI只需要配置主机只发模式,这样可以节省一个IO口 驱动整盘WS2812都很轻松 . N. d* b2 W7 C0 }6 | 驱动库说明:) o- Z. ]1 F! w/ B( H* n 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,1 [1 @: J8 V6 G; e: y# n. Q$ X 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上,; C; j6 e4 \8 X0 u' Q 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 o# I" n+ U/ V5 }. ]; [% |. F; F , P2 o, Z/ r6 K" S . z1 ?' p' n0 }+ N* e/ [- ~- {% k |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
7 H2 i+ W: X: ~+ k! ]
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)# K; T% V/ L+ Z0 {4 R6 @1 Y/ [
{9 v% c4 x( V$ q; e) L' I* H6 ]
uint8_t newBrightness = b + 1;
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value" U8 T* Y5 M3 B; ?* j5 Y
uint32_t c;
uint16_t scale,i;
if(newBrightness != swObj->Brightness) # L, q9 x V$ Z) W1 W1 S
{ // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
) Q% M* N+ f0 h' M$ y3 |( z D
if(oldBrightness == 0) + f# x7 e$ g3 k% v
scale = 0; // Avoid /0
else if(b == 255)
scale = 65535 / oldBrightness;
else 9 {% r4 P2 k0 l* ?, i: H
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
$ `1 [" n0 q- R1 ^
for(i=0; i<swObj->PixelLen; i++)6 }( s" O6 O- v- X* G
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 + L j7 r' H, f- v7 N' _! ^
c = Sw28_ScaleColor(scale, c);7 `% R& D7 H$ K
Sw28_SetPixelsColor(swObj,i,c);//设置颜色/ \7 @0 n3 g% \5 {1 s" [
}
swObj->Brightness = newBrightness;/ d. o5 R% H b- A4 n! b6 P O' a
}
}
+ y: Q1 x$ k: \' F4 s9 A
2 b0 i: C, l `5 @ A
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00 $ @2 ~: ?$ U4 u
L/ a* T5 Q. X; B
转换为二进制9 t9 h% h4 F9 S: Y4 G. d2 x$ V
001 001 001 001 001 001 001 001 001 001 0019 M2 E6 F6 N" I% Q. Z
110 110 110 110 110 110 110 110 110 110 1106 @0 k" A7 n: U% P" l1 t
001 001 001 001 001 001 001 001 001 001 001 : x- a) a4 ]9 F! O$ `) y
SPI数据为:# b7 X) w$ J# B0 w8 O, Y
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110) v' R0 W; V, U% I7 r9 S2 I8 t
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
) X( E: C* ]) C# I) P+ I! p+ V
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。