低硬體成本上的TouchGFX
本節討論如何在RAM和Flash大小有限、無加速且與外部Flash和顯示器的SPI連線速度慢的低成本硬體上使用TouchGFX。
我們將提供一些關於為指定硬體編寫最佳應用程式的建議。
本節將以STM32G071 Nucleo開發板和X-Nucleo-GFX01M1擴展開發板為例,描述如何對硬體使用TouchGFX開發板設置。 擴展開發板具有16位元顯示器和串列快閃記憶體。
硬體概述
該套件中的硬體設定包括STM32G071 MCU、SPI NOR flash、SPI顯示器和搖杆按鈕。
元件 | |
---|---|
MCU | STM32G071RB |
MCU RAM | 32 Kb |
MCU Flash | 128 Kb |
顯示器 | Displaytech DT022CTFT |
顯示器解析度 | 240 x 320 |
顯示格式 | 16位RGB565 |
顯示器控制器 | ILI9341V |
顯示器連接 | SPI |
顯示器連線速度 | 32 MHz |
NOR Flash | Macronix MX25L6433F |
NOR Flash大小 | 64 Mbit |
NOR Flash連線速度 | 32 MHz |
顯示器連接到SPI1外設,而快閃記憶體連接到SPI2外設。 因此,MCU能夠在向顯示器發送資料的同時從快閃記憶體讀取資料。
GPIO配置
信號 | GPIO引腳 |
---|---|
顯示CS | PB5 |
顯示DCX | PB3 |
顯示SCK | PA5 |
顯示MOSI | PA7 |
顯示TE | PA0 |
Flash CS | PB9 |
Flash SCK | PB13 |
Flash MOSI | PC3 |
Flash MISO | PC2 |
上表列出了快閃記憶體和顯示器信號的GPIO分配。 這些信號可通過示波器或邏輯分析儀進行監測。 這在諸如性能等問題的Debug中非常實用。
啟動專案
在TouchGFX Designer中,可以輕鬆地為STM32G071RB Nucleo評估套件啟動一個專案。 點擊"Create New",然後選擇STM32G071 Nucleo。 此範本專為Nucleo-G071RB套件和X-Nucleo-GFX01M1顯示板而開發。
該範本支援NOR flash、顯示器和按鈕。 顯示器有豎屏和橫屏兩種使用模式。
可以在TouchGFX Designer中的Config -> Display部分修改顯示器方向:
X-Nucleo-GFX01M1 Shield上的顯示器原本是豎屏(高度大於寬度),但很容易改為橫屏。
顯示器更新
如上文所述,顯示器解析度為240 x 320像素。 總共76,800像素或153,600位元組。 MCU與顯示器之間的SPI連接的運行頻率為32 MHz。 因此,傳送速率可以達到4 MB/s或2M像素/s。
顯示器的刷新頻率為76.1 Hz,因此每幀為13.14 ms。
這意味著有最多13 ms的時間來發送下一幀的資料。 在此期間,我們可以發送2.000.000像素/秒/76 fps=26.280像素/幀或34%的全屏。 實際上,由於協定的限制,我們無法維持SPI匯流排上的傳送速率,因此不能發送超過一個完整幀的30%左右。
如果應用更新的像素數超過此值,硬體將無法在每幀的時間以內完成發送。 結果是顯示器將在全部更新結束前開始顯示更新的幀。 因此,用戶有時會看到原來的幀與新的幀混合在一起。
對於一些動畫而言,用戶注意不到這一點,但在其他情況下可能無法接受。
因此,我們建議將更新率維持在30%以下。 如 通過漸進式地分步更新幀。
因此,一般來說最好在螢幕上擴展物件,而不是移動物件。
當星形移動到右側時,必須更新星形覆蓋的所有像素。 如果只擴展星形,則只需更新新像素。 在上一幀更新的像素保持不變。
繪製速度
向顯示器發送資料的頻率為最高32 MHz。
串列快閃記憶體能以與顯示器發送相同的速度運行。 這意味著串列快閃記憶體的速度足夠快,能以最高速度向顯示器供應資料。
這只有在快閃記憶體中的影像位元格式為RGB565時才能實現。 這種情況下,從快閃記憶體讀取的兩個位元組等於1個像素,也就是顯示器上的兩個字元。 如果快閃記憶體中的像素格式為ARGB8888,我們需要從快閃記憶體中讀取兩倍的資料量才能在顯示器上產生像素,而串列Flash將無法跟上顯示器的速度。
當發生這種情況時,不再繼續向顯示器發送資料,並且將不可能更新顯示器上一個幀資料的30%。 有一種可能的辦法是將影像移動到內部快閃記憶體,另一種辦法是更改像素格式。
其他的工具不受快閃記憶體速度的限制。 如 方框小工具,用於繪製彩色矩形。 此工具速度很快,比顯示器資料發送速度要快許多。 其他小工具(如直線和圓)需要使用更多CPU資源。 這些小工具無法以發送到顯示器的速度來生成像素。 對於使用這些小工具的應用,不能期望能夠更新顯示器上每幀的30%。
點擊這裡瞭解像素渲染的複雜性
使用串列快閃記憶體時TouchGFX的限制
應用程式撰寫者必須認識到,在具有串列快閃記憶體的STM32G0上使用TouchGFX時的幾點限制。
紋理映射器
紋理映射器小工具(TextureMapper、AnimationTextureMapper和 ScalableImage)不能繪製存儲在外部SPI快閃記憶體中的圖像。 原因在於,用存儲在串列快閃記憶體中的影像無法獲得可接受的性能,如圖像旋轉。
為了通過紋理映射器使用圖像,必須將圖像保存在內部快閃記憶體或RAM中。 通過在TouchGFX Designer中修改圖像配置,可以輕鬆地將圖像保存在內部快閃記憶體中。
轉至“Images ”選項卡並選中圖像。 在視窗的右側,將“Section”屬性更改為“IntFlashSection”。
紋理映射器的程式碼量過大,不能包含在所有專案中。 因此,對於STM32G0專案,默認禁用紋理映射器。 這意味著您必須先啟用紋理映射器,然後才能在STM32G0專案中使用它。
轉至“Config”選項卡,選擇“Framework Features”,並點擊相關的紋理映射器或一組紋理映射器。
還可以使用點陣圖緩存將圖像暫時移動到RAM
點陣圖繪製器
可通過圖像為直線、圓和DynamicGraph上色。 這不適用於存儲在SPI快閃記憶體中的圖像。 使用這些小工具的圖像必須放在內部快閃記憶體或RAM中。
L8調色板
L8格式的圖像可以用在具有串列快閃記憶體的硬體上。 限制條件是調色板資料必須放在內部快閃記憶體中(也是出於性能考量)。
通過在TouchGFX Designer中將“Extra Section”修改為“IntFlashSection”,可以將調色板移動到內部快閃記憶體。
驅動程式
應用範本是使用TouchGFX Generator創建的。 點擊此處閱讀TouchGFX Generator的更多相關內容。 TouchGFX Generator生成HAL層,它連接TouchGFX框架與一組底層驅動器(已在該應用範本中實現)。 該應用範本的底層驅動位於專案的Core/Src
資料夾中。
驅動器位於3個檔中:
驅動器 | 檔案 |
---|---|
顯示器 | Core/Src/MB1642BDisplayDriver.c |
Flash | Core/Src/MB1642BDataReader.c |
按鈕 | Core/Src/MB1642BButtonController.cpp |
顯示器
顯示器使用標準SPI協定。 為了配置顯示器,可以對顯示器中的許多暫存器執行寫入。 在資料發送到顯示器時鎖定選擇的晶片。 使用額外的GPIO(DCX)將指令位元組與資料位元組區分開來。
驅動程式使用DMA通道發送顯示器像素資料。 這樣就可以在MCU計算像素的同時進行發送。 DMA完成中斷被用來釋放已發送資料的存儲空間以便在將來繪製時重複使用,以及在有新資料可用時重新開始發送資料。
由於CS和CDX腳位必須在小封裝之間切換並位於其內部,因此不通過DMA發送配置資料。
在發送配置資料時,驅動程式使用8位元模式的SPI,但在發送像素資料時改為16位元模式。 其中的原因在於,MCU記憶體以小端模式讀取。 RGB565格式的像素存儲在RAM中,首先是低位元組(G和B),然後是高位元組(R和G)。 當8位SPI為進行發送而讀取記憶體時,維持此順序不變。 當SPI為16位元模式時,按16位元RGB565從記憶體讀取資料,並按顯示器的正確順序發送資料。
對於不使用16位DMA的驅動,必須在發送前交換像素中的位元組。
初始化
顯示器初始化在函數MB1642BDisplayDriver_DisplayInit(void)
中完成
驅動程式按照建議的上電順序向顯示器發送6個指令:
- 退出睡眠模式(11h)
- 進入正常模式(13h)
- 利用MX和BGR位置設定記憶體存取控制(36h)
- 設置像素格式(3Ah)為16位格式
- 撕裂效應線開啟(35h)
- 設置撕裂掃描線(44h)使其 = 0
驅動會在這些指令之間休眠100 ms。
撕裂效應
來自顯示器的撕裂效應(TE)信號非常重要。 從而允許應用程式將顯示器記憶體的更新與顯示刷新率正確同步。 這有助於應用程式避免顯示器上的撕裂效應。 顯示器在開始更新週期時生成信號。 MCU使用此信號向顯示器發送資料。
TE信號連接到MCU的外部中斷輸入。 CubeMx生成並配置該引腳上的中斷。
驅動中的callback 指示TouchGFX開始繪製:
MB1642BDisplayDriver.c
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
...
touchgfxSignalVSync();
}
外部快閃記憶體
顯示板卡上的SPI NOR flash是標準SPI flash。 該驅動比顯示器驅動簡單。 無需特別初始化即可從快閃記憶體讀取資料。
該驅動可使用輪詢SPI(忙碌等待所有位元組)或使用DMA讀取資料。 開始DMA接收的時間接近於以輪詢模式讀取20個位元組所需的時間,因此短讀通常較慢。 另一方面,DMA在中斷(即sysTick或應用中斷)期間繼續運行,並且可以在MCU忙於渲染像素時在後臺運行。 出於這個原因使得兩種方法皆被使用。
Flash驅動使用與顯示器驅動不同的DMA通道,因此新資料接收和已繪製像素發送可以同時運行。
連結器腳本
連結器控制應用中各種資料所在的位置。 這是在連結器腳本中指定的。 下面是gcc編譯器的連結器腳本的第一部分:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
SPI_FLASH (r) : ORIGIN = 0x90000000, LENGTH = 8M
}
它宣告NOR flash從位址0x90000000開始。 目標應用程式中的Flash驅動器從SPI Flash讀取0x90000000位址中的資料(使用較低的24位作為Flash中的位址)。
STM32CubeProgramer中使用的外部快閃記憶體載入器可以將此範圍內的資料燒錄到SPI Flash(見下文)。
第二部分將圖像(ExtFlashSection)和字體(FontFlashSection)資料放在SPI快閃記憶體中。
ExtFlashSection :
{
*(ExtFlashSection ExtFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SPI_FLASH
FontFlashSection :
{
*(FontFlashSection FontFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SPI_FLASH
通過向連結器腳本中添加相似分區,可將其他資料放入SPI快閃記憶體。
快閃記憶體下載
G071 TouchGFX開發板設置包含STM32CubeProgrammer的快閃記憶體載入器。 此快閃記憶體載入器可將資料寫入SPI NOR flash。
快閃記憶體載入器位於文件gcc/S25FL032P_STM32G071B-NUCLEO.stldr
中
STM32CubeIDE專案可以直接從CubeIDE燒錄,但IAR或Keil應用程式必須從STM32CubeProgrammer燒錄。
STM32CubeProgrammer中最初不能使用快閃記憶體載入器,必須將stldr複製到安裝資料夾進行安裝:
現在,可以正常地在STM32CubeProgrammer中選擇快閃記憶體載入器:
Tip
如果在自訂硬體上對串列快閃記憶體使用其他GPIO配置,則必須相應地修改快閃記憶體載入器。
按鈕
按鈕驅動十分簡單。 它對MB1642B上的搖杆和Nucleo板上的藍色按鈕使用的5個GPIO的狀態進行採樣。
此按鈕驅動作為BottonController安裝在TouchGFX中。 這意味著可以直接在TouchGFX Designer中點擊按鈕以便使用。 還可以在用戶程式碼中使用它們,例如:
void Screen1View::handleKeyEvent(uint8_t key)
{
if (key == '6')
{
application().gotoScreen2Screen();
}
}
使用的鍵碼:
鍵 | 程式碼 |
---|---|
左 | '4' |
右 | '6' |
上 | '8' |
下 | '2' |
中 | '5' |
藍色按鈕 | '0' |
當您使用鍵盤numpad運行模擬器(在TouchGFX Designer中點擊F5
) 時,這些鍵也可以使用。