這篇要使用到SPI+DMA,需要了解的話,可以參考我另兩篇博客
時鍾:https://www.cnblogs.com/PureHeart/p/11330967.html
SPI+DMA通信:https://www.cnblogs.com/PureHeart/p/11218076.html
文章前半會先介紹WS2812通信方式,文章后半才是SPI+DMA
WS2812,這LED內部已經整合了信號處理的芯片,以4pin的WS2812為例,它的引腳分別是:
VDD:電源,3.5V~5.3V
VSS:地
DIN:數據輸入
DOUT:數據輸出
相關參數如下圖

接下來,才是最主要的,WS2812是如何通信?

它就像一塊大蛋糕
把大蛋糕交給第1人,第1人吃了一口
然后把吃過的大蛋糕,交給第2人,第2人吃了一口
再然后把吃過的大蛋糕,交給第3人,第3人吃了一口....
數據也是如此,例如上圖,以24bit為1組數據,相當於蛋糕的一口
D1(第一顆LED)收到3組數據(大蛋糕,3×24bit),自己截取一組數據(吃一口,24bit),剩下兩組數據(2×24bit),交給D2
D2也截取一組,剩下最后一組,交給D3
D3也一定要截取,然后就沒有數據能交給D4了(假設如圖那樣,只發了3組數據)
那什么時候,WS2812會認為你的數據是新的呢(新一輪的蛋糕)?
低電平時間 >= 50us,WS2812就會認為是新一輪的數據了
至於為什么是低電平,下面的圖片,我會和24bit的內容一起介紹

24bit的數據里面,最高8位是控制綠色,中間8位控制紅色,低8位控制藍色
亮度為0~255,所以1111 1111就是最亮,0000 0000就是不亮
然后最最重要的地方來了
這里的1、0,上圖說的很明白了
一定時間的高電平 + 一定時間的低電平 = WS2812承認的一位信號(高電平或低電平)
0 code(WS2812承認的低電平)就要求【T0H】和【T0L】的時間,當然 1 code(高電平)也是
所以!
假設以串口為例(用串口比喻,是因為我覺得大家應該都熟悉,當然,這里還沒考慮WS2812需要很高波特率這個問題)
設置好串口初始化之類的,然后對照g7,g6,g5,...,b0,調用串口發送3個字節來點亮1個WS2812,這是不可能的!
如下圖所示

既然此路不通,那應該如何解決呢?
我們應該進行壓縮,如下圖

是不是啊,只要我把一個字節的長度(以綠色波形為例),壓縮到跟G7一樣的長度(圖片只壓縮到G7~G3,弄的太小就看不清楚啦)
然后再改一下,不要發0x90,按照【T0H、T0L】【T1H、T1L】,就能控制了
所以,要能控制WS2812,我必須要發24個字節,這還只是一個LED要的數據而已
然后是壓縮,有經驗的人應該馬上會想到,其實這就是時鍾,設定好SPI的時鍾,就能達到這樣的效果
那么時鍾應該要設置多少呢?
在STM32F4里面,SPI發送可以設置8位或是16位數據
以8位為例,8位的時間總和,不管是 0 code 還是 1 code ,都約等於1.25u
1.25u / 8,每一位等於0.15625u
公式:頻率 = 周期的倒數
頻率 = 1 / 0.15625u
頻率 = 6.4M
SPI設置6.4M就可以了
當然,我上面用的是1.25u,也可以用1.1u,也可以用1.4u(因為有150n的允許誤差)
反正不超過規定的值,就可以了。。。也許。。。?
主時鍾設置為40M,SPI經過8分頻,得到5M
因為我有一些其他外設要配合,才這么設置主時鍾的
當然,我實測5M也是可以的。。。
1 / 5M = 0.2u
0.2u × 8 = 1.6u,已經超過規定的1.25u ± 150n 了!
不過可以用就好了。。。
代碼,應該也沒有什么好講的了,還是把它貼上吧,另外我有用DMA(減少CPU負擔)
下圖main函數里while(1)里面的0805LED,只是普通的LED,和WS2812沒關系,啊,另外,我用的是STM32F4的芯片
代碼鏈接:https://pan.baidu.com/s/1S33m7tx9Tfg8e3WKphGuNQ
提取碼:s82g


