本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 & f- S! b3 [7 ?+ H6 ]& x) l 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 仔细一看发现 WS2812一个bit 周期是: TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns1 h+ i& C$ K9 ?, i 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。- `; `7 {" w; \! C! n SPI=0x8 等于 WS2812的 0) `! Z5 J7 q. c6 a SPI=0xE 等于 WS2812的 18 D) R& r$ a9 Z# V9 V/ I0 q8 j 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte SPI速度及极性配置:# |( V3 P N2 A& `# ^, n6 p 2 J6 `+ k+ {; S3 l + F1 ]8 j" x1 F. ^6 L8 P SPI只需要配置主机只发模式,这样可以节省一个IO口 驱动整盘WS2812都很轻松 - L5 X# Y0 z1 ? L) b+ i 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程, s, I& V$ o/ g+ d* t+ E0 R 程序移植了Adafruit NeoPixel库函数, 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 1 C! ?! `( E& Y# t% }2 t |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps
$ f/ N. m4 r- ~: g' \, p3 j
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{
uint8_t newBrightness = b + 1;* ?) R0 {. [/ ^7 e
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value! q7 Z6 @3 C! Z6 V! H t
uint32_t c;) u: l/ I: [+ g
uint16_t scale,i;
if(newBrightness != swObj->Brightness) " S- P% o+ E7 X" d5 ^$ _$ b" A
{ // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM( k1 ^( ^0 g8 r4 q% c
; h4 L" G$ b' n! G- D: M
if(oldBrightness == 0) 7 x' G8 t$ E+ s+ a: y5 C
scale = 0; // Avoid /0: r& N+ b7 f6 W4 o4 l
else if(b == 255)
scale = 65535 / oldBrightness;
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;0 G: `( c9 w4 j$ L( H+ z
for(i=0; i<swObj->PixelLen; i++)9 E6 P& G/ D8 D( a0 G
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色
c = Sw28_ScaleColor(scale, c);) M- O) R) c/ A2 w, _
Sw28_SetPixelsColor(swObj,i,c);//设置颜色
}9 d5 f9 e4 P% j" Q$ K, v. @
swObj->Brightness = newBrightness;& o3 }6 p/ _' @; K+ s/ k q7 X1 G
}8 A# l- o/ L; N9 J* u) G8 e
}
) O1 M& p3 m: Q4 I
6 N, F( s/ Z- d
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code 1 y: M/ ~4 B8 L X1 V
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00
转换为二进制8 s3 ]3 E, `- y0 j/ E3 C
001 001 001 001 001 001 001 001 001 001 0019 H: ?+ ]% f$ D& f1 H4 }
110 110 110 110 110 110 110 110 110 110 110& r- t+ y( l U) x4 O, v
001 001 001 001 001 001 001 001 001 001 001 ' a+ ~8 M2 u( p, X! [6 s
SPI数据为:
0x24 0x92 0x49# y* h, z1 k1 g5 I7 U
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6
1101 1011 0110 1101 1011 0110
0x24 0x92 0x49
0010 0100 1001 0010 0100 1001
6 F8 h* z B' B/ Z8 }8 z
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。