目录
一 通过STM32CubeMX配置LTDC
二 配置SDRAM与DMA2D
三 通过STM32CubeMX配置STemWin(推荐)
四 添加STemWin代码(手动移植STemWin)
五 编写RGB LCD驱动文件(手动移植STemWin)
六 关联TFTLCD驱动函数与STemWin(手动移植STemWin)
开发板: 正点原子STM32F767
LCD型号: 正点原子4.3寸、分辨率为480×272的RGB屏
STM32CubeMX : Version 5.2.1
1.Parameter Setting配置
RGB LCD几个重要的参数配置如下所示:
通过上表可以得出以下关键信息:
通过以上说明配置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时钟配置如下:
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传输数据是会一直等待传输完成。
配置好LTDC后StemWin才是可选择的:
至此,已经可以生成代码,在开发板上运行程序了。
stm32cubemx官方下载地址
1. 使用STemWin必须打开CRC,否则图形库运行不起来
2.添加的代码如下:
3. 头文件路径如下:
主要实现画点, 读点,填充函数, 这里填充函数使用了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; //清除传输完成标志
}
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);
}