動(dòng)實(shí)戰(zhàn):從硬件設(shè)計(jì)到SPI調(diào)試全解析)
我手里這塊1.47寸的ST7789V3彩屏從畫原理圖到把第一幀彩色畫面點(diǎn)亮前后折騰了大概兩個(gè)晚上。中間踩了不少坑有電容選型的問題也有初始化序列順序的問題更有SPI時(shí)序理解偏差的問題。這篇文章就把整個(gè)硬件設(shè)計(jì)和驅(qū)動(dòng)調(diào)試的過程完整捋一遍從電源設(shè)計(jì)到寄存器配置從白屏排查到幀率優(yōu)化把那些數(shù)據(jù)手冊(cè)里沒寫明白、只有實(shí)際動(dòng)手才能發(fā)現(xiàn)的東西全部講清楚。如果你正準(zhǔn)備用ST7789V3做小尺寸彩屏方案或者已經(jīng)點(diǎn)亮了但畫面不正常這篇文章應(yīng)該能幫你省下不少排查時(shí)間。1. 為什么1.47寸小屏選ST7789V3替代型號(hào)背后的選型邏輯1.1 屏幕參數(shù)與驅(qū)動(dòng)IC的關(guān)系先說清楚一個(gè)概念。我們常說的1.47寸彩屏240x280分辨率本質(zhì)上是一塊TFT-LCD面板而ST7789V3是驅(qū)動(dòng)這塊面板的控制芯片由晶門科技出品。面板和驅(qū)動(dòng)IC不是綁定的同樣的1.47寸尺寸市面上有多個(gè)驅(qū)動(dòng)IC方案ST7789V3、ST7789V、NT35510、GC9107這些都有可能遇到。但ST7789V3是其中最常見的一種尤其是在電商平臺(tái)上大量標(biāo)稱“1.47寸ST7789V3彩屏”的模塊。1.47寸這個(gè)尺寸很有意思。它比0.96寸和1.3寸大了一圈顯示內(nèi)容從幾行文字?jǐn)U展到了可以放簡(jiǎn)單圖形甚至小縮略圖但價(jià)格又比1.8寸、2.0寸便宜不少。240x280的分辨率在SPI接口下刷整屏如果用10MHz的時(shí)鐘RGB565格式一幀數(shù)據(jù)是2402802等于134400字節(jié)整屏刷新大概需要107毫秒。這個(gè)速度做菜單切換沒問題做視頻播放就別想了后面會(huì)詳細(xì)說怎么優(yōu)化。1.2 ST7789V3和ST7789V到底有什么區(qū)別這個(gè)坑我一開始就踩了。嘉立創(chuàng)商城和某寶上搜索“1.47寸彩屏”有些標(biāo)注ST7789V3有些標(biāo)注ST7789V看起來差不多實(shí)際上寄存器細(xì)節(jié)有差異。ST7789V是面向240x320分辨率的常青樹型號(hào)而ST7789V3的顯示RAM被裁到了240x280部分控制寄存器的上電默認(rèn)值也有調(diào)整。兩張屏幕如果混用初始化代碼會(huì)出現(xiàn)幾個(gè)典型癥狀喚醒后屏幕有背光但全白、豎條紋、或者只有上半屏有內(nèi)容。我后來專門用邏輯分析儀對(duì)比了兩顆IC讀取ID寄存器的返回值發(fā)現(xiàn)ST7789V3讀回來是0x85而ST7789V是0x85還是0x81要看具體批次。更穩(wěn)妥的做法是直接解析模塊絲印和店家給的規(guī)格書不要只靠驅(qū)動(dòng)IC型號(hào)猜。對(duì)于1.47寸240x280的屏廠商一般會(huì)提供一個(gè)配套的初始化序列里面會(huì)有幾處關(guān)鍵的差異配置比如伽馬曲線、電源控制寄存器的寫入值。采購(gòu)時(shí)盡量固定供應(yīng)商、固定批次換供應(yīng)商之后第一件事不是改代碼而是先重新調(diào)初始化序列。1.3 接口選型SPI足夠還是必須上并口ST7789V3同時(shí)支持SPI和MIPI DBI并口8080系列但市面上幾乎所有1.47寸小模組都只引出了SPI接口個(gè)別焊盤上有并口的走線但沒有實(shí)際焊接。設(shè)計(jì)硬件之前我糾結(jié)過要不要為了刷新速度上并口后來算了一筆賬模組引腳數(shù)量從6個(gè)直接翻到16個(gè)以上51單片機(jī)或者普通STM32的GPIO占用劇增而SPI模式已經(jīng)能滿足大部分HMI人機(jī)界面的更新需求。最終我選定了4線SPI的方案CS、SCLK、MOSI、DC外加RESET和背光控制。3線SPI可以省掉DC引腳用指令流的格式區(qū)分命令和數(shù)據(jù)但驅(qū)動(dòng)代碼的封裝復(fù)雜度會(huì)上升而且很多現(xiàn)成的圖形庫默認(rèn)需要DC引腳。個(gè)人項(xiàng)目選4線SPI兼容性最好。2. 硬件電路設(shè)計(jì)實(shí)操電源、背光與接口布局的細(xì)節(jié)2.1 電源設(shè)計(jì)為什么單獨(dú)留意IOVCC而不是只給3.3VST7789V3內(nèi)部集成了DC-DC轉(zhuǎn)換器用于產(chǎn)生面板驅(qū)動(dòng)的正負(fù)壓但它本身的工作電源分為VCI主電源和IOVCC接口邏輯電源。不同廠家的模組對(duì)這兩個(gè)引腳的對(duì)外引出方式不一樣核心板模塊通常已經(jīng)把VCI和IOVCC連在一起接3.3V但如果你是從裸屏開始做硬件設(shè)計(jì)這兩個(gè)引腳必須分別供電。VCI的典型范圍是2.4V到3.3VIOVCC的范圍是1.65V到3.3V。我設(shè)計(jì)時(shí)的策略是VCI和IOVCC都接3.3V這樣做的好處是SPI信號(hào)電平不需要額外的電平轉(zhuǎn)換電路。如果主控是5V的51單片機(jī)IOVCC可以接到3.3V然后SPI信號(hào)線上串聯(lián)330歐姆電阻限流實(shí)測(cè)穩(wěn)定工作但更規(guī)范的做法是加電平轉(zhuǎn)換芯片。電源去耦電容別省。VCI引腳旁邊至少放一個(gè)1uF和一個(gè)100nF的電容組合注意是引腳周圍緊挨著放不是隔了很遠(yuǎn)才接。DC-DC轉(zhuǎn)換器的開關(guān)頻率會(huì)通過電源走線傳導(dǎo)到其他電路尤其當(dāng)屏幕和主控共用一個(gè)LDO的時(shí)候如果去耦電容布局不合理顯示會(huì)出現(xiàn)輕微的水波紋干擾表現(xiàn)為灰階過渡時(shí)橫向條紋游走。2.2 背光電路限流電阻的算法與PWM調(diào)光頻率選擇背光LED的驅(qū)動(dòng)看似簡(jiǎn)單實(shí)際容易出錯(cuò)。大部分1.47寸模組的背光LED內(nèi)部結(jié)構(gòu)是4顆LED并聯(lián)正向壓降Vf大約在2.8V到3.2V之間。模塊廠商會(huì)把LED正極引到LEDA引腳負(fù)極引到LEDK引腳有些模塊上已經(jīng)串聯(lián)了限流電阻有些沒有。到手后先用萬用表二極管檔測(cè)一下LEDA和LEDK之間是否有電阻通路如果測(cè)出來阻值在幾十歐姆以內(nèi)說明模塊板上沒有限流電阻需要自己設(shè)計(jì)。計(jì)算公式如下限流電阻 電源電壓 - LED正向壓降 / 目標(biāo)工作電流以3.3V供電、LED正向壓降3.0V、目標(biāo)電流20mA為例 $$R (3.3 - 3.0) / 0.02 15歐姆$$實(shí)際項(xiàng)目里我用了20歐姆把電流壓到15mA左右亮度依然充足而且長(zhǎng)時(shí)間點(diǎn)亮發(fā)熱量更低對(duì)延長(zhǎng)屏幕壽命有好處。如果你用5V供電就需要串聯(lián)100歐姆左右的電阻注意電阻的功率5V-3V壓降2V乘以20mA等于40mW0603封裝的電阻是1/10W有余量但發(fā)熱稍大最好用0805封裝。PWM調(diào)光是另一個(gè)常見坑。MCU通過PWM控制三極管或MOS管來調(diào)節(jié)背光亮度PWM頻率如果選得不對(duì)會(huì)出現(xiàn)兩種情況頻率太低能看到肉眼可見的閃爍頻率正好落在音頻范圍內(nèi)會(huì)聽到蜂鳴器一樣的高頻嘯叫。經(jīng)驗(yàn)值建議PWM頻率不低于1kHz我習(xí)慣用5kHz到20kHz之間。這里有個(gè)細(xì)節(jié)人眼對(duì)低亮度下的低頻閃爍特別敏感當(dāng)你把背光PWM調(diào)低到10%亮度時(shí)1kHz的PWM還能看到輕微抖動(dòng)如果IL和刷新率不匹配會(huì)有摩爾紋。用20kHz可以完全消除。2.3 SPI接口連接與上下拉電阻的處理4線SPI的接線順序是固定的但有兩個(gè)細(xì)節(jié)容易被忽略。第一是DC引腳。DC用于區(qū)分命令和數(shù)據(jù)命令模式下拉低數(shù)據(jù)模式下拉高。在主控沒有輸出的時(shí)候DC引腳應(yīng)該是確定的電平否則模組上電瞬間可能誤判命令導(dǎo)致初始化失敗。如果主控的空閑GPIO是高阻態(tài)建議在DC引腳上加上下拉電阻方向取決于你驅(qū)動(dòng)代碼里默認(rèn)的電平。我一般接一個(gè)10k歐姆的下拉電阻到GND然后驅(qū)動(dòng)代碼里先拉高DC再發(fā)送數(shù)據(jù)這樣即使主控復(fù)位瞬間DC懸空模組也不會(huì)錯(cuò)誤進(jìn)入數(shù)據(jù)模式。第二是CS引腳。CS低電平有效很多初次做硬件的人習(xí)慣直接把CS接地省掉一個(gè)GPIO這在單設(shè)備總線的情況下確實(shí)可以工作但后果是初始化序列中某些依賴CS片選信號(hào)的命令可能無法正確執(zhí)行。ST7789V3的部分指令需要在CS拉高的上升沿鎖存數(shù)據(jù)如果CS一直拉低這些指令的邊界就會(huì)模糊調(diào)試時(shí)非常難查。所以不要省CS每個(gè)SPI傳輸都嚴(yán)格拉低CS、傳完拉高CS這是規(guī)范做法。SCLK和MOSI引腳的連接沒有太多講究注意控制走線長(zhǎng)度不要超過10厘米超過的話在高速傳輸時(shí)信號(hào)完整性會(huì)變差。我的實(shí)際板子上SCLK和MOSI走線長(zhǎng)度大約3厘米SPI時(shí)鐘跑到30MHz的時(shí)候用示波器測(cè)量波形邊沿仍然干凈沒有明顯過沖。2.4 復(fù)位電路RC復(fù)位還是GPIO控制ST7789V3的復(fù)位引腳也是容易被忽略的地方。如果只是上電后用RC電路產(chǎn)生復(fù)位脈沖有時(shí)候模組內(nèi)部電源還沒穩(wěn)定復(fù)位就結(jié)束了容易造成初始化失敗。我的做法是用MCU的一個(gè)GPIO專門控制RESET引腳初始化流程為先拉低RESET至少10毫秒然后拉高等待120毫秒以上再開始發(fā)送初始化命令。這個(gè)時(shí)間序列是從ST7789V3數(shù)據(jù)手冊(cè)的中“Power On Sequence”章節(jié)里提煉的實(shí)際上大多數(shù)第三方圖形庫也是這樣實(shí)現(xiàn)。如果GPIO數(shù)量緊張可以用一個(gè)1uF電容和10k歐姆電阻組成RC復(fù)位電路R連接到3.3VC連接到RESET和GND這樣上電時(shí)RC充電過程提供了一個(gè)約10毫秒的低電平脈沖。但要注意這種被動(dòng)復(fù)位無法在運(yùn)行過程中軟復(fù)位屏幕遇到長(zhǎng)時(shí)間運(yùn)行后花屏的情況只能斷電重啟。從可維護(hù)性出發(fā)還是建議占用一個(gè)GPIO。3. 上電啟動(dòng)與初始化序列調(diào)試從黑屏到顯示第一幀畫面的完整代碼3.1 初始化序列中關(guān)鍵寄存器的逐一解讀網(wǎng)上能找到很多ST7789V的初始化代碼但直接拿給ST7789V3用不一定成功。我整理了一套針對(duì)1.47寸240x280屏幕的初始化序列這里不貼完整代碼只拆解幾個(gè)最關(guān)鍵的部分。首先是解鎖命令0xFE和0xFF。ST7789V3的部分?jǐn)U展寄存器需要先寫入0xFE和0xFF解鎖才能訪問相當(dāng)于進(jìn)入隱藏設(shè)置頁面。很多初始化失敗就是因?yàn)槁┝诉@一步。然后是0x36 MADCTL寄存器這個(gè)控制顯示方向、RGB/BGR順序。對(duì)于1.47寸240x280的屏幕我的配置是0x00或0xC0具體取決于屏幕的安裝方向。這里的坑在于如果你把0x36配置成RGB順序但屏幕本身是BGR排列顏色就會(huì)變成紅藍(lán)互換人像膚色會(huì)偏青。0x36寄存器的第3位控制顏色順序在調(diào)試時(shí)先設(shè)置一個(gè)方向刷純紅、純綠、純藍(lán)三色畫面確認(rèn)顏色順序正確后再做圖形界面。接著是0x3A像素格式寄存器。ST7789V3支持RGB4440x03、RGB5650x05、RGB6660x06三種像素格式其中RGB565是16位色色彩表現(xiàn)力和傳輸效率的平衡最好。SPI接口下強(qiáng)制用RGB565因?yàn)镽GB666雖然色彩更細(xì)膩但數(shù)據(jù)位不對(duì)齊驅(qū)動(dòng)庫需要額外處理得不償失。再然后是電源控制寄存器組0xC0到0xC7。這部分每個(gè)屏幕廠商都會(huì)給一組推薦值根據(jù)液晶面板的VCOM電壓和伽馬特性定制的。不同批次的面板甚至都可能有細(xì)微差異如果顏色出現(xiàn)明顯色偏優(yōu)先檢查這一組寄存器而不應(yīng)該先懷疑伽馬曲線。我用的模組廠商提供的序列里0xC0寫入0x2C、0xC1寫入0x12另一家供應(yīng)商同樣的屏寫0xC5為0x28、0xC6為0x19直接拷過來屏幕就出現(xiàn)輕微泛白。用原廠推薦值解決了。最后是伽馬曲線寄存器0xE0和0xE1各自包含15個(gè)字節(jié)的數(shù)據(jù)用于微調(diào)不同灰階的亮度曲線。這個(gè)字段通常直接拷貝廠商提供的值即可如果需要偏暖或偏冷的顯示效果修改這幾組數(shù)據(jù)比在MCU側(cè)做軟件色彩校正更高效。3.2 上電時(shí)序與初始化序列的發(fā)送順序上電時(shí)序的錯(cuò)誤不會(huì)立刻暴露往往在隔夜冷啟動(dòng)的瞬間才會(huì)復(fù)現(xiàn)。ST7789V3數(shù)據(jù)手冊(cè)要求VCI和IOVCC建立穩(wěn)定后至少等待5毫秒才能拉高RESETRESET拉高后又需要等待120毫秒才能發(fā)送第一條命令。我的初始化鐵律如下拉高背光PWM如果硬件上背光由MCU控制拉低RESET保持至少10毫秒拉高RESET阻塞延時(shí)150毫秒給內(nèi)部DC-DC建立電壓的時(shí)間發(fā)送0x01 Soft Reset命令延時(shí)200毫秒發(fā)送完整的寄存器配置序列最后發(fā)送0x29 Display On命令前幾步很多人都知道但第五步容易漏。ST7789V3上電后默認(rèn)處于Sleep Out之前的狀態(tài)面板還在睡眠模式如果跳過0x01直接配置寄存器雖然也能配置成功但后續(xù)Display On之后可能出現(xiàn)屏幕亮度不均勻的現(xiàn)象。我實(shí)測(cè)跳過Soft Reset后屏幕右半部分會(huì)輕微偏亮重新補(bǔ)上0x01并等待200毫秒后恢復(fù)正常據(jù)說這是內(nèi)部電荷泵的充放電沒有完全復(fù)位導(dǎo)致的。3.3 SPI時(shí)序參數(shù)實(shí)測(cè)與配置驅(qū)動(dòng)代碼里SPI速率的設(shè)置直接決定了畫面刷新體驗(yàn)。ST7789V3的最大SPI時(shí)鐘頻率標(biāo)稱是62MHz但實(shí)際跑多快取決于三個(gè)方面主控的SPI外設(shè)最高頻率、FPC排線和PCB走線的信號(hào)質(zhì)量、以及模組上是否有ESD保護(hù)器件增加容性負(fù)載。我用STM32F103的SPI1實(shí)測(cè)分頻到18MHz時(shí)讀寫寄存器完全正常畫面無殘留無條紋。分頻到36MHz時(shí)大部分情況下正常工作但在畫面從全黑切換成全白這種極端高翻轉(zhuǎn)率的場(chǎng)景下屏幕頂部偶爾會(huì)出現(xiàn)一條細(xì)小的橫向干擾紋。分析原因是長(zhǎng)排線在高頻下產(chǎn)生了振鈴信號(hào)過沖導(dǎo)致模組內(nèi)部寄存器被誤觸發(fā)。最終我把SPI時(shí)鐘穩(wěn)定在18MHz整幀刷新時(shí)間從之前的107毫秒縮短到了約75毫秒視覺上已經(jīng)足夠流暢。這里有一個(gè)提升穩(wěn)定性的技巧配置SPI的CPOL0、CPHA1也就是模式1。ST7789V3的數(shù)據(jù)手冊(cè)明確支持SPI Mode 0和Mode 3但模式1和模式2在采樣邊沿上正好相反。我測(cè)試下來模式0CPOL0CPHA0是兼容性最好的選擇絕大多數(shù)主控的SPI外設(shè)默認(rèn)支持。如果你選模式3很多國(guó)產(chǎn)MCU的SPI外設(shè)在極高頻率下會(huì)出現(xiàn)不可控的相位偏移表現(xiàn)為偶發(fā)的一個(gè)像素錯(cuò)位。4. 驅(qū)動(dòng)調(diào)試中踩過的坑與排查鏈路白屏、花屏與偏色問題4.1 白屏不顯示從電源到復(fù)位的逐級(jí)排查點(diǎn)亮屏幕的第一關(guān)就是白屏。所謂白屏就是背光亮了但屏幕上沒有任何內(nèi)容這通常是系統(tǒng)性的故障不是某一個(gè)寄存器配置錯(cuò)誤造成的。我的排查鏈路按順序如下第一步萬用表測(cè)電源電壓。分別在VCI和IOVCC測(cè)試點(diǎn)量電壓確認(rèn)在3.15V到3.3V之間。如果電壓偏低比如掉到2.8V說明電源供應(yīng)能力不足最常見的原因是背光LED和邏輯電路共用一個(gè)LDO背光電流拉低整個(gè)電壓。解決辦法是把背光供電獨(dú)立出來或者增大LDO輸出電流。第二步示波器看RESET引腳波形。上電瞬間RESET應(yīng)該有一個(gè)從低到高的上升沿如果RESET一直為低模組永遠(yuǎn)處于復(fù)位狀態(tài)。有幾次我把RESET接到了MCU的NRST引腳結(jié)果MCU自己在運(yùn)行過程中復(fù)位的時(shí)候屏幕也跟著復(fù)位了初始化序列被中斷表現(xiàn)也是白屏。后來把RESET換到普通GPIO后問題解決。第三步邏輯分析儀抓CS、DC、SCLK、MOSI四路信號(hào)。確認(rèn)初始化序列確實(shí)在發(fā)送而且發(fā)送的內(nèi)容正確。這一步能快速判斷是軟件沒跑到初始化還是初始化了但沒有生效。如果邏輯分析儀顯示MCU在死循環(huán)之前根本沒有進(jìn)入初始化函數(shù)問題就在主控程序和屏幕無關(guān)。第四步檢查背光控制信號(hào)。有些模組的背光使能引腳是高電平有效有些是低電平有效。萬用表量LEDA對(duì)地電壓如果是0V說明背光電路沒打開。我就被這個(gè)坑過一次模塊的背光控制引腳上標(biāo)著BL看起來像高電平有效實(shí)際上模組內(nèi)部電路是PNP三極管驅(qū)動(dòng)低電平才開背光改一下代碼邏輯就好了。4.2 花屏與殘影初始化序列和像素時(shí)鐘的聯(lián)合診斷花屏的典型現(xiàn)象是屏幕上出現(xiàn)雪花、色塊、錯(cuò)位條紋或者刷新畫面時(shí)留下的殘影。這個(gè)問題比白屏復(fù)雜因?yàn)樯婕暗囊蛩馗?。我遇到的第一次花屏是初始化序列里漏掉?x36 MADCTL寄存器。屏幕默認(rèn)的掃描方向是水平翻轉(zhuǎn)的導(dǎo)致MCU往左上角寫像素實(shí)際顯示在右下角看起來就是內(nèi)容錯(cuò)位加顏色混亂。解決方法是向0x36寫入0xC0對(duì)應(yīng)240x280分辨率下從左到右、從上到下的掃描方向。第二次花屏是刷新過程中出現(xiàn)的隨機(jī)橫條。這種隨機(jī)性故障和寄存器配置的關(guān)系不大優(yōu)先懷疑SPI時(shí)鐘頻率過高或者供電噪聲。我把SPI時(shí)鐘從36MHz降到18MHz之后橫條徹底消失。如果需要保高頻可以嘗試在SCLK引腳上串一個(gè)22歐姆電阻抑制過沖。殘影問題特別是長(zhǎng)時(shí)間顯示固定畫面后切換頁面下一幀隱約能看到上一幀的內(nèi)容這通常不是驅(qū)動(dòng)問題而是液晶面板本身的特性??梢試L試在切換畫面之前刷一幀全黑畫面讓液晶分子快速回到松弛狀態(tài)但會(huì)引入一幀的黑屏閃爍。更優(yōu)雅的做法是避免在畫面切換時(shí)直接寫全屏改用局部刷新只更新變化區(qū)域殘影會(huì)大幅減少。4.3 偏色問題排查RGB順序與伽馬曲線的雙重影響我在調(diào)試中遇到過三種典型的偏色紅藍(lán)互換、整體偏綠、灰階斷層。紅藍(lán)互換的問題在4.1節(jié)提到過通過修改0x36寄存器的第3位BGR位能解決。但有一種特殊情況就是屏幕廠商在模組內(nèi)部已經(jīng)把BGR信號(hào)用硬件交叉了你再修改寄存器的BGR位反而會(huì)得到相反的結(jié)果。這里的判斷方法是先刷一個(gè)純紅色畫面如果顯示出來是藍(lán)色翻轉(zhuǎn)BGR位后再試直到顏色正確。整體偏綠的現(xiàn)象我在一塊不同批次的屏幕上遇到過。當(dāng)時(shí)查下來是電源控制寄存器0xC6的值導(dǎo)致的原批次寫入0x19新批次必須寫0x13否則VCOM電壓偏離正常范圍綠色通道被過度放大。這印證了之前說的不同批次的面板VCOM推薦值可能存在差異。灰階斷層表現(xiàn)為純黑到純白的漸變中出現(xiàn)明顯色帶通常是像素格式寄存器0x3A配置成了RGB444。RGB444只有4位色深顏色會(huì)明顯斷層。確認(rèn)0x3A的值是0x05即RGB565。4.4 運(yùn)行時(shí)意外花屏DMA與中斷的潛在沖突這個(gè)問題屬于深層驅(qū)動(dòng)的坑不一定每個(gè)人都會(huì)遇到但遇到了會(huì)非常難排查。我在主控上啟用了SPI的DMA傳輸來加速刷屏偶爾會(huì)在系統(tǒng)中斷繁忙時(shí)出現(xiàn)整屏隨機(jī)花點(diǎn)。用邏輯分析儀看DMA傳輸?shù)牟ㄐ伟l(fā)現(xiàn)CS信號(hào)在DMA傳輸中途被MCU的某個(gè)中斷服務(wù)函數(shù)拉高了SPI傳輸被強(qiáng)制終止模組接收到的數(shù)據(jù)不完整。解決方案是在DMA傳輸期間關(guān)閉可屏蔽中斷或者使用SPI的中斷標(biāo)志位判斷傳輸完成而不是依賴DMA傳輸完成中斷。更穩(wěn)妥的做法是給SPI傳輸定義一個(gè)臨界區(qū)在CS拉低之前關(guān)閉所有優(yōu)先級(jí)低于SPI的中斷CS拉高之后重新開啟。代價(jià)是刷屏期間系統(tǒng)無法響應(yīng)其他緊急事件但這個(gè)代價(jià)在HMI場(chǎng)景下完全可以接受。5. 進(jìn)階優(yōu)化幀率、雙緩沖與長(zhǎng)時(shí)間穩(wěn)定運(yùn)行的實(shí)測(cè)經(jīng)驗(yàn)5.1 幀率優(yōu)化從整屏刷新到區(qū)域刷新很多剛上手的人刷新畫面時(shí)習(xí)慣調(diào)用全屏刷新函數(shù)哪怕只改了一個(gè)數(shù)字也會(huì)把整個(gè)240x280緩沖區(qū)通過SPI發(fā)一遍。在18MHz時(shí)鐘下整屏RGB565數(shù)據(jù)是134400字節(jié)需要約75毫秒。如果界面上有10個(gè)動(dòng)態(tài)控件每個(gè)控件每秒鐘更新2次光刷屏就占掉了1.5秒的傳輸時(shí)間MCU其他任務(wù)幾乎沒法做。優(yōu)化方案是區(qū)域刷新。ST7789V3支持通過設(shè)置窗口地址CASET和RASET寄存器來限定寫入?yún)^(qū)域只把發(fā)生變化區(qū)域的像素?cái)?shù)據(jù)發(fā)給屏幕。具體實(shí)現(xiàn)方式先發(fā)送0x2A設(shè)置列地址范圍再發(fā)送0x2B設(shè)置行地址范圍然后發(fā)送0x2C開始寫顯存數(shù)據(jù)。這樣更新一個(gè)100x50像素的控件區(qū)域只需要100502字節(jié)等于10000字節(jié)在同一時(shí)鐘頻率下刷新時(shí)間縮短到約6毫秒視覺流暢度提升了一個(gè)量級(jí)。區(qū)域刷新需要注意邊界對(duì)齊。如果頻繁更新一個(gè)區(qū)域且邊界的X坐標(biāo)不是8的倍數(shù)會(huì)導(dǎo)致上下幀之間出現(xiàn)一條1像素寬的殘留亮線。原因是LCD面板的掃描線在邊界處存在像素翻轉(zhuǎn)延遲實(shí)際上解決方法是把區(qū)域邊界對(duì)齊到偶數(shù)像素。另外窗口地址寄存器的值必須嚴(yán)格遞增否則顯示會(huì)出現(xiàn)亂序。5.2 雙緩沖與撕裂效應(yīng)的簡(jiǎn)單規(guī)避單緩沖刷新時(shí)如果MCU在屏幕掃描的過程中寫入顯存用戶會(huì)看到畫面撕裂——上半幀是新的下半幀是舊的。ST7789V3沒有硬件TETearing Effect引腳輸出無法通過硬件同步因此軟件避免撕裂的方法有兩種。第一種是做雙緩沖。MCU內(nèi)部維護(hù)一個(gè)完整的虛擬顯存所有圖形操作都寫入這個(gè)虛擬緩沖區(qū)然后一次性把整個(gè)緩沖區(qū)或變化區(qū)域刷給屏幕。好處是MCU端顯示邏輯永遠(yuǎn)操作一個(gè)完好的幀壞處是需要額外的134KB內(nèi)存RGB565格式下這在STM32F103這種只有64KB內(nèi)存的平臺(tái)上無法實(shí)現(xiàn)整屏雙緩沖只能對(duì)局部小區(qū)域做雙緩沖。因此更實(shí)用的方案是動(dòng)態(tài)分割法把屏幕分成若干橫向區(qū)域只對(duì)當(dāng)前更新的區(qū)域做雙緩沖。第二種是接受偶發(fā)撕裂。HMI界面的菜單切換通常發(fā)生在用戶點(diǎn)擊按鈕之后并不是和屏幕掃描嚴(yán)格同步大概率撕裂發(fā)生在非敏感區(qū)域視覺上幾乎感知不到。實(shí)測(cè)下來把SPI速率提高到18MHz以上單緩沖刷新導(dǎo)致的撕裂只出現(xiàn)在畫面高速運(yùn)動(dòng)時(shí)對(duì)于靜態(tài)菜單和數(shù)據(jù)顯示場(chǎng)景完全沒有可感知影響。5.3 長(zhǎng)時(shí)間運(yùn)行的穩(wěn)定性從初始化自愈到定期刷新屏幕長(zhǎng)時(shí)間運(yùn)行特別是工業(yè)設(shè)備那種幾個(gè)月不關(guān)機(jī)的場(chǎng)景ST7789V3偶發(fā)花屏的概率會(huì)增加。我遇到的實(shí)際情況是設(shè)備運(yùn)行一周后屏幕出現(xiàn)一條持續(xù)顯示的橫向亮帶斷電重啟后消失但過幾天又出現(xiàn)。邏輯分析儀抓初始化時(shí)序并沒有發(fā)現(xiàn)異常。問題最終定位在SPI總線的串?dāng)_上。屏幕的SCLK走線和背光PWM走線在PCB上平行走了5厘米背光PWM切換時(shí)產(chǎn)生了毛刺耦合到SCLK上長(zhǎng)期運(yùn)行中偶爾觸發(fā)一次錯(cuò)誤的時(shí)鐘沿模組的掃描狀態(tài)機(jī)被破壞。調(diào)整PCB布線使SCLK遠(yuǎn)離干擾源并在SCLK上加了一個(gè)33歐姆的串聯(lián)電阻后問題徹底消失。軟件層面我加了兩個(gè)防護(hù)措施一是SPI傳輸完成后延時(shí)1毫秒再拉高CS確保最后一位數(shù)據(jù)被正確鎖存二是每30分鐘發(fā)送一次刷新命令0x20Tearing Effect Line On實(shí)際上0x20是進(jìn)入撕裂效果模式真正需要定期做的是向屏幕重新發(fā)送0x29 Display On或者做一個(gè)完整的軟復(fù)位再初始化。這個(gè)操作耗時(shí)不足100毫秒對(duì)用戶體驗(yàn)無感但能有效清理偶發(fā)的顯示狀態(tài)異常。5.4 從51單片機(jī)到高性能MCU的移植要點(diǎn)很多入門者是拿51單片機(jī)玩ST7789V3這時(shí)候有一個(gè)棘手的問題傳統(tǒng)51的GPIO翻轉(zhuǎn)速度太慢用軟件模擬SPI時(shí)時(shí)鐘頻率只能到幾百千赫茲整屏刷新要幾秒鐘體驗(yàn)極差。一個(gè)輕松的解決方法是把屏幕接在增強(qiáng)了SPI外設(shè)的單片機(jī)上例如STM32系列。如果只能用51就考慮用STC系列帶硬件SPI的型號(hào)把SPI時(shí)鐘用硬件方式拉高到MHz級(jí)別。移植到更高性能的MCU上需要注意SPI的FIFO和DMA配置。STM32的SPI外設(shè)支持DMA發(fā)送刷屏?xí)rMCU可以繼續(xù)運(yùn)行業(yè)務(wù)邏輯CPU占用率從100%降到不到20%。在實(shí)際項(xiàng)目中我把刷屏邏輯完全放入DMA完成中斷中處理主循環(huán)只負(fù)責(zé)響應(yīng)按鍵和傳感器數(shù)據(jù)系統(tǒng)實(shí)時(shí)性大幅提升。如果追求極致刷屏速度可以嘗試STM32H7或者ESP32-S3這類帶專用LCD外設(shè)的芯片它們能直接從片內(nèi)RAM通過DMA把數(shù)據(jù)送到SPI外設(shè)而不經(jīng)過CPU搬運(yùn)整屏240x280刷到30幀是可行的。但這時(shí)SPI時(shí)鐘往往要跑到40MHz以上要注意信號(hào)完整性和初始化時(shí)序建議在主控和模組之間加一級(jí)74LVC1T45電平轉(zhuǎn)換或者縮短FPC排線。我個(gè)人的體會(huì)是ST7789V3這顆驅(qū)動(dòng)IC的水準(zhǔn)在小尺寸彩屏里屬于越用越順手的那種它的寄存器設(shè)計(jì)雖然初看繁瑣但功能劃分清晰每一個(gè)顯示異常都能找到對(duì)應(yīng)寄存器。上手階段不要急著跑復(fù)雜界面先把純色、漸變、文字、圖像這四類基礎(chǔ)顯示完整調(diào)通再逐步疊加功能這樣出了問題排查范圍會(huì)小很多。最后提醒一句每次換屏幕批次或者換供應(yīng)商都要重新跑一遍完整的顏色和灰度測(cè)試不要理所當(dāng)然覺得同一型號(hào)的屏初始化代碼一定通用。做1.47寸這種小屏方案很多時(shí)候拼的不是多高深的技術(shù)而是對(duì)每一個(gè)細(xì)節(jié)的較真程度。