討論用一片STM32C8T6驅(qū)動2048個(gè)串行單線RGB的方法

串行RGB WS2812 SK6812 等相信大家都很熟悉了,你電腦里面的光污染大多來源于此,網(wǎng)上很多相關(guān)的資料,驅(qū)動方式多種多樣,PWM SPI,甚至直接進(jìn)行IO模擬來驅(qū)動。

這里討論一下,如何用一片C8T6驅(qū)動 2048個(gè)燈,并且實(shí)現(xiàn)以下參數(shù):
驅(qū)動2048個(gè)RGB
30FPS 刷新速率
單片機(jī)不能阻塞
單片機(jī)不能爆空間
先看看時(shí)序,大家應(yīng)該都很熟悉了。

0,1這里咱們先不看,不同的燈可能會有所差異,但是一個(gè)BIT需要1.25us的時(shí)間大多數(shù)燈都一樣。
那么也就是一個(gè)燈傳輸24個(gè)字節(jié)(R G B 各需要8位)
換算下來就是 24x1.25us = 30us/每個(gè)燈的Data Time 數(shù)據(jù)傳輸時(shí)間。
那么我們有2048個(gè)燈?? 2048x30us = 61440us 數(shù)據(jù)時(shí)間 +上RES時(shí)間50us大概一幀所需要花費(fèi)時(shí)間 61.490MS 很明顯 ,如果按這樣 以最快的速度 刷新燈的數(shù)據(jù)也只有約16幀
所以這里咱們得把燈板拆分開來,我打樣的板子是16*32,所以我就分成了4份。

這樣的話 我們需要分開4個(gè)IO口同時(shí) 驅(qū)動4個(gè)單片512個(gè)燈,512*30us =15360us+50us? 單片理論刷新時(shí)間應(yīng)該能達(dá)到60幀多一點(diǎn)。但是肯定做不到這么高,這里后面再說.

確定了硬件之后我們來確定一下軟件驅(qū)動。
這里我使用PWM+DMA的方式來驅(qū)動。
PWM定時(shí)器設(shè)置為800Khz周期
然后依次將對應(yīng)電平的占空比放到PWM的buff數(shù)組中,就可以實(shí)現(xiàn)0.1的CODE輸出,那么也就說 一個(gè)燈需要24個(gè)占空比值,在DMA 的BUFF中一個(gè)燈需要24個(gè)長度為16位數(shù)去儲存顏色數(shù)據(jù),(這里先不 談RES數(shù)據(jù))。
簡單換算一下,一個(gè)燈24(PWM值)x 2(16位數(shù)據(jù)一個(gè)數(shù)據(jù)占2個(gè)字節(jié))=48個(gè)字節(jié)。本項(xiàng)目2048個(gè)燈僅僅數(shù)據(jù)部分一共需要98304個(gè)字節(jié)=96K TOO BIG
眾所周知C8T6擁有64KB FLASH? 20K的RAM,其的身軀根本無給他這么大的BUFF空間。那么怎么辦呢。
重點(diǎn)來了
這里我們把DMA的半傳輸中斷和循環(huán)模式打開,實(shí)現(xiàn)顯示緩存的功能,示意如下:

1,寫入 BUFF1 和BUFF2啟動DMA
2,進(jìn)入半傳輸HC中斷后,更新緩存1的數(shù)據(jù)(此時(shí)此刻DAM正在傳輸緩存2的數(shù)據(jù))
3,進(jìn)入傳輸完成TC中斷后,更新緩存2的數(shù)據(jù)(此時(shí)此刻DAM正在傳輸緩存1的數(shù)據(jù))
4,進(jìn)入半傳輸HC中斷后,更新緩存1的數(shù)據(jù)(此時(shí)此刻DAM正在傳輸緩存2的數(shù)據(jù))
5,進(jìn)入傳輸完成TC中斷后,更新緩存2的數(shù)據(jù)(此時(shí)此刻DAM正在傳輸緩存1的數(shù)據(jù))
............
所有燈數(shù)據(jù)傳輸完畢后,將DMA緩存設(shè)置為0,發(fā)送一組RES指令過去使燈數(shù)據(jù)有效。
使用這種方法可大幅節(jié)省RAM空間,如果我們緩存定義為16個(gè)燈的大小,也就是一次傳輸16個(gè)燈的數(shù)據(jù),單組2個(gè)緩存就是32個(gè)燈 32*24=768長度的16位數(shù)組,也就是占用1536個(gè)字節(jié)。
由于我們分開4路PWM 同時(shí)進(jìn)行驅(qū)動,一共有4組DMA緩存 也就是4*1536=6144個(gè)字節(jié)
然后用一個(gè)8位數(shù)組,存放2048個(gè)燈的RGB數(shù)據(jù)占用 6144 個(gè)字節(jié)。
6144+6144=12288個(gè)字節(jié),對于C8T6的RAM來說也完全可以跑下去了。

下面是使用CUBEMAX工程的建立:

定時(shí)器配置如上

這里我使用的是TIM1 的4個(gè)PWM通道,DMA設(shè)置為循環(huán)模式 Memory to Peripheral ,以及Half Word

時(shí)鐘樹如上

下面說一下程序方面需要注意的幾個(gè)小點(diǎn)

由于分開了4組DMA,如果同時(shí)啟動可能會導(dǎo)致同時(shí)進(jìn)入傳輸中斷導(dǎo)致數(shù)據(jù)錯(cuò)誤,小小延遲一下避開同時(shí)進(jìn)入中斷即可解決此問題,也可以對DMA中斷進(jìn)行優(yōu)先級進(jìn)行設(shè)置來避免此問題。




還有一個(gè)坑,在Cubemx生成的void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle) 代碼下 通道4會有多出來的LINK

必須屏蔽其他DMA LINK。否則CH4不會進(jìn)中斷。




展示2
以這種方式進(jìn)行RGB驅(qū)動,可以大幅節(jié)約系統(tǒng)資源,這邊測試驅(qū)動2048個(gè)RGB,還做了256 的FFT,可達(dá)到30FPS左右的幀率。
有一點(diǎn)不得不說,2048個(gè)2812電流爆炸,沒寫亮度控制的時(shí)候,通電我仿佛看到了太陽,也未敢3色全點(diǎn)進(jìn)行測試,電源直接保護(hù)了,保守估計(jì)得有50A左右電流。
個(gè)人倒騰記錄可能有不嚴(yán)謹(jǐn)?shù)牡胤?,請見諒,本文僅提供一種思路,涉及代碼已貼出,歡迎大家一起討論建議。