|
本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html6 k) A2 c/ o! ^5 K$ e 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。8 L2 G7 n* q$ H8 f, w# I3 S
仔细一看发现 WS2812一个bit 周期是: TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。" P, f$ p/ ]0 t. |* W/ e; I SPI=0x8 等于 WS2812的 0. p t, V. [1 s+ @: A! h5 g% P) N SPI=0xE 等于 WS2812的 1 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte 7 C) E1 j Q% l- i SPI速度及极性配置:
. |. d( Y: p- T' Y3 `$ O3 x SPI只需要配置主机只发模式,这样可以节省一个IO口
# q! J) X. a5 j. T/ @ 驱动整盘WS2812都很轻松
驱动库说明:, I3 W6 _' v! `. d- A" c 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 n* e$ _) N5 N 程序移植了Adafruit NeoPixel库函数, 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。- o4 Y" s+ r8 g4 k, G
! ^. g- V4 z) I9 m |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1202
驱å¨åº
微信公众号
手机版
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps5 [- R; P& z0 R0 U. G* F
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。4 |3 w. L, |! \8 V; O! Z" I1 f
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{
uint8_t newBrightness = b + 1;7 y7 u3 ?3 g- E+ Y0 t% v9 Y
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c;% T, X* t! m# N) C- z
uint16_t scale,i;; r1 q0 Y* N8 i8 ^3 k
if(newBrightness != swObj->Brightness) % p+ ~$ N- o4 `/ y( u; Q
{ // Compare against prior value" S6 j( q) |+ N2 J; ^# b' \. U+ F
// Brightness has changed -- re-scale existing data in RAM
& k! N P# Y9 O J
if(oldBrightness == 0) * u& Z( E2 A7 w: g, c! H
scale = 0; // Avoid /0 t- @; w' m# u* G' l3 z, N2 m9 ]
else if(b == 255) 5 P, C% k3 }/ s6 |1 ?) v1 o
scale = 65535 / oldBrightness;
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; }9 N$ B: G# Y4 K
/ z! a8 g" D0 Z' L5 {) K7 ?
for(i=0; i<swObj->PixelLen; i++)8 ~. N! }+ l% u, t o
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 ' P/ D+ a0 ~9 h- K
c = Sw28_ScaleColor(scale, c);# n4 x2 ^! a) H% M
Sw28_SetPixelsColor(swObj,i,c);//设置颜色5 I! t9 x g' j5 C3 T
}' n( U! z. ]( r0 E$ a' |! K
swObj->Brightness = newBrightness;- `/ J$ D2 K4 C/ E& K
}
}% S* p% F/ `- v
4 K& z: j% W |% c$ ]
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色) ]. h E* h7 p/ P4 z
按照G R B 传输 为 0x00 0xFF 0x00
) q/ n1 n' L5 a3 H' E. J) X/ t
转换为二进制. ~6 }/ |7 w' O, U: P. E" M/ n; M
001 001 001 001 001 001 001 001 001 001 001# B" V5 R5 E/ q3 N
110 110 110 110 110 110 110 110 110 110 110* m: q1 q# w8 U Z
001 001 001 001 001 001 001 001 001 001 001
: n0 U, P4 P9 \! t9 |+ M
SPI数据为:
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001 9 f3 j4 @/ J" [" X
0xDB 0x6D 0xB6" u& p( D* A: C, z* j% f
1101 1011 0110 1101 1011 0110 C' B1 Y- V! q3 A1 B; ^
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
5 a+ C1 }6 X: k- K, N
) {% ` d+ N& w/ d9 Q
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG 4 e) S2 D3 [; M# l9 @
mdk的,论坛里有人分享过了,你可以搜一下
好方法。