本帖最后由 waiman-156411 于 2018-2-6 17:57 编辑 看到zoomdy 的驱动例子启发 https://www.stmcu.org.cn/module/forum/thread-610279-1-1.html$ Q3 a, {" C) ^0 c: c 效果虽然不错,可以节省不少MCU资源,但用一个byte的SPI数据代替WS2812一个bit,很浪费RAM资源,而且生成像素的效率也很慢。 仔细一看发现 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的时序需求。" P6 q' @9 X, m SPI=0x8 等于 WS2812的 0& e* m' S2 j5 w. R# h SPI=0xE 等于 WS2812的 1 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte & d+ B5 z! E6 u( z0 b - K4 s& K1 t2 F+ q* a SPI速度及极性配置: 7 P/ f5 }2 v/ V9 ~ - w7 Z2 T& u0 ^! ^4 ?/ P4 x SPI只需要配置主机只发模式,这样可以节省一个IO口 驱动整盘WS2812都很轻松4 X% c- p8 f2 V" p4 w4 M, A' H * b* J) I! ~* M$ b+ a 驱动库说明: 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,3 M, `1 F" ~. H( h 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上, 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。4 i h5 `: e: A* k1 G+ V# b |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1161
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps" `# | r; x5 J2 \1 x* K6 ]
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
, Y! a. m0 u9 ^2 ?
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)7 c- {5 R- @+ \* K9 x! \! |4 M4 P
{( z! U" S% P6 O+ G# Z
uint8_t newBrightness = b + 1;
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 RAM4 E0 Z; K5 V: I2 Q4 O- N+ \
if(oldBrightness == 0)
scale = 0; // Avoid /0
else if(b == 255) 7 r5 H, E' d9 {" A& K
scale = 65535 / oldBrightness;
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;, K( U* _4 G G+ p+ s+ z
# ~. E7 s6 ?( g) K
for(i=0; i<swObj->PixelLen; i++)! M9 n1 L4 ?6 _1 t$ V+ q3 g2 D
{
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色
c = Sw28_ScaleColor(scale, c);- U7 |6 A3 ]. E" A, D. S
Sw28_SetPixelsColor(swObj,i,c);//设置颜色
}
swObj->Brightness = newBrightness;+ N6 Z- ?; v7 j& o' i0 f
}
}4 X# T9 j+ \' J3 I. U
" v1 b+ ^& L- |1 k, V
- B% |7 C* [! E) d4 Q
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code 6 ?/ a" W8 M' o b5 p& I
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色: x+ K5 } I& C( a [4 S
按照G R B 传输 为 0x00 0xFF 0x00 0 a+ ?' Z) }& F* F
5 b' O- \7 r4 g# ]* Y" M3 c( x l; n
转换为二进制
001 001 001 001 001 001 001 001 001 001 001
110 110 110 110 110 110 110 110 110 110 110, M3 J0 Q4 @) _/ z! a
001 001 001 001 001 001 001 001 001 001 001 " |! O3 P' y8 c, e4 t& M5 B* X
; A/ y/ q6 r# f. P
SPI数据为:; _# g! k* p& b! R) j! Q2 r
0x24 0x92 0x49( U6 D# U0 @& c, m
0010 0100 1001 0010 0100 1001
0xDB 0x6D 0xB6* q# J! t5 o' |' `) u& Y* v- o
1101 1011 0110 1101 1011 0110
0x24 0x92 0x494 x8 ?" q9 i6 D: x
0010 0100 1001 0010 0100 1001 * e+ @( T0 b! n6 W5 I
/ [# r8 R( m- a* E3 V ?! x5 |) A
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。