
本帖最后由 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 周期是: # V- N& d, Z2 w* X TH+TL=1250ns (±600ns), Min=650ns,Max=1850ns& T% ]. v( T3 W8 \! ] 如果把SPI提速到4Mbits/S 的时候,SPI一个bit的周期是250ns,刚好和符合WS2812 T0H或T1L 400ns ±150ns范围。SPI 4个bit的周期刚好1000ns,刚好可以满足WS2812的时序需求。7 e$ A6 \6 J1 ^6 b7 X, _ SPI=0x8 等于 WS2812的 09 @9 b; U/ J7 N3 V, k SPI=0xE 等于 WS2812的 1, P7 n& ?/ {4 D, U& f 也就变成一个SPI的byte,可以表示2个Ws2812的2个bit。一RGB像素颜色只需要 24bit/2bit = 12byte5 W' V' Z8 c0 r) T6 I SPI速度及极性配置: ![]() SPI只需要配置主机只发模式,这样可以节省一个IO口: _4 @. M3 n) U6 o t* j ![]() 5 q- n; ^* q1 |# s& O! q 驱动整盘WS2812都很轻松& n* I# e$ X i$ h ![]() ![]() 驱动库说明:6 K$ [5 U7 ]* S. I$ f 例子使用Stm32CubMx 4.23,STM32L151C8T6,IAR/MDK工程 程序移植了Adafruit NeoPixel库函数,+ C8 @+ b1 \3 \# L) h. I# p 采用HAL库驱动方式(struct),可以方便移植到其他STM32芯片上,6 o" T# x) ~8 \. b# z" I1 m 只需要分配多个struct变量,硬件稍微改下,就能分时复用,控制多串灯珠。 ![]() 5 n `- C- f: f m# S' e9 c6 p |
SPI_DMA_WS281X.rar
下载584.49 KB, 下载次数: 1200
驱å¨åº
用3位代表1个bit通过SPI方式驱动WS2812时,SPI的速度请调整到2.25Mbps7 `! j' r# V0 d. |0 s' B4 d
以下是我用的代码,供你参考。ptr指向SPI Buf,value 是要转码的值。
void Sw28_SetBrightness(SW28_HandleTypeDef *swObj, uint8_t b)
{
uint8_t newBrightness = b + 1;
uint8_t oldBrightness = swObj->Brightness - 1; // De-wrap old brightness value1 n" P/ ^5 s, Q+ N
uint32_t c;
uint16_t scale,i;
if(newBrightness != swObj->Brightness)
{ // Compare against prior value, g0 S9 F- [& H m
// Brightness has changed -- re-scale existing data in RAM
if(oldBrightness == 0)
scale = 0; // Avoid /0
else if(b == 255) 6 Y T0 ~' l% {# i
scale = 65535 / oldBrightness;( `; C0 ~- P& Z! f u
else
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;/ C ~0 B; w, y/ q; Z& D
for(i=0; i<swObj->PixelLen; i++)
{8 u* I9 R4 p: W1 E& j
c = Sw28_GetPixelColor(swObj,i); //获取16bit颜色 - `! K: G& [& e; E& i3 b: ~- E- b
c = Sw28_ScaleColor(scale, c);
Sw28_SetPixelsColor(swObj,i,c);//设置颜色
}8 w; S& B5 Y. f1 d
swObj->Brightness = newBrightness;
}
}6 t l1 u9 P2 W- S( h5 d0 g T
( B" [3 `& j# V9 n
我现在遇到一个问题 3bit表示一个code 001 表示0code 110表示1code % s1 K0 J+ Q( @# J$ A
当我要发送9byte的一个24bit颜色值的时候 比如是传输红色
按照G R B 传输 为 0x00 0xFF 0x00 % \# p# z* J% d* Q1 H8 V, I
转换为二进制3 Z9 n4 \+ R9 E6 i b
001 001 001 001 001 001 001 001 001 001 0016 H9 I5 ?( @, T2 x+ Q6 I5 R
110 110 110 110 110 110 110 110 110 110 110
001 001 001 001 001 001 001 001 001 001 001
SPI数据为:
0x24 0x92 0x49. L" ?8 d, y! v4 K
0010 0100 1001 0010 0100 1001 ) F# _- A2 p7 @
0xDB 0x6D 0xB6- r/ P* I* Q1 i1 j- O% p, b
1101 1011 0110 1101 1011 0110
0x24 0x92 0x492 [. U! \3 w' J l$ C
0010 0100 1001 0010 0100 1001 / h: R, F: ~5 p8 J& f4 ]
这里的问题是当我SPI发送完0x24之后 发送0x92的时候 0x24的最后一位是0 0x92最后一位是1 导致0x24的最后一个0码和0x92的1码混合了
修补BUG
mdk的,论坛里有人分享过了,你可以搜一下
好方法。