本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html2 X( I$ `1 @2 ~- r0 s 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 仔细一看发现 WS2812一个bit 周期是: TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns! w8 \0 |4 A: p 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。% V/ B8 s$ ]! t, \4 Y SPI=0x8 等于 WS2812的 0 SPI=0xE 等于 WS2812的 17 l0 h! B4 a- z- e 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte5 w% b# o. U6 D6 }, N1 @; g 0 V: m" ?# p2 X# p1 y SPI速度及极性配置: * `1 ]$ Q7 Y6 x" A) f2 V& j' \ SPI只需要配置主机只发模式,这样可以节省一个IO口! x) S E; H( I y9 x( p1 t0 ^ 驱动整盘WS2812都很轻松 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,# b+ r* K' w" Q3 L' L, ^3 H 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, R; c6 B/ i6 c8 m! P" O3 O( S 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 , G9 ?% }0 e F, q) w9 q |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps# V' [+ l6 `8 L( d! r
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。* K! R9 s7 v" X( d$ T
! |/ {4 T ^7 J2 U. D8 s
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)6 n2 J" @- T- @2 q! B" `
{, D( P7 v% Z1 v* F2 ]
uint8_t newBrightness = b + 1;. q4 O& U) P# {0 d2 s
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value7 ]/ R. a3 \6 U
uint32_t c;
uint16_t scale,i;2 m+ X# |. o3 S2 t9 r4 j
if(newBrightness != swObj->Brightness)
{ // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
if(oldBrightness == 0)
scale = 0; // Avoid /0
else if(b == 255)
scale = 65535 / oldBrightness;
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
for(i=0; i<swObj->PixelLen; i++)
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 1 U* F" X1 r8 T: ` \8 _9 a$ }. d) V
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色; y, z( ?- t. b1 n X+ L7 W& Y' p
}
swObj->Brightness = newBrightness;
}/ V% X. S% t& j% H
}" M: R( n! v/ y
; r3 Q) ]9 f3 J2 n5 T6 C% @
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00
+ |+ |+ C- L( ~/ I
转换为二进制
001 001 001 001 001 001 001 001 001 001 001
110 110 110 110 110 110 110 110 110 110 110+ y0 D7 ~7 F R8 r6 b
001 001 001 001 001 001 001 001 001 001 001 ' f& z) K! k5 ^6 R$ j
& v# p. d) b* A0 Z
SPI数据为:
0x24 0x92 0x495 ^: t6 Z. u& ^( ~' A4 o0 a
0010 0100 1001 0010 0100 1001 4 W( C3 u9 ` m# i. y O
0xDB 0x6D 0xB65 K* E1 P x7 b9 y
1101 1011 0110 1101 1011 0110# ?. j, b1 w! k, v. J
0x24 0x92 0x49" }: L+ [$ e( z! G" ]
0010 0100 1001 0010 0100 1001
8 ^0 }/ ?) t# r- ^/ c) s
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。