|
本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 9 k# Q0 `$ T5 g1 ~* f$ e/ }6 x 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html3 ?" }, n7 W" \ i* A& \& } 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。9 l3 A' h" i- F8 ~3 |4 t
仔细一看发现 WS2812一个bit 周期是: 6 H6 [, }$ J8 y7 \0 Z3 T3 D- _ TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。, }6 O7 G- @5 z) r) U, Y SPI=0x8 等于 WS2812的 0 SPI=0xE 等于 WS2812的 17 v( X& b5 k6 r/ a! r+ h3 ~9 w 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte; `% C; D1 M% T# R/ q 0 Q' q9 y/ r7 G8 P- X! y' {( E SPI速度及极性配置:
5 C7 n* ^% _1 d4 ~8 J* m SPI只需要配置主机只发模式,这样可以节省一个IO口1 j/ f2 L" T9 n
驱动整盘WS2812都很轻松0 A$ |' `0 Y" }
驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程# W8 M6 B. n! |- I2 S% B 程序移植了Adafruit NeoPixel库函数, 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。! q t) }! c9 S0 V: t! d( F$ V
$ {* b) y) C; |( o5 Q e1 ?& @1 J3 g 4 d6 W0 ] b' j |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1202
驱å¨åº
微信公众号
手机版
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps+ t: Y6 ?4 A3 U" a2 }, N6 L& X
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。% }( ^/ F: h# w8 M3 ?$ a: k
! T1 G0 b5 x5 E- o+ r
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{9 B% u3 R: G9 W( d4 C) k6 M" |
uint8_t newBrightness = b + 1;% g4 E6 q" C- C' d$ M! `; h
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value
uint32_t c;
uint16_t scale,i;# E+ M7 x" G: i/ f& h) O
if(newBrightness != swObj->Brightness)
{ // Compare against prior value2 r: R/ P, n8 H* B. C
// Brightness has changed -- re-scale existing data in RAM
0 @3 R( b/ z' b' M% n$ {: o% ^
if(oldBrightness == 0)
scale = 0; // Avoid /0) \2 z6 q, Z8 w D" ~, N( `8 b
else if(b == 255)
scale = 65535 / oldBrightness;# s0 Q2 o; m/ E u& t
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
for(i=0; i<swObj->PixelLen; i++)
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色
}
swObj->Brightness = newBrightness;
}+ K5 c8 i$ z4 F3 S L- |# _
}; o/ S& L3 `9 @
) u. v& x! e# ~! a0 P! B/ y
( H; V! l8 M7 K Z$ t
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色- k2 s P* e9 Q! Z4 l1 u- }2 F
按照G R B 传输 为 0x00 0xFF 0x00
转换为二进制4 y' @, r. }: N8 x/ R+ t
001 001 001 001 001 001 001 001 001 001 0017 E. C" q9 k: e' [
110 110 110 110 110 110 110 110 110 110 110
001 001 001 001 001 001 001 001 001 001 001 % H& T! D2 c( } j9 b$ f9 q
. V a0 |+ f* D7 D4 v
SPI数据为:
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110; i/ i% o, Z5 x
0x24 0x92 0x495 Y. ?$ x5 A# t, K
0010 0100 1001 0010 0100 1001 0 B8 c+ A) S+ ]& q
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。