DMA2D可以加快图像填充,并且支持像素格式转换。
/*************************************************************************************************************
* 文件名 : dma2d.c
* 功能 : STM32F7 DMA2D驱动
* 作者 : [email protected]
* 创建时间 : 2019-10-29
* 最后修改时间 : 2019-10-29
* 详细:
*************************************************************************************************************/
#include "dma2d.h"
#include "SYSTEM.H"
/*************************************************************************************************************************
* 函数 : void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX, DMA2D_COLOR_MODE ColorMode, u32 Color)
* 功能 : DMA2D进行单色填充
* 参数 : FGRAM_Addr:GRAM地址,通过地址控制开始的X,Y坐标;Width:填充的宽度;Height:填充的高度;OffsetX:通过偏移设置跳过的X坐标;
ColorMode:颜色模式;Color:颜色值
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-29
* 最后修改时间 : 2019-10-30
* 说明 : 用于填充矩形颜色,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX, DMA2D_COLOR_MODE ColorMode, u32 Color)
{
SYS_DeviceClockEnable(DEV_DMA2D, TRUE); //使能DMA2D时钟
DMA2D->CR = 0; //先停止DMA2D
DMA2D->IFCR |= 1<<1; //清除传输完成标志
DMA2D->CR = DMA2D_MODE_REG<<16; //寄存器到存储器模式
DMA2D->OPFCCR = ColorMode; //输出颜色格式
DMA2D->OOR = OffsetX; //输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
DMA2D->OMAR = FGRAM_Addr; //目的地址
DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0); //设置每行像素与行数
DMA2D->OCOLR = Color; //输出颜色
DMA2D_Start(); //开始传输
}
/*************************************************************************************************************************
* 函数 : void DMA2D_WaitTransferComplete(u32 TimeOutMs)
* 功能 : 等待DMA2D传输完成
* 参数 : TimeOutMs:超时时间
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 超时后会取消传输
*************************************************************************************************************************/
void DMA2D_WaitTransferComplete(u32 TimeOutMs)
{
u32 timeout = 0;
while((DMA2D->ISR & (1<<1)) == 0) //等待传输完成
{
timeout++;
SYS_DelayMS(1); //延时1ms
if(timeout > TimeOutMs)
{
DMA2D_Abort(); //终止传输
break; //超时退出
}
}
DMA2D->IFCR |= 1<<1; //清除传输完成标志
}
/*************************************************************************************************************************
* 函数 : void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode)
* 功能 : DMA2D进行矩形图形填充
* 参数 : SourceImageAddr:源图像地址(通过地址控制开始的X,Y坐标);DestGRAMAddr:目标GRAM地址(通过地址控制开始的X,Y坐标);
Width:填充的宽度;Height:填充的高度;SourceImageOffsetX:源图像X偏移(通过偏移设置跳过的X坐标);DestGRAMOffsetX:目标GRAM X偏移(通过偏移设置跳过的X坐标);
ColorMode:颜色模式
* 返回 : 是否设置成功
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-28
* 最后修改时间 : 2019-10-28
* 说明 : 用于填充图形,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode)
{
SYS_DeviceClockEnable(DEV_DMA2D, TRUE); //使能DMA2D时钟
DMA2D->CR = 0; //先停止DMA2D
DMA2D->CR = DMA2D_MODE_MEM<<16; //存储器到存储器模式
DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0); //设置每行像素与行数
DMA2D->OPFCCR = ColorMode; //输出颜色格式
DMA2D->OMAR = DestGRAMAddr; //目的地址
DMA2D->OOR = DestGRAMOffsetX; //目的GRAM图像行偏移
DMA2D->FGPFCCR = ColorMode; //源图像颜色格式
DMA2D->FGOR = SourceImageOffsetX; //输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
DMA2D->FGMAR = SourceImageAddr; //源地址
DMA2D_Start(); //开始传输
}
/*************************************************************************************************************************
* 函数 : void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode,
DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
* 功能 : DMA2D进行矩形图形填充(会执行像素格式转换)
* 参数 : SourceImageAddr:源图像地址(通过地址控制开始的X,Y坐标);DestGRAMAddr:目标GRAM地址(通过地址控制开始的X,Y坐标);
Width:填充的宽度;Height:填充的高度;SourceImageOffsetX:源图像X偏移(通过偏移设置跳过的X坐标);DestGRAMOffsetX:目标GRAM X偏移(通过偏移设置跳过的X坐标);
SourceColorMode:源图像颜色模式;DestColorMode:目标图像颜色模式
AlphaMode:alpha模式;Alpha:Alpha值;
* 返回 : 是否设置成功
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-28
* 最后修改时间 : 2019-10-28
* 说明 : 用于填充图形,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode,
DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
{
SYS_DeviceClockEnable(DEV_DMA2D, TRUE); //使能DMA2D时钟
DMA2D->CR = 0; //先停止DMA2D
DMA2D->CR = DMA2D_MODE_MEM_PFC<<16; //存储器到存储器模式-激活PFC
DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0); //设置每行像素与行数
DMA2D->OPFCCR = DestColorMode; //输出颜色格式
DMA2D->OMAR = DestGRAMAddr; //目的地址
DMA2D->OOR = DestGRAMOffsetX; //目的GRAM图像行偏移
DMA2D->FGPFCCR =((u32)Alpha << 24) | ((u32)AlphaMode << 16) | SourceColorMode; //源图像颜色格式
DMA2D->FGOR = SourceImageOffsetX; //输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
DMA2D->FGMAR = SourceImageAddr; //源地址
DMA2D_Start(); //开始传输
}
/*************************************************************************************************************
* 文件名 : dma2d.H
* 功能 : STM32F7 DMA2D驱动
* 作者 : [email protected]
* 创建时间 : 2019-10-29
* 最后修改时间 : 2019-10-29
* 详细:
*************************************************************************************************************/
#ifndef __DMA2D_H_
#define __DMA2D_H_
#include "system.h"
typedef enum
{
DMA2D_MODE_MEM = 0, //存储器到存储器(仅限 FG前景色 获取)
DMA2D_MODE_MEM_PFC = 1, //存储器到存储器并执行 PFC(仅限 FG PFC 激活时的 FG 获取)
DMA2D_MODE_MEM_MIXED= 2, //存储器到存储器并执行混合(执行 PFC 和混合时的 FG 和 BG 获取)
DMA2D_MODE_REG = 3, //寄存器到存储器(无 FG 和 BG,仅输出阶段激活)
}DMA2D_MODE;
//颜色模式
typedef enum
{
DMA2D_COLOR_ARGB8888 = 0,
DMA2D_COLOR_RGB888 = 1,
DMA2D_COLOR_RGB565 = 2,
/*DMA2D_COLOR_ARGB1555 = 3,
DMA2D_COLOR_ARGB4444 = 4,
DMA2D_COLOR_L8 = 5, //8 位 Luminance
DMA2D_COLOR_AL44 = 6, //4 位 Alpha,4 位 Luminance
DMA2D_COLOR_AL88 = 7, //8 位 Alpha,8 位 Luminance
DMA2D_COLOR_L4 = 8, //4 位 Luminance
DMA2D_COLOR_A8 = 9, //8 位 Alpha
DMA2D_COLOR_A4 = 10, //4 位 Alpha*/
}DMA2D_COLOR_MODE;
//Alpha 模式
typedef enum
{
DMA2D_ALPHA_NULL = 0,//不修改前景层图像的 alpha 通道值
DMA2D_ALPHA_REPLACE = 1,//原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0]
DMA2D_ALPHA_PRODUCT = 2,//原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0] 与原始 alpha 通道值的乘积
}DMA2D_ALPHA_MODE;
__inline void DMA2D_Abort(void) {DMA2D->CR |= BIT2;} //终止传输
__inline void DMA2D_Suspend(void) {DMA2D->CR |= BIT1;} //挂起传输
__inline void DMA2D_Start(void) {DMA2D->CR |= BIT0;} //开始传输
void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX, DMA2D_COLOR_MODE ColorMode, u32 Color); //DMA2D进行单色填充
void DMA2D_WaitTransferComplete(u32 TimeOutMs); //等待DMA2D传输完成
void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode);//DMA2D进行矩形图形填充
void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode,
DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha);//DMA2D进行矩形图形填充(会执行像素格式转换)
#endif //__DMA2D_H_
/*************************************************************************************************************
* 文件名 : DMA2D_GRAM.c
* 功能 : GRAM相关操作
* 作者 : [email protected]
* 创建时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 详细: 显存相关操作接口
*************************************************************************************************************/
#include "dma2d.h"
#include "DMA2D_GRAM.h"
#include "SYSTEM.H"
//基本接口
void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color); //32bit色彩GRAM显存画点
void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color); //24bit色彩GRAM显存画点
void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color); //16bit色彩GRAM显存画点
//GRAM相关接口-16bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_16bit =
{
(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_16bit, //GRAM显存画点(RGB565格式)
(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill, //GRAM矩形填充
(void(*)(void *,u32))GRAM_Clear, //GRAM清屏(使用DMA)
};
//GRAM相关接口-24bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_24bit =
{
(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_24bit, //GRAM显存画点(RGB888格式)
(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill, //GRAM矩形填充
(void(*)(void *,u32))GRAM_Clear, //GRAM清屏(使用DMA)
};
//GRAM相关接口-32bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_32bit =
{
(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_32bit, //GRAM显存画点(ARGB8888格式)
(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill, //GRAM矩形填充
(void(*)(void *,u32))GRAM_Clear, //GRAM清屏(使用DMA)
};
/*************************************************************************************************************************
* 函数 : void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
* 功能 : GRAM句柄初始化(不会申请内存)
* 参数 : pHandle:GRAM句柄;GRAM_Addr:GRAM内存;Width:显存宽度;Height:显存高度;ColorMode:颜色模式
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 初始化显存
*************************************************************************************************************************/
void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
{
while(pHandle == NULL)
{
DEBUG("无效的句柄pHandle\r\n");
SYS_DelayMS(500);
}
pHandle->GRAM_Addr = GRAM_Addr; //GRAM地址
pHandle->Width = Width; //GRAM宽度
pHandle->Height = Height; //GRAM高度
pHandle->pGRAM_32bit = (u32*)GRAM_Addr; //32bit颜色模式下显存指针
pHandle->pGRAM_24bit = (u8*)GRAM_Addr; //24bit颜色模式下显存指针
pHandle->pGRAM_16bit = (u16*)GRAM_Addr; //16bit颜色模式下显存指针
//像素模式
switch(ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_32bit;
}break;
case DMA2D_COLOR_RGB888 :
{
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_24bit;
}break;
default: //DMA2D_COLOR_RGB565
{
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_16bit;
ColorMode = DMA2D_COLOR_RGB565;
}break;
}
pHandle->ColorMode = ColorMode; //GRAM显存像素格式
pHandle->InitStatusId = DMA_INIT_OK; //初始化成功
}
/*************************************************************************************************************************
* 函数 : void GRAM_Init(GRAM_HANDLE *pHandle, u16 Width,u16 Height,DMA2D_COLOR_MODE ColorMode)
* 功能 : 创建一个GRAM(会申请内存)
* 参数 : Width:显存宽度;Height:显存高度;ColorMode:颜色模式
* 返回 : NULL:失败;其他:GRAM句柄
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2020-02-02
* 最后修改时间 : 2020-02-02
* 说明 : 初始化显存
*************************************************************************************************************************/
GRAM_HANDLE *GRAM_Create( u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
{
GRAM_HANDLE *pHandle = NULL;
u32 GRAM_Addr;
pHandle = (GRAM_HANDLE *)GRAM_malloc(sizeof(GRAM_HANDLE)); //为句柄申请内存
while(pHandle == NULL)
{
DEBUG("无效的句柄pHandle\r\n");
SYS_DelayMS(500);
}
switch(ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
GRAM_Addr = (u32)GRAM_malloc(sizeof(u32) * Width * Height);//为显存分配内存
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_32bit;
}break;
case DMA2D_COLOR_RGB888 :
{
GRAM_Addr = (u32)GRAM_malloc(3 * Width * Height); //为显存分配内存
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_24bit;
}break;
default: //DMA2D_COLOR_RGB565
{
GRAM_Addr = (u32)GRAM_malloc(sizeof(u16) * Width * Height); //为显存分配内存
pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_16bit;
ColorMode = DMA2D_COLOR_RGB565;
}break;
}
while(GRAM_Addr == NULL)
{
DEBUG("显存申请内存失败\r\n");
SYS_DelayMS(500);
}
pHandle->GRAM_Addr = GRAM_Addr; //GRAM地址
pHandle->ColorMode = ColorMode; //GRAM显存像素格式
pHandle->Width = Width; //GRAM宽度
pHandle->Height = Height; //GRAM高度
pHandle->pGRAM_32bit = (u32*)GRAM_Addr; //32bit颜色模式下显存指针
pHandle->pGRAM_24bit = (u8*)GRAM_Addr; //24bit颜色模式下显存指针
pHandle->pGRAM_16bit = (u16*)GRAM_Addr; //16bit颜色模式下显存指针
pHandle->InitStatusId = DMA_CREATE_OK; //创建成功
return pHandle;
}
/*************************************************************************************************************************
* 函数 : void GRAM_Delete(GRAM_HANDLE *pHandle)
* 功能 : 删除一个GRAM(会释放内存)
* 参数 : pHandle:GRAM句柄
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-12-16
* 最后修改时间 : 2019-12-16
* 说明 : 用于删除显存,释放内存
*************************************************************************************************************************/
void GRAM_Delete(GRAM_HANDLE *pHandle)
{
if(pHandle!=NULL && pHandle->InitStatusId == DMA_CREATE_OK)
{
if(pHandle->GRAM_Addr != NULL)
{
GRAM_free((u8 *)pHandle->GRAM_Addr); //释放显存内存
pHandle->GRAM_Addr = NULL;
}
pHandle->InitStatusId = 0;
GRAM_free(pHandle); //释放句柄内存
pHandle = NULL;
}
}
/*************************************************************************************************************************
* 函数 : void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能 : 32bit色彩GRAM显存画点
* 参数 : pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
pHandle->pGRAM_32bit[(u32)Ypos * pHandle->Width + Xpos] = Color;
}
/*************************************************************************************************************************
* 函数 : void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能 : 24bit色彩GRAM显存画点
* 参数 : pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
memcpy(&pHandle->pGRAM_24bit[((u32)Ypos * pHandle->Width + Xpos)*3], &Color, 3);
}
/*************************************************************************************************************************
* 函数 : void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能 : 16bit色彩GRAM显存画点
* 参数 : pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
pHandle->pGRAM_16bit[(u32)Ypos * pHandle->Width + Xpos] = Color;
}
/*************************************************************************************************************************
* 函数 : void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color)
* 功能 : GRAM矩形填充(使用DMA2D)
* 参数 : pHandle:GRAM句柄;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 采用DMA2D实现
*************************************************************************************************************************/
void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color)
{
switch(pHandle->ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_32bit[(u32)sy * pHandle->Width + sx], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_ARGB8888, color); //DMA2D进行单色填充
}break;
case DMA2D_COLOR_RGB888 :
{
DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_24bit[((u32)sy * pHandle->Width + sx)*3], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_RGB888, color); //DMA2D进行单色填充
}break;
case DMA2D_COLOR_RGB565 :
{
DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_16bit[(u32)sy * pHandle->Width + sx], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_RGB565, color); //DMA2D进行单色填充
}break;
default:return;
}
DMA2D_WaitTransferComplete(500); //等待DMA2D传输完成
}
/*************************************************************************************************************************
* 函数 : void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color)
* 功能 : GRAM清屏(使用DMA2D)
* 参数 : pHandle:GRAM句柄;color:需要填充的颜色
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 说明 : 采用DMA2D实现
*************************************************************************************************************************/
void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color)
{
switch(pHandle->ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_ARGB8888, color); //DMA2D进行单色填充
}break;
case DMA2D_COLOR_RGB888 :
{
DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_RGB888, color); //DMA2D进行单色填充
}break;
case DMA2D_COLOR_RGB565 :
{
DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_RGB565, color); //DMA2D进行单色填充
}break;
default:return;
}
SYS_DelayMS(5);
DMA2D_WaitTransferComplete(500); //等待DMA2D传输完成
}
/*************************************************************************************************************************
* 函数 : void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width,
u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
* 功能 : GRAM局部拷贝(支持Alpha)
* 参数 : pDestHandle:目标GRAM句柄;DestSx,DestSy:目标开始坐标;
pSourceHandle:源GRAM句柄;SourceSx,SourceSy:源开始坐标;Width:宽度;Height:宽度
AlphaMode:alpha模式;Alpha:Alpha值;
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2020-02-02
* 最后修改时间 : 2020-02-02
* 说明 : 不会检查GRAM大小,请确保GRAM
*************************************************************************************************************************/
void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
{
u32 SourceImageAddr; //源图像地址(通过地址控制开始的X,Y坐标)
u32 DestGRAMAddr; //目标GRAM地址(通过地址控制开始的X,Y坐标);
u32 PixelByteSize; //像素字节大小
if(pDestHandle == NULL || pDestHandle->GRAM_Addr == NULL)
{
DEBUG("无效的句柄,pDestHandle\r\n");
return;
}
if(pSourceHandle == NULL || pSourceHandle->GRAM_Addr == NULL)
{
DEBUG("无效的句柄,pSourceHandle\r\n");
return;
}
//源图像地址(通过地址控制开始的X,Y坐标) 计算
switch(pSourceHandle->ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
PixelByteSize = 4;
}break;
case DMA2D_COLOR_RGB888 :
{
PixelByteSize = 3;
}break;
default: //DMA2D_COLOR_RGB565
{
PixelByteSize = 2;
}break;
}
SourceImageAddr = pSourceHandle->GRAM_Addr + (SourceSy * pSourceHandle->Width + SourceSx)*PixelByteSize; //计算源开始地址
//目标图像地址(通过地址控制开始的X,Y坐标) 计算
switch(pDestHandle->ColorMode)
{
case DMA2D_COLOR_ARGB8888 :
{
PixelByteSize = 4;
}break;
case DMA2D_COLOR_RGB888 :
{
PixelByteSize = 3;
}break;
default: //DMA2D_COLOR_RGB565
{
PixelByteSize = 2;
}break;
}
DestGRAMAddr = pDestHandle->GRAM_Addr + (DestSy * pDestHandle->Width + DestSx)*PixelByteSize; //计算目标开始地址
//进行拷贝
DMA2D_FillImageToFGRAM_PFC(SourceImageAddr, DestGRAMAddr, Width, Height,pSourceHandle->Width-Width, pDestHandle->Width-Width, pSourceHandle->ColorMode,
pDestHandle->ColorMode, AlphaMode, Alpha); //DMA2D进行矩形图形填充(会执行像素格式转换)
DMA2D_WaitTransferComplete(200); //等待DMA2D传输完成
}
/*************************************************************************************************************************
* 函数 : void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width,
u16 Height)
* 功能 : GRAM局部拷贝(不支持Alpha)
* 参数 : pDestHandle:目标GRAM句柄;DestSx,DestSy:目标开始坐标;
pSourceHandle:源GRAM句柄;SourceSx,SourceSy:源开始坐标;Width:宽度;Height:宽度
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : [email protected]
* 时间 : 2020-02-02
* 最后修改时间 : 2020-02-02
* 说明 : 不会检查GRAM大小,请确保GRAM
*************************************************************************************************************************/
void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, u16 Height)
{
GRAM_LocalCopyAlpha(pDestHandle, DestSx, DestSy, pSourceHandle, SourceSx, SourceSy, Width, Height, DMA2D_ALPHA_NULL, 255);
}
/*************************************************************************************************************
* 文件名 : DMA2D_GRAM.h
* 功能 : GRAM相关操作
* 作者 : [email protected]
* 创建时间 : 2019-10-30
* 最后修改时间 : 2019-10-30
* 详细: 显存相关操作接口
*************************************************************************************************************/
#ifndef __DMA2D_GRAM_H_
#define __DMA2D_GRAM_H_
#include "system.h"
#include "DMA2D.h"
#include "SYSMalloc.h"
//初始化状态id
#define DMA_INIT_OK 0x1234423 //初始化成功(不可以释放)
#define DMA_CREATE_OK 0x3643423 //创建成功(可以释放)
//颜色模式
typedef DMA2D_COLOR_MODE GRAM_COLOR_MODE;
//基本GDI接口(由于两个结构体不能相互包含,此处将GRAM_HANDLE*使用void*替换,可能会出现变异警告)
typedef struct
{
void (*pDrawPoint)(void *pHandle, u16 Xpos,u16 Ypos,u32 Color); //绘点函数
void (*pFill)(void *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color); //填充
void (*pClear)(void *pHandle, u32 color); //清屏
}GDI_BasicInterface;
//GRAM相关接口-16bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_16bit;
//GRAM相关接口-24bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_24bit;
//GRAM相关接口-32bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_32bit;
//所需的内存申请接口
__inline void *GRAM_malloc(u32 size)
{
return mymalloc(SRAMEX, size); //内存分配(外部调用)-使用外部SRAM
}
//所需的内存释放接口
__inline void GRAM_free(void *ptr)
{
myfree(SRAMEX, ptr); //使用外部SRAM
}
//显存句柄
typedef struct
{
u32 InitStatusId; //初始化状态id
u32 GRAM_Addr; //GRAM地址
DMA2D_COLOR_MODE ColorMode; //GRAM显存像素格式
u16 Width; //GRAM宽度
u16 Height; //GRAM高度
u32 *pGRAM_32bit; //32bit颜色模式下显存指针
u8 *pGRAM_24bit; //24bit颜色模式下显存指针
u16 *pGRAM_16bit; //16bit颜色模式下显存指针
const GDI_BasicInterface *pBasicInterface; //底层GDI接口
}GRAM_HANDLE;
void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode); //GRAM句柄初始化(不会申请内存)
void GRAM_Delete(GRAM_HANDLE *pHandle); //删除一个GRAM(会释放内存)
void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color); //GRAM矩形填充(使用DMA2D)
void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color); //GRAM清屏(使用DMA2D)
GRAM_HANDLE *GRAM_Create( u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode); //创建一个GRAM(会申请内存)
void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle,
u16 SourceSx, u16 SourceSy, u16 Width, u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha); //GRAM局部拷贝(支持Alpha)
void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle,
u16 SourceSx, u16 SourceSy, u16 Width, u16 Height); //GRAM局部拷贝(不支持Alpha)
#endif //__DMA2D_GRAM_H_
/*************************************************************************************************************
* 文件名 : GDI.c
* 功能 : 图形设备接口(Graphics Device Interface)
* 作者 : [email protected]
* 创建时间 : 2019-11-02
* 最后修改时间 : 2020-02-02
* 详细 : STM32F7 图形设备接口
*************************************************************************************************************/
#include "system.h"
#include "DMA2D.h"
#include "stm32f7_ltdc.h"
#include "DMA2D_GRAM.h"
#include "GDI.h"
//显示器Layer1 GRAM定义
const GRAM_HANDLE cg_LTDC_Layer1_GRAM_Handle =
{
DMA_INIT_OK,
(u32) &g_LTDC_BUFF_RGB888[0], //GRAM地址
DMA2D_COLOR_ARGB8888, //GRAM显存像素格式
LTDC_WIDTH, //GRAM宽度
LTDC_HEIGHT, //GRAM高度
(u32 *)&g_LTDC_BUFF_RGB888[0], //32bit颜色模式下显存指针
(u8 *)&g_LTDC_BUFF_RGB888[0], //24bit颜色模式下显存指针
(u16 *)&g_LTDC_BUFF_RGB888[0], //16bit颜色模式下显存指针
&cg_GDI_GRAM_Interface_32bit,
};
//显示器Layer2 GRAM定义
const GRAM_HANDLE cg_LTDC_Layer2_GRAM_Handle =
{
DMA_INIT_OK,
(u32) &g_LTDC_BUFF_RGB888[1], //GRAM地址
DMA2D_COLOR_ARGB8888, //GRAM显存像素格式
LTDC_WIDTH, //GRAM宽度
LTDC_HEIGHT, //GRAM高度
(u32 *)&g_LTDC_BUFF_RGB888[1], //32bit颜色模式下显存指针
(u8 *)&g_LTDC_BUFF_RGB888[1], //24bit颜色模式下显存指针
(u16 *)&g_LTDC_BUFF_RGB888[1], //16bit颜色模式下显存指针
&cg_GDI_GRAM_Interface_32bit,
};
/*************************************************************************************************************************
* 函数 : void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color)
* 功能 : 绘制空心圆
* 参数 : pHandle:GRAM句柄;Xpos,Ypos:圆心坐标;Radius:半径;Color:颜色
* 返回 : 无
* 依赖 : 画点函数
* 作者 : [email protected]
* 时间 : 2011-09-20
* 最后修改时间 : 2019-11-02
* 说明 : 无
*************************************************************************************************************************/
void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color)
{
int a = 0,b = Radius;
int di;
di = 3 -(Radius << 1); //判断下个点位置的标志
#if(GDI_PARAMETER_CHECK) //参数检查
while(pHandle==NULL)
{
DEBUG("无效的句柄 pHandle\r\n");
SYS_DelayMS(1000);
}
#endif //GDI_PARAMETER_CHECK
while(a <= b)
{
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos - a,Color); //3
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + b,Ypos - a,Color); //0
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - a,Ypos + b,Color); //1
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos - a,Color); //7
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - a,Ypos - b,Color); //2
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + b,Ypos + a,Color); //4
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + a,Ypos - b,Color); //5
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + a,Ypos + b,Color); //6
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos + a,Color);
a ++;
//使用Bresenham算法画圆
if(di<0)
di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b --;
}
}
}
/*************************************************************************************************************************
* 函数 : void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
* 功能 : 绘制直线(可以倾斜)
* 参数 : pHandle:GRAM句柄;sx,sy:开始坐标;ex,ey:结束坐标;Color:颜色
* 返回 : 无
* 依赖 : 画点函数
* 作者 : [email protected]
* 时间 : 2011-09-20
* 最后修改时间 : 2019-11-02
* 说明 : 无
*************************************************************************************************************************/
void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
#if(GDI_PARAMETER_CHECK) //参数检查
while(pHandle==NULL)
{
DEBUG("无效的句柄 pHandle\r\n");
SYS_DelayMS(1000);
}
#endif //GDI_PARAMETER_CHECK
delta_x=ex-sx; //计算坐标增量
delta_y=ey-sy;
uRow=sx;
uCol=sy;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
pHandle->pBasicInterface->pDrawPoint(pHandle, uRow, uCol,Color);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
/*************************************************************************************************************************
* 函数 : void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
* 功能 : 在指定位置画一个矩形
* 参数 : pHandle:GRAM句柄;sx,sy:左上角坐标;ex,ey:右下角坐标;Color:颜色
* 返回 : 无
* 依赖 : 画线函数
* 作者 : [email protected]
* 时间 : 2011-09-20
* 最后修改时间 : 2019-11-02
* 说明 : 无
*************************************************************************************************************************/
void GDI_DrawRectangle(GRAM_HANDLE *pHandle, u16 sx, u16 sy, u16 ex, u16 ey,u16 Color)
{
#if(GDI_PARAMETER_CHECK) //参数检查
while(pHandle==NULL)
{
DEBUG("无效的句柄 pHandle\r\n");
SYS_DelayMS(1000);
}
#endif //GDI_PARAMETER_CHECK
GDI_DrawLine(pHandle, sx, sy, ex, sy, Color);
GDI_DrawLine(pHandle, sx, sy, sx, ey, Color);
GDI_DrawLine(pHandle, sx, ey, ex, ey, Color);
GDI_DrawLine(pHandle, ex, sy, ex, ey, Color);
}
/*************************************************************************************************************************
* 函数 : void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能 : 画一个2*2的大点
* 参数 : pHandle:GRAM句柄;Xpos,Ypos:坐标;Color:颜色
* 返回 : 无
* 依赖 : 画点函数
* 作者 : [email protected]
* 时间 : 2011-09-20
* 最后修改时间 : 2019-11-02
* 说明 : 无
*************************************************************************************************************************/
void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
#if(GDI_PARAMETER_CHECK) //参数检查
while(pHandle==NULL)
{
DEBUG("无效的句柄 pHandle\r\n");
SYS_DelayMS(1000);
}
#endif //GDI_PARAMETER_CHECK
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos, Color); //中心点
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos+1, Ypos, Color);
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos+1, Color);
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos+1, Ypos+1, Color);
}
/*************************************************************************************************************
* 文件名 : GDI.h
* 功能 : 图形设备接口(Graphics Device Interface)
* 作者 : [email protected]
* 创建时间 : 2019-11-02
* 最后修改时间 : 2020-02-02
* 详细 : STM32F7 图形设备接口
*************************************************************************************************************/
#ifndef _GDI_H_
#define _GDI_H_
#include "system.h"
#include "DMA2D_GRAM.h"
#define GDI_PARAMETER_CHECK 1 //参数检查-主要检查指针
#define GDI_DEBUG 1 //调试输出
#if GDI_DEBUG
#define GDI_debug(format,...) uart_printf(format,##__VA_ARGS__)
#else
#define GDI_debug(format,...) /\
/
#endif //GDI_DEBUG
extern const GRAM_HANDLE cg_LTDC_Layer1_GRAM_Handle; //显示器Layer1 GRAM定义
extern const GRAM_HANDLE cg_LTDC_Layer2_GRAM_Handle; //显示器Layer2 GRAM定义
#define LTDC_Layer1_GRAM_HANDLE ((GRAM_HANDLE*) &cg_LTDC_Layer1_GRAM_Handle) //显示器GRAM 1
#define LTDC_Layer2_GRAM_HANDLE ((GRAM_HANDLE*) &cg_LTDC_Layer2_GRAM_Handle) //显示器GRAM 2
//GDI相关API
__inline void GDI_DrawPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos, Color); //画点
}
void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color); //绘制空心圆
void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color); //绘制直线(可以倾斜)
void GDI_DrawRectangle(GRAM_HANDLE *pHandle, u16 sx, u16 sy, u16 ex, u16 ey,u16 Color); //在指定位置画一个矩形
void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color); //画一个2*2的大点
#endif /*_GDI_H_*/
测试代码,使用的FATFS,读取一个事先准备的图片bin文件,RGB565格式。
FIL *pFile;
FILE_ERROR mError;
GRAM_HANDLE *pGramHandle;
pGramHandle = GRAM_Create(320, 240, DMA2D_COLOR_RGB565); //创建一个GRAM(会申请内存),分辨率320*240,像素格式RGB565
if(pGramHandle != NULL)
{
GRAM_Clear(pGramHandle, 0xff00); //清除显存,防止读取失败了还是现实上一次的图片
uart_printf("[OK]GRAM初始化成功\r\n");
pFile = FILE_Open("0:\\16bit.bin", &mError, FA_READ);
if(pFile != NULL)
{
uart_printf("[OK]打开文件成功\r\n");
if(FILE_Read(pFile, (u8 *)(pGramHandle->GRAM_Addr), U32_MAX, &mError) == TRUE)//读取文件,将一个事先准备的RGB565的bin图片加载到显存中
{
uart_printf("[OK]读取文件成功\r\n");
}
else
{
uart_printf("读取文件错误:%d\r\n", mError);
}
}
else
{
uart_printf("打开文件错误:%d\r\n", mError);
}
//将显存拷贝到屏幕中
GRAM_LocalCopy(LTDC_Layer1_GRAM_HANDLE,(480-320)/2-1, (272-240)/2-1, pGramHandle, 0, 0, 320, 240); //GRAM局部拷贝
}
效果图