目錄
六 關聯TFTLCD驅動函數與STemWin(手動移植STemWin)
開發板: 正點原子STM32F767
LCD型號: 正點原子4.3寸、分辨率爲480×272的RGB屏
STM32CubeMX : Version 5.2.1
一 通過STM32CubeMX配置LTDC
1.Parameter Setting配置
RGB LCD幾個重要的參數配置如下所示:
通過上表可以得出以下關鍵信息:
- LCD頻率可配置爲9MHz
- VSYNC width:垂直同步脈寬, 取值1
- VBP:垂直後廊,表示垂直同步信號後,無效行的個數,取值8
- VFP:垂直前廊,表示一幀數據輸出結束後,到下一個垂直同步信號開始之前的無效行數,取值8
- Active Height:有效高度,橫屏取值272,豎屏取值480
- HSYNC width:水平同步脈寬,取值1
- HBP:水平後廊,,表示水平同步信號開始到行有效數據開始之間的相素時鐘(CLK)個數,取值40
- HFP:水平前廊,表示行有效數據結束到下一個水平有效信號開始之前的相素時鐘(CLK)個數,取值5
- Active width:有效寬度,橫屏取值480,豎屏取值272
通過以上說明配置Parameter Setting如下所示:
2 Layer Setting配置
RGB LCD可以配置兩層,一般情況下Layer1作爲前景層,Layer0作爲背景層,需要知道的是這裏的兩層是軟件層面上的,硬件上LCD只有一層,最終顯示時,是將兩層數據進行混合形成一層數據,再發送給LCD進行顯示。
例如下圖有一副前景圖片,該圖片含有透明因子,該圖片存放在Layer1對應的buff1中;另有一副背景圖片,該圖片存放在Layer0對應的buff0中。stm32通過混合運算,將buff1與buff0中的數據進行合併後再發送給RGB LCD顯示。
3. GPIO Setting配置如下:
4. 配置像素時鐘
通過數據手冊得知時鐘範圍爲5~12MHz,典型爲9MHz,所以LCD-TFT時鐘配置如下:
二 配置SDRAM與DMA2D
LCD採用RGB565的方式,所以每一個點的顏色佔用2字節, LCD共有480×272個點
所以LCD一層的顯示至少需要 480×272×2 = 261120 byte = 255 kb
一般情況下RGBLCD有兩層,如果需要兩層顯示則需要 255 ×2 = 510 kb
而stm32f767內置flash只有512kb, 明顯是不夠用的,所以需要使用外擴SDRAM.
1. 通過STM32CubeMX配置SDRAM可參考博客: https://blog.csdn.net/Ningjianwen/article/details/90940570
2. 配置DMA2D
Chrom-Art Accelerator™ (DMA2D) 是專用於圖像處理的專業 DMA。由前面介紹可知,顯示的圖形是通過一定格式存儲在內存中,要改變顯示的內容,只需將新的數據存儲在對應的顯存中即可,可以通過DMA傳輸數據。DMA2D和普通的DMA通道不一樣是,它是專用於圖像處理的專用DMA,他可以執行下列操作。
- 用特定顏色填充目標圖像的一部分或全部
- 將源圖像的一部分(或全部)複製到目標圖像的一部分(或全部)中
- 通過像素格式轉換將源圖像的一部分或全部複製到目標圖像的一部分或全部中
- 將像素格式不同的兩個源圖像部分和 / 或全部混合,再將結果複製到顏色格式不同的部分或整個目標圖像中。
DMA2D的Parameter Setting配置如下所示:
需要特別注意的是,這裏必須要配置DMA2D中斷,否則在使用DMA2D傳輸數據是會一直等待傳輸完成。
三 通過STM32CubeMX配置STemWin(推薦)
配置好LTDC後StemWin纔是可選擇的:
至此,已經可以生成代碼,在開發板上運行程序了。
四 添加STemWin代碼(手動移植STemWin)
1. 使用STemWin必須打開CRC,否則圖形庫運行不起來
2.添加的代碼如下:
3. 頭文件路徑如下:
五 編寫RGB LCD驅動文件(手動移植STemWin)
主要實現畫點, 讀點,填充函數, 這裏填充函數使用了DMA2D
#define LTDC_WIDTH 480
#define LTDC_HEIGHT 272
uint16_t ltdc_layer0[LTDC_HEIGHT][LTDC_WIDTH] __attribute__((at(LAYER0_ADDR))); //定義最大屏分辨率時,LCD所需的幀緩存數組大小
uint16_t ltdc_layer1[LTDC_WIDTH][LTDC_HEIGHT] __attribute__((at(LAYER1_ADDR))); //定義最大屏分辨率時,LCD所需的幀緩存數組大小
/***************************************************************************************
* @brief 讀取個某點的顏色值
* @input x,y:座標
* @return 返回值:此點的顏色
***************************************************************************************/
uint32_t LCD_ReadPoint(uint16_t x, uint16_t y)
{
return *(uint16_t*)((uint32_t)ltdc_layer0[0] + 2 * (LTDC_WIDTH * y + x));
}
/***************************************************************************************
* @brief 畫點
* @input x,y:座標 color:顏色
* @return
***************************************************************************************/
void LCD_DrawPoint(uint16_t x, uint16_t y, uint32_t color)
{
*(uint16_t*)((uint32_t)ltdc_layer0[0] + 2 * (LTDC_WIDTH * y + x)) = color;
}
/***************************************************************************************
* @brief 在指定區域內填充單個顏色
* @input (sx,sy),(ex,ey):填充矩形對角座標,區域大小爲:(ex-sx+1)*(ey-sy+1)
* @input color:要填充的顏色
* @return
***************************************************************************************/
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color)
{
uint32_t timeout = 0;
uint32_t addr = ((uint32_t)ltdc_layer0[0] + 2 * (LTDC_WIDTH * sy + sx));//輸出存儲器地址
uint16_t offline = LTDC_WIDTH - (ex - sx + 1); //設置行偏移
RCC->AHB1ENR |= RCC_AHB1LPENR_DMA2DLPEN; //使能DM2D時鐘
DMA2D->CR = DMA2D_CR_MODE; //寄存器到存儲器模式
DMA2D->OPFCCR = LTDC_PIXEL_FORMAT_RGB565;//設置顏色格式
DMA2D->OOR = offline;
DMA2D->CR &= ~(DMA2D_CR_START); //先停止DMA2D
DMA2D->OMAR = addr;
DMA2D->NLR = (ey - sy + 1) | ((ex - sx + 1)<<16);//設定行數寄存器
DMA2D->OCOLR = color; //設定輸出顏色寄存器
DMA2D->CR |= DMA2D_CR_START; //啓動DMA2D
while((DMA2D->ISR & DMA2D_ISR_TCIF) == 0) //等待傳輸完成
{
timeout++;
if(timeout>0X1FFFFF)
break; //超時退出
}
DMA2D->IFCR |= DMA2D_IFCR_CTCIF; //清除傳輸完成標誌
}
六 關聯TFTLCD驅動函數與STemWin(手動移植STemWin)
1. 註釋掉LCD_ConfDefaults.h和LCD_Private.h文件中的#include "LCDConf.h"
2. GUIConf.h 文件中添加 #define OS_SUPPORT 啓用OS
3. 從STemWin庫中複製STemWin_Library_V1.2.0\Project\STM32469I-EVAL\RTOS\Config\GUI_X_FreeRTOS.c文件
替代GUI_X_OS.c文件中的內容. (stm32cubemx官方下載地址)
4. 修改LCDConf_FlexColor_Template.c文件
在這個文件中我們要完成 STemWin 的打點(_SetPixelIndex())、讀點(_GetPixelIndex())、填充(_FillRect())等函數的實現
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
......
GUI_USE_PARA(PixelIndex);
{
LCD_DrawPoint(x,y,PixelIndex); //此處調用畫點函數
}
......
}
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
......
GUI_USE_PARA(y);
{
PixelIndex = LCD_ReadPoint(x,y); //次處調用讀點函數
}
......
}
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) {
......
if (GUI_pContext->DrawMode & LCD_DRAWMODE_XOR) {
......
} else {
LCD_Fill(x0,y0,x1,y1,LCD_COLORINDEX);//此處修改爲畫矩形函數
}
}
5.修改LCDConf_FlexColor_Template.c
該文件主要修改LCD_X_Config函數 與XSIZE_PHYS /YSIZE_PHYS 兩個宏,
有一點需要注意:GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
該函數的第一個參數是有修改的,表示我們使用的驅動函數是GUIDRV_Template_API數組中的函數
#define XSIZE_PHYS 480// To be adapted to x-screen size
#define YSIZE_PHYS 272// To be adapted to y-screen size
void LCD_X_Config(void) {
// Set display driver and color conversion
//
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
//
// Display driver configuration, required for Lin-driver
//
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);
}