STM32f746gdiscovery LTDC 驱动

需要提前准备好SDRAM驱动,如果没有SDRAM可以进行纯色彩测试,底层时钟,IO操作相关看注释,我使用的是寄存器封装的。

/*************************************************************************************************************
 * 文件名		:	stm32f7_ltdc.c
 * 功能			:	STM32F7 外部RGB LCD驱动
 * 作者			:	[email protected]
 * 创建时间		:	2019-09-12
 * 最后修改时间	:	2019-09-12
 * 详细:	
*************************************************************************************************************/	
#include "stm32f7_ltdc.h"
#include "SYSTEM.H" 
#include "stm32f7_sdram.h"
#include "DMA2D.h"


u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH]  __attribute__ ((at(Bank5_SDRAM_ADDR)));		//需要SDRAM支持,LCD帧缓冲区,RGB888格式


//记录全局层配置信息
typedef struct
{
	u16 sx;					//层开始X坐标,从0开始
	u16 sy;					//层开始Y坐标,从0开始
	u16 width;				//层宽度
	u16 height;				//层高度
	u32 *pFrameBuff;		//帧缓冲区指针,需要进行初始化
}LTDC_LayerConfig;



//全局的LTDC配置信息
typedef struct
{
	u16 lcd_width;						//显示器宽度
	u16 lcd_height;						//显示器高度
	LTDC_LayerConfig LayerConfig[2];	//层信息
}LTDC_ConfigData;


static LTDC_ConfigData sg_LTDC_ConfigData;	//记录全局的LCD配置


//显示屏信息
typedef struct
{
	u16 	Width;		//面板宽度,单位:像素
	u16 	Height;		//面板高度,单位:像素
	u8  	Thbp;		//水平后廊
	u8  	Thfp;		//水平前廊
	u8  	Thw;		//水平同步宽度
	u8  	Tvbp;		//垂直后廊
	u8  	Tvfp;		//垂直前廊
	u8  	Tvw;		//垂直同步宽度
	u8  	DCLK;		//时钟速度,MHz
	
	u8		HSPOL;		//水平同步极性,0:低电平有效;1:高电平有效
	u8		VSPOL;		//垂直同步极性,0:低电平有效;1:高电平有效
	u8		DEPOL;		//数据使能极性,0:低电平有效;1:高电平有效
	bool	PCPOL;		//像素时钟反向
}LTDC_INFO_TYPE;


LTDC_INFO_TYPE DefaultLCD_Info =
{
	480,	//面板宽度,单位:像素
	272,	//面板高度,单位:像素
	41,		//水平后廊
	8,		//水平前廊
	2,		//水平同步宽度
	2,		//垂直后廊
	4,		//垂直前廊
	10,		//垂直同步宽度
	9,		//时钟速度,MHz
	0,		//水平同步极性,0:低电平有效;1:高电平有效
	0,		//垂直同步极性,0:低电平有效;1:高电平有效
	1,		//数据使能极性,0:低电平有效;1:高电平有效
	FALSE,	//像素时钟反向
};

bool LTDC_ClockInit(u16 ClockFreq);							//STM32F4 LTDC时钟初始化


/*************************************************************************************************************************
* 函数	:			void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)
* 功能	:			LTDC 层窗口尺寸设置(会自动根据窗口尺寸以及像素格式设置帧缓冲区大小)
* 参数	:			LayerIndex:层选择(0-1);sx,sy:起始坐标;width,height:宽度和高度
* 返回	:			无
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2019-10-28
* 最后修改时间 : 	2019-10-28
* 说明	: 			不会使能层,不会更新层,只设置配置,需要刷新层配置后更新
*************************************************************************************************************************/ 
void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)
{
	u32 temp;
	u8 pixformat=0; 
	
	if(LayerIndex==0)
	{
		//基本配置
		LTDC_Layer1->CFBAR = FrameBuff;									//设置层颜色帧缓存起始地址
		LTDC_Layer1->PFCR = LTDC_PIXEL_FORMAT;							//设置层颜色格式
		LTDC_Layer1->CACR = Alpha;										//常数 Alpha,255分频;设置255,则不透明
		LTDC_Layer1->DCCR = 0x00;										//设置默认颜色:透明的黑色
		LTDC_Layer1->BFCR = ((u32)6<<8)|7;								//设置层混合系数
		//配置窗口
		temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16; 
		LTDC_Layer1->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;//设置行起始和结束位置 
		temp = (sy+height+(LTDC->BPCR&0X7FF))<<16; 
		LTDC_Layer1->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;			//设置列起始和结束位置
		pixformat = LTDC_Layer1->PFCR&0X07;								//得到颜色格式
		if(pixformat == 0)temp=4;										//ARGB8888,一个点4个字节
		else if(pixformat == 1)temp=3;									//RGB888,一个点3个字节
		else if(pixformat==5||pixformat==6)temp=1;						//L8/AL44,一个点1个字节
		else temp=2;													//其他格式,一个点2个字节
		LTDC_Layer1->CFBLR = (width*temp<<16)|(width*temp+3);			//帧缓冲区长度设置(字节为单位)
		LTDC_Layer1->CFBLNR = height;									//帧缓冲区行数设置	
		
		//记录层窗口大小位置信息
		sg_LTDC_ConfigData.LayerConfig[0].sx = sx;		
		sg_LTDC_ConfigData.LayerConfig[0].sy = sy;	
		sg_LTDC_ConfigData.LayerConfig[0].width = width;	
		sg_LTDC_ConfigData.LayerConfig[0].height = height;	
	}else
	{
		//基本配置
		LTDC_Layer2->CFBAR = FrameBuff;									//设置层颜色帧缓存起始地址
		LTDC_Layer2->PFCR = LTDC_PIXEL_FORMAT;							//设置层颜色格式
		LTDC_Layer2->CACR = Alpha;										//常数 Alpha,255分频;设置255,则不透明
		LTDC_Layer2->DCCR = 0x00;										//设置默认颜色:透明的黑色
		LTDC_Layer2->BFCR = ((u32)6<<8)|7;								//设置层混合系数
		//配置窗口
		temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16; 
		LTDC_Layer2->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;	//设置行起始和结束位置 
		temp = (sy+height+(LTDC->BPCR&0X7FF))<<16; 
		LTDC_Layer2->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;			//设置列起始和结束位置
		pixformat = LTDC_Layer2->PFCR&0X07;								//得到颜色格式
		if(pixformat == 0)temp=4;										//ARGB8888,一个点4个字节
		else if(pixformat == 1)temp=3;									//RGB888,一个点3个字节
		else if(pixformat == 5||pixformat==6)temp=1;					//L8/AL44,一个点1个字节
		else temp = 2;													//其他格式,一个点2个字节
		LTDC_Layer2->CFBLR = (width*temp<<16)|(width*temp+3);			//帧缓冲区长度设置(字节为单位)
		LTDC_Layer2->CFBLNR = height;									//帧缓冲区行数设置	
		
		//记录层窗口大小位置信息
		sg_LTDC_ConfigData.LayerConfig[1].sx = sx;		
		sg_LTDC_ConfigData.LayerConfig[1].sy = sy;	
		sg_LTDC_ConfigData.LayerConfig[1].width = width;	
		sg_LTDC_ConfigData.LayerConfig[1].height = height;		
	}
}



/*************************************************************************************************************************
* 函数	:			void LTDC_Init(void)
* 功能	:			LTDC 接口初始化
* 参数	:			无
* 返回	:			无
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2019-09-08
* 最后修改时间 : 	2019-09-08
* 说明	: 			用于初始化STM32F7 LTDC 接口
*************************************************************************************************************************/  
void LTDC_Init(void)
{
	u32 temp;
	
	SYS_DeviceClockEnable(DEV_LTDC, TRUE);	//LTDC时钟使能
	SYS_DeviceReset(DEV_LTDC);				//STM32F7外设复位
	SYS_DeviceClockEnable(DEV_GPIOE, TRUE);	//使能GPIOE时钟
	SYS_DeviceClockEnable(DEV_GPIOG, TRUE);	//使能GPIOG时钟
	SYS_DeviceClockEnable(DEV_GPIOJ, TRUE);	//使能GPIOJ时钟
	SYS_DeviceClockEnable(DEV_GPIOK, TRUE);	//使能GPIOK时钟
	SYS_DeviceClockEnable(DEV_GPIOI, TRUE);	//使能GPIOI时钟

	
	//初始化IO
	SYS_GPIOx_Init(GPIOE, BIT4, AF_PP_OPU, SPEED_100M);										//PE4
	SYS_GPIOx_Init(GPIOG, BIT12, AF_PP_OPU, SPEED_100M);									//PG12
	SYS_GPIOx_Init(GPIOJ, 0Xffff&(~BIT12), AF_PP_OPU, SPEED_100M);							//PJ0~11/13/14/15
	SYS_GPIOx_Init(GPIOK, BIT0|BIT1|BIT2|BIT4|BIT5|BIT6|BIT7, AF_PP_OPU, SPEED_100M);		//PK0/1/2/4/5/6/7
	SYS_GPIOx_Init(GPIOI, BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M);					//PI9/10/14/15
	
	SYS_GPIOx_SetAF(GPIOE, 4, AF14_LTDC);		//PE4,AF14	
 	SYS_GPIOx_SetAF(GPIOG, 12, AF14_LTDC);		//PG12,AF14	
	SYS_GPIOx_SetAF(GPIOJ, 0, AF14_LTDC);		//PJ0,AF14
	SYS_GPIOx_SetAF(GPIOJ, 1, AF14_LTDC);		//PJ1,AF14
	SYS_GPIOx_SetAF(GPIOJ, 2, AF14_LTDC);		//PJ2,AF14
	SYS_GPIOx_SetAF(GPIOJ, 3, AF14_LTDC);		//PJ3,AF14
	SYS_GPIOx_SetAF(GPIOJ, 4, AF14_LTDC);		//PJ4,AF14
	SYS_GPIOx_SetAF(GPIOJ, 5, AF14_LTDC);		//PJ5,AF14
	SYS_GPIOx_SetAF(GPIOJ, 6, AF14_LTDC);		//PJ6,AF14
	SYS_GPIOx_SetAF(GPIOJ, 7, AF14_LTDC);		//PJ7,AF14
	SYS_GPIOx_SetAF(GPIOJ, 8, AF14_LTDC);		//PJ8,AF14
	SYS_GPIOx_SetAF(GPIOJ, 9, AF14_LTDC);		//PJ9,AF14
	SYS_GPIOx_SetAF(GPIOJ, 10, AF14_LTDC);		//PJ10,AF14
	SYS_GPIOx_SetAF(GPIOJ, 11, AF14_LTDC);		//PJ11,AF14
	SYS_GPIOx_SetAF(GPIOJ, 13, AF14_LTDC);		//PJ13,AF14
	SYS_GPIOx_SetAF(GPIOJ, 14, AF14_LTDC);		//PJ14,AF14
	SYS_GPIOx_SetAF(GPIOJ, 15, AF14_LTDC);		//PJ15,AF14
	
	SYS_GPIOx_SetAF(GPIOK, 0, AF14_LTDC);		//PK0,AF14
	SYS_GPIOx_SetAF(GPIOK, 1, AF14_LTDC);		//PK1,AF14
	SYS_GPIOx_SetAF(GPIOK, 2, AF14_LTDC);		//PK2,AF14
	SYS_GPIOx_SetAF(GPIOK, 4, AF14_LTDC);		//PK4,AF14
	SYS_GPIOx_SetAF(GPIOK, 5, AF14_LTDC);		//PK5,AF14
	SYS_GPIOx_SetAF(GPIOK, 6, AF14_LTDC);		//PK6,AF14
	SYS_GPIOx_SetAF(GPIOK, 7, AF14_LTDC);		//PK7,AF14
	
 	SYS_GPIOx_SetAF(GPIOI, 9, AF14_LTDC);		//PI9,AF14
 	SYS_GPIOx_SetAF(GPIOI, 10, AF14_LTDC);		//PI10,AF14 
	SYS_GPIOx_SetAF(GPIOI, 14, AF14_LTDC);		//PI14,AF14
 	SYS_GPIOx_SetAF(GPIOI, 15, AF14_LTDC);		//PI15,AF14 
	
	LTDC_ClockInit(DefaultLCD_Info.DCLK); 		//设置像素时钟  9Mhz 
	//设置LTDC 全局控制寄存器 (LTDC_GCR)
	temp = 0;
	temp |= (DefaultLCD_Info.HSPOL&0x01) << 31;	//水平同步极性
	temp |= (DefaultLCD_Info.VSPOL&0x01) << 30;	//垂直同步极性
	temp |= (DefaultLCD_Info.DEPOL&0x01) << 29;	//数据使能极性
	temp |= (DefaultLCD_Info.PCPOL&0x01) << 28;	//像素时钟极性
	LTDC->GCR = temp;
	//LTDC 后沿配置寄存器 (LTDC_BPCR)
	temp = (DefaultLCD_Info.Tvw + DefaultLCD_Info.Tvbp - 1) << 0;	//这些位定义累加水平后沿宽度(水平同步像素加水平后沿像素减 1)。
	temp |= (DefaultLCD_Info.Thw + DefaultLCD_Info.Thbp - 1) << 16;	//这些位定义累加垂直后沿宽度(垂直同步行加垂直后沿行减 1)。
	LTDC->BPCR=temp;	
	
	//LTDC 有效宽度配置寄存器 (LTDC_AWCR)
	temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height-1)<<0;	//累加有效高度=垂直脉宽+垂直后沿+垂直分辨率-1
	temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width-1)<<16;	//累加有效宽度=水平脉宽+水平后沿+水平分辨率-1
	LTDC->AWCR=temp;	
	//LTDC 总宽度配置寄存器 (LTDC_TWCR)
 	temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height+DefaultLCD_Info.Tvfp-1)<<0;	//总高度=垂直脉宽+垂直后沿+垂直分辨率+垂直前廊-1
	temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width+DefaultLCD_Info.Thfp-1)<<16;	//总宽度=水平脉宽+水平后沿+水平分辨率+水平前廊-1
	LTDC->TWCR=temp;				

	//背景设置
	LTDC->BCCR=0xffffff;				//设置背景层颜色寄存器(RGB888格式)
	LTDC_Enable(TRUE);					//开启LTDC
	//初始化层1
	LTDC_SetLayerConfig(0, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[0], 255);
	//初始化层2
	LTDC_SetLayerConfig(1, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[1], 255);
	LTDC_Clear(0, 0xFF000000);			//清屏层1-不透明的黑色
	LTDC_Clear(1, 0x00000000);			//清屏层2-透明的黑色
	LTDC_LayerEnable(0, TRUE);			//使能层1
	LTDC_LayerRefreshConfig();			//LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
	LCD_DispIoInit();					//初始化DISP引脚-启动显示
}

/*************************************************************************************************************************
* 函数			:	void LTDC_LayerRefreshConfig(void)
* 功能			:	LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
* 参数			:	无
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-29
* 最后修改时间 	: 	2019-10-29
* 说明			:	修改层配置后必须重新加载,否则不会生效
*************************************************************************************************************************/
void LTDC_LayerRefreshConfig(void)
{
	LTDC->SRCR|=1<<0;							//重新加载配置-必须重新加载,否则上面的层不会更新,折腾好久才发现,叫啥影子寄存器重载,也不说清楚
}

/*************************************************************************************************************************
* 函数			:	void LTDC_Enable(bool Enable)
* 功能			:	LTDC使能设置
* 参数			:	Enable:TRUE:使能;FALSE:失能
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-29
* 最后修改时间 	: 	2019-10-29
* 说明			:	
*************************************************************************************************************************/
void LTDC_Enable(bool Enable)
{
	if(Enable)
	{
		LTDC->GCR |= BIT0;					//打开LTDC
	}
	else
	{
		LTDC->GCR &= ~BIT0;					//关闭LTDC
	}
}

/*************************************************************************************************************************
* 函数			:	void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
* 功能			:	LTDC 层使能设置
* 参数			:	LayerIndex:层选择0-1;Enable:TRUE:使能;FALSE:失能
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-29
* 最后修改时间 	: 	2019-10-29
* 说明			:	
*************************************************************************************************************************/
void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
{
	if(Enable)
	{
		if(LayerIndex == 0)					//层1
		{
			LTDC_Layer1->CR |= BIT0;		//使能层1
		}
		else
		{
			LTDC_Layer2->CR |= BIT0;		//使能层2
		}
	}
	else
	{
		if(LayerIndex == 0)					//层1
		{
			LTDC_Layer1->CR &= ~BIT0;		//失能层1
		}
		else
		{
			LTDC_Layer2->CR &= ~BIT0;		//失能层2
		}
	}
}




/*************************************************************************************************************************
* 函数			:	bool LTDC_ClockInit(u16 ClockFreq)			
* 功能			:	STM32F7 LTDC时钟初始化
* 参数			:	ClockFreq:时钟频率,2-168MHZ
* 返回			:	是否设置成功
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-28
* 最后修改时间 	: 	2019-10-28
* 说明			:	输入时钟频率在系统主时钟初始化之后就会设置为1MHz,通过设置SAI PLL实现LTDC所需频率,VCO频率范围:49~432
*************************************************************************************************************************/
bool LTDC_ClockInit(u16 ClockFreq)
{
	u32 TimeOut = 0;
	u32 VCO;
	u32 PLLSAIR;		//PLLSAICFGR[30:28]
	u32 PLLSAIDIVR;		//DCKCFGR1[17:16]
	u32 temp;
	
	if(ClockFreq < 1)ClockFreq = 1;
	if(ClockFreq > 100) ClockFreq = 100;
	
	RCC->CR &= ~(1<<28);						//关闭SAI时钟 
	TimeOut = 0;
	while(RCC->CR&(1<<29))						//等待关闭成功
	{
		nop;
		TimeOut ++;
		if(TimeOut > 0xFFFF) return FALSE;		//关闭超时
	}
	//计算分频与VCO频率,通过PLLSAICFGR[30:28]可以设置2-7分频
	//通过PLLSAICFGR[17:16]可以设置00:2 01:4 10:8 11:16分频
	//通过PLLSAICFGR[14:6]可以设置为49-432MHz的VCO频率
	if(ClockFreq <= 6)
	{
		PLLSAIR = 4;	//4分频
		PLLSAIDIVR = 3;	//16分频
		VCO = ClockFreq * PLLSAIR * 16;			//VCO范围:64-384;
	}
	else if(ClockFreq <= 13)
	{
		PLLSAIR = 4;	//4分频
		PLLSAIDIVR = 2;	//8分频
		VCO = ClockFreq * PLLSAIR * 8;			//VCO范围:224-416;
	}
	else if(ClockFreq <= 26)
	{
		PLLSAIR = 2;	//2分频
		PLLSAIDIVR = 2;	//8分频
		VCO = ClockFreq * PLLSAIR * 8;			//VCO范围:224-416;
	}
	else if(ClockFreq <= 52)
	{
		PLLSAIR = 2;	//2分频
		PLLSAIDIVR = 1;	//4分频
		VCO = ClockFreq * PLLSAIR * 4;			//VCO范围:216-416;
	}
	else if(ClockFreq <= 104)
	{
		PLLSAIR = 2;	//2分频
		PLLSAIDIVR = 0;	//2分频
		VCO = ClockFreq * PLLSAIR * 2;			//VCO范围:212-416;
	}
	//设置PLLSAICFGR
	temp = RCC->PLLSAICFGR;
	temp &= ~((3<<28) | (0x1FF<<6));			//清除之前的设置
	temp |= PLLSAIR << 28;						//设置分频PLLSAICFGR[30:28]
	temp |= VCO << 6;							//设置VCO
	RCC->PLLSAICFGR = temp;
	//设置DCKCFGR1
	temp = RCC->DCKCFGR1;
	temp &= ~(3<<16);							//清除之前的设置
	temp |= PLLSAIDIVR << 16;					//设置分频DCKCFGR1[17:16]
	RCC->DCKCFGR1 = temp;
	//启动时钟
	RCC->CR |= 1<<28;							//启动SAI时钟
	TimeOut = 0;
	while((RCC->CR&(1<<29)) == 0)				//等待开启成功
	{
		nop;
		TimeOut ++;
		if(TimeOut > 0xFFFF) return FALSE;		//开启超时
	}
	
	return TRUE;
}


/*************************************************************************************************************************
* 函数			:	void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)	
* 功能			:	矩形填充(使用DMA2D)
* 参数			:	LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	采用DMA2D实现
*************************************************************************************************************************/
void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)
{
	DMA2D_FillColorToFGRAM((u32)&g_LTDC_BUFF_RGB888[LayerIndex][sy][sx], ex-sx+1, ey-sy+1, LTDC_WIDTH-(ex-sx+1),  DMA2D_COLOR_ARGB8888, color);		//DMA2D进行单色填充
	DMA2D_WaitTransferComplete(500);																												//等待DMA2D传输完成
}


/*************************************************************************************************************************
* 函数			:	void LTDC_Clear(u8 LayerIndex,u32 color)
* 功能			:	清屏(使用DMA2D)
* 参数			:	LayerIndex:层选择0-1;color:需要填充的颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	采用DMA2D实现
*************************************************************************************************************************/
void LTDC_Clear(u8 LayerIndex,u32 color)
{
	DMA2D_FillColorToFGRAM((u32)&g_LTDC_BUFF_RGB888[LayerIndex][0][0], LTDC_WIDTH, LTDC_HEIGHT, 0,  DMA2D_COLOR_ARGB8888, color);					//DMA2D进行单色填充
	SYS_DelayMS(5);
	DMA2D_WaitTransferComplete(500);																												//等待DMA2D传输完成
}


/*************************************************************************************************************************
* 函数			:	void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)
* 功能			:	矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)
* 参数			:	LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,ImageAddr:需要填充的图像地址
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	采用DMA2D实现,将源图像指定位置传输到现存,要求源图像与显存大小一致
*************************************************************************************************************************/
void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)
{
	DMA2D_FillImageToFGRAM(ImageAddr+sy*LTDC_WIDTH+sx, (u32)&g_LTDC_BUFF_RGB888[LayerIndex][sy][sx], ex-sx+1, ey-sy+1, LTDC_WIDTH-(ex-sx+1), LTDC_WIDTH-(ex-sx+1), DMA2D_COLOR_ARGB8888);//DMA2D进行矩形图形填充
	DMA2D_WaitTransferComplete(500);
}
/*************************************************************************************************************
 * 文件名		:	stm32f7_ltdc.h
 * 功能			:	STM32F7 外部RGB LCD驱动
 * 作者			:	[email protected]
 * 创建时间		:	2019-09-12
 * 最后修改时间	:	2019-09-12
 * 详细:	
*************************************************************************************************************/		
#ifndef __STM32F7_LTDC_H_
#define	__STM32F7_LTDC_H_	   
#include "system.h"
#include "DMA2D.h"

#define LTDC_WIDTH		480
#define LTDC_HEIGHT		272


extern u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH];

//像素格式定义
typedef enum
{
	LTDC_ARGB8888 	= 0,
	LTDC_RGB888 	= 1,
	LTDC_RGB565 	= 2,
	/*LTDC_ARGB1555 	= 3,
	LTDC_ARGB4444 	= 4,
	LTDC_L8 		= 5,	//8 位 Luminance
	LTDC_AL44 		= 6,	//4 位 Alpha,4 位 Luminance
	LTDC_AL88 		= 7,	//8 位 Alpha,8 位 Luminance*/
}LTDC_PixelFormat;
#define LTDC_PIXEL_FORMAT		LTDC_ARGB8888		//选择ARGB8888格式




//画点函数32bit ARGB8888格式
__inline void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color)
{
	g_LTDC_BUFF_RGB888[LayerIndex][Ypos][Xpos] = ARGB8888_Color;
}

//初始化DISP引脚
__inline void LCD_DispIoInit(void)
{
	SYS_GPIOx_Init(GPIOI, BIT12, OUT_PP, SPEED_25M);												//PI12 LCD_DISP H:正常模式;L:低功耗							
	PIout(12) = 1;																					//DISP = H  2019-10-16:一直忽略将此引脚置为高电平,调试走了很多弯路
}

void LTDC_Enable(bool Enable);																		//LTDC使能设置
void LTDC_Init(void);																				//LTDC 接口初始化
void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha);//LTDC 层窗口尺寸设置
void LTDC_LayerEnable(u8 LayerIndex, bool Enable);													//LTDC 层使能设置
void LTDC_LayerRefreshConfig(void);																	//LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)

//图形相关API
void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color);							//画点函数32bit ARGB8888格式
void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color);								//矩形填充(使用DMA2D)
void LTDC_Clear(u8 LayerIndex,u32 color);															//清屏(使用DMA2D)

void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr);//矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)

#endif //__STM32F7_LTDC_H_
发布了134 篇原创文章 · 获赞 362 · 访问量 80万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/104153079
今日推荐