|
本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。
仔细一看发现 WS2812一个bit 周期是: 3 \; N) U& d& p+ I t$ o/ T3 g# r d TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns+ O [7 s) H8 ^! r( x0 _$ [+ r 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。 SPI=0x8 等于 WS2812的 0 SPI=0xE 等于 WS2812的 13 N0 X0 P! K0 f2 p* i; g' O' K 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte, s& |; `. B$ T) M/ L$ E; G( X % z( o( a% }8 k- p3 p2 R 4 R2 d& Y/ P2 G SPI速度及极性配置:( Z) m' w. b2 i/ ]# t4 \) `" Z: B% `
. }* h1 R2 v( O) E SPI只需要配置主机只发模式,这样可以节省一个IO口
驱动整盘WS2812都很轻松
( }$ x$ v5 z% [5 N2 ] 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数, 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。
|
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1202
驱å¨åº
微信公众号
手机版
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps
6 J6 e$ `! U; j) c1 v5 g
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
3 O* B) L' S6 R' d2 L& f* p
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)% O4 E( a0 q! L+ v7 b+ u
{
uint8_t newBrightness = b + 1;# q" L0 h8 x1 {# a1 U" T2 A: H
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c;
uint16_t scale,i;
if(newBrightness != swObj->Brightness)
{ // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
R) u7 N! K5 k% w" x
if(oldBrightness == 0) 9 z m/ {8 ?8 }( z; p# h0 j
scale = 0; // Avoid /0) _) I l5 a2 y4 X/ r- o
else if(b == 255) 2 z9 u N/ a+ ?9 K/ s9 K) {! A# g
scale = 65535 / oldBrightness;: U8 [ Q# M2 d. s# `; b
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;8 [7 o8 M9 E* s$ k5 J" U
1 x2 U' X. p2 K
for(i=0; i<swObj->PixelLen; i++) I2 h9 R3 A6 P2 S7 U, Z
{: u& x% a5 J; V7 i. @
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 & p G/ ]& @) x8 T0 J/ L
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色
}+ L g0 y" w u
swObj->Brightness = newBrightness;" `* c' W0 X: a: \8 z) o3 p4 B
}
}0 o5 Y1 z, R/ \
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00
+ Z+ L: V) S; k, H3 s1 |
转换为二进制# S; [- ]; S: P: E6 ~+ v
001 001 001 001 001 001 001 001 001 001 001% ]. x& X( D+ Z
110 110 110 110 110 110 110 110 110 110 110
001 001 001 001 001 001 001 001 001 001 001
& L9 H1 B/ T+ j6 }
SPI数据为:) x% `. D$ z4 j0 H4 M2 i- V Q
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6( ?5 t6 [) u# N) F
1101 1011 0110 1101 1011 0110
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001 R' }: ]* T) {, h
( I+ w6 \3 ~2 D5 }( l
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG : k6 J$ i) |! [$ m% Y/ T. q; ]% R
mdk的,论坛里有人分享过了,你可以搜一下
好方法。