本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 , _- z; A. Z! a 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html3 \& l) }( c4 [" i. g 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。/ _5 l2 ?6 @( ?( t) F9 L # c) T8 G+ q4 t! Z3 Q1 j0 u, t 仔细一看发现 WS2812一个bit 周期是: 8 w4 w+ M3 a1 T7 G) E9 O+ P7 C TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns, u0 x7 A: ]% Y8 C 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。/ P6 F1 `; H9 y6 m6 Z SPI=0x8 等于 WS2812的 0! x' \' g4 y) }: _5 \( ~8 ~( E SPI=0xE 等于 WS2812的 1 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte6 m5 B4 R: v8 I 6 L5 A4 n: ]' w: ?# V* l9 y SPI速度及极性配置: , _7 s3 q4 A5 ~! i! N3 v5 c3 b 7 F: N5 S: V- @+ | SPI只需要配置主机只发模式,这样可以节省一个IO口0 j+ S) D4 A, v- S - V* T n, r5 } 驱动整盘WS2812都很轻松% P6 `/ ~9 h3 v, h1 H# u 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程# n1 h3 E+ B1 J% @# s# E4 n! p 程序移植了Adafruit NeoPixel库函数,6 V* p ^' d( E7 L; U, |2 c2 R/ N 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。4 ^$ K+ P2 \0 ~( D J$ \' a 0 y4 a, M1 g5 V8 A |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps
; Q- U5 A# |' c) K3 J
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
3 p) L) A+ S, B, v. ?) v) N
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{4 m5 Z; Y* s& i) _) }$ K! S c% A
uint8_t newBrightness = b + 1;
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c;
uint16_t scale,i;
if(newBrightness != swObj->Brightness) ( v! C; b" c- e( R1 [3 b
{ // Compare against prior value9 v7 ~" G' E* c( {6 ]8 h
// Brightness has changed -- re-scale existing data in RAM, W3 D5 w5 @% a& S) k0 I/ J
if(oldBrightness == 0)
scale = 0; // Avoid /0) k5 |) r M5 F& n, P
else if(b == 255)
scale = 65535 / oldBrightness;
else 6 s- z/ X6 c% T t; f
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
4 P r* Z% {& x7 p4 v
for(i=0; i<swObj->PixelLen; i++)
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色& |; v J9 | E/ ^
}
swObj->Brightness = newBrightness;
}
}5 z) `5 d. X% e
) o. w: b3 y/ d3 Q) [4 m
* k) j/ D- c6 y, z! ~; S7 t. [
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code * _8 I, [5 P( q1 n1 Q, W7 C
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00 ! `" q6 c0 v3 @& n T9 Q0 A0 D
转换为二进制( m, u4 c2 }. ?4 J6 m; K8 L0 c
001 001 001 001 001 001 001 001 001 001 0013 O$ y' X5 [0 G% Y4 O0 n
110 110 110 110 110 110 110 110 110 110 110; d/ S" _0 S- y" u0 v
001 001 001 001 001 001 001 001 001 001 001
SPI数据为:+ a$ ~* r, V! N. `7 Z3 o/ B5 |/ T
0x24 0x92 0x492 a# V& E* G) [9 I( o t$ Y
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110. R( T4 [5 Y. p
0x24 0x92 0x49, ?. Q3 U( D! t0 H& A) s/ P+ a
0010 0100 1001 0010 0100 1001 # V4 q$ j# A) s8 h3 Y
4 c/ J3 o9 K) e- N. i1 p
/ R/ B' ~- X9 t) |
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。