LTDC会一直从显存中搬运数据并刷新数据到液晶屏, 所以我们只需要往显存写数据就可以了
1 什么是DMA2D
下面资料来自安富莱BSP手册
2 DMA2D工作模式
1 模式 1:寄存器到存储器模式
这个模式主要用于清屏,也即是将显示屏清为单色效果
2 模式 2:存储器到存储器模式
这个模式用于从一个存储器复制一块数据到另一个存储器,比如将摄像头 OV7670 的输出图像复制到
LCD 显存就可以采用这种方式。
3 模式 3:存储器到存储器模式,带颜色格式转换
这个模式比模式 2 多了一个颜色格式转换,比如我们要显示一幅 RGB888 颜色格式的位图到 RGB565
颜色格式的显示屏,就需要用到这个模式,只需输入端配置为 RGB888,输出端配置 RGB565 即可。
位图颜色格式转换后会显示到显示屏上。
4 模式 4:存储器到存储器模式,带颜色格式转换和混合
这个模式比模式 3 多了一个混合操作,通过混合,可以将两种效果进行混合显示。
5 模式 5:存储器到存储器模式,带颜色格式转换和混合,前景色是固定的
同模式 4,只是前景色的颜色值是固定的。
1 寄存器到存储器
这个模式主要用于清屏,也即是将显示屏清为单色效果
此函数主要用于 LCD 的颜色填充。
第 23 行,设置 DMA2D 采用寄存器往存储器传输数据模式,即 DMA2D 将 OCOLR 寄存器设置颜色
值填充到存储器里面。
第 24 行,OCOLR 寄存器用于设置输出颜色值,特别注意要跟第 27 行的输出颜色格式匹配。比如设
置的是 RGB565,那么设置的颜色值就要是 16 位色的。
第 25 行,设置输出填充区的首地址。
第 26 行,设置输出行偏移。
第 27 行,设置输出颜色格式,如果是输出到 LCD 显存,那么此格式要与 LCD 颜色格式一致,否则
显示不正常。
第 28 行,高 16 位用于设置每行的像素数,低 16 位用于设置行数,合并起来决定总传输次数。
第 31-34 行,启动传输,并等待传输完成。
具体应用:
1 正点原子
//LTDC填充矩形,DMA2D填充
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
//color:要填充的颜色
//有时候需要频繁的调用填充函数,所以为了速度,填充函数采用寄存器版本,
//不过下面有对应的库函数版本的代码。
void LTDC_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint32_t color)
{
uint32_t psx,psy,pex,pey; //以LCD面板为基准的坐标系,不随横竖屏变化而变化
uint32_t timeout=0;
uint16_t offline;
uint32_t addr;
//坐标系转换
if(PIXELS_DIR) //横屏
{
psx=sx;
psy=sy;
pex=ex;
pey=ey;
} else //竖屏
{
psx=sy;
psy=PIXELS_H-ex-1;
pex=ey;
pey=PIXELS_H-sx-1;
}
offline=PIXELS_W-(pex-psx+1);
addr=(LCD_FRAME_BUF_ADDR+PIXELS_BYTE*(PIXELS_W*psy+psx));
__HAL_RCC_DMA2D_CLK_ENABLE(); //使能DM2D时钟
//DMA2D->CR&=~(DMA2D_CR_START); //先停止DMA2D
DMA2D->CR=DMA2D_R2M; //寄存器到存储器模式
// 设置 DMA2D 采用寄存器往存储器传输数据模式,即 DMA2D 将 OCOLR 寄存器设置颜色值填充到存储器里面。
DMA2D->OPFCCR=LTDC_PIXEL_FORMAT_RGB565; //设置颜色格式
DMA2D->OOR=offline; //设置行偏移
DMA2D->OMAR=addr; //输出存储器地址
DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16); //设定行数寄存器
DMA2D->OCOLR=color; //设定输出颜色寄存器
DMA2D->CR|=DMA2D_CR_START; //启动DMA2D
while((DMA2D->ISR&(DMA2D_FLAG_TC))==0) //等待传输完成
{
}
DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志
}
2 安富莱
/*
*********************************************************************************************************
* 函 数 名: _DMA2D_Fill
* 功能说明: DMA2D颜色填充功能
* 形 参: pDst 颜色数据目的地址
* xSize 色块X轴大小,即每行像素数
* ySize 色块Y轴大小,即行数
* OffLine 前景层图像的行偏移
* ColorIndex 色块颜色值
* PixelFormat 目标区颜色格式
* 返 回 值: 无
*********************************************************************************************************
*/
static void _DMA2D_Fill(void * pDst,
uint32_t xSize,
uint32_t ySize,
uint32_t OffLine,
uint32_t ColorIndex,
uint32_t PixelFormat)
{
/* DMA2D采用寄存器到存储器模式, 这种模式用不到前景层和背景层 */
DMA2D->CR = 0x00030000UL | (1 << 9);
DMA2D->OCOLR = ColorIndex;
DMA2D->OMAR = (uint32_t)pDst;
DMA2D->OOR = OffLine;
DMA2D->OPFCCR = PixelFormat;
DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize;
/* 启动传输 */
DMA2D->CR |= DMA2D_CR_START;
/* 等待DMA2D传输完成 */
while (DMA2D->CR & DMA2D_CR_START) {}
}
2 存储器到存储器模式
此函数用于从前景层复制指定区域的颜色数据到目标区域。
第 25 行,设置 DMA2D 采用存储器往存储器传输数据模式,输入存储器只能是前景层。即 DMA2D
将 FGMAR 寄存器所指向的存储数据传输到寄存器 OMAR 所指向的存储器。
第 26 行,设置前景层数据首地址。
第 27 行,设置输出存储器首地址。
第 28 行,设置前景层行偏移。
第 29 行,设置输出区行偏移。
第 32-33 行,设置前景层和输出区域都采用 RGB565 颜色格式。另外注意,如果是输出到 LCD 显存,
那么输出颜色格式要与 LCD 颜色格式一致,否则显示不正常。
第 35 行,高 16 位用于设置每行的像素数,低 16 位用于设置行数,合并起来决定总传输次数。
第 38-41 行,启动传输,并等待传输完成。
注意事项:
1. 使用此函数前务必要调用函数__HAL_RCC_DMA2D_CLK_ENABLE 使能 DMA2D 时钟。
1 正点原子
//矩形彩色填充函数
void LTDC_Color_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t *color)
{
uint32_t psx,psy,pex,pey; //以LCD面板为基准的坐标系,不随横竖屏变化而变化
uint32_t timeout=0;
uint16_t offline;
uint32_t addr;
//坐标系转换
if(PIXELS_DIR) //横屏
{
psx=sx;
psy=sy;
pex=ex;
pey=ey;
} else //竖屏
{
psx=sy;
psy=PIXELS_H-ex-1;
pex=ey;
pey=PIXELS_H-sx-1;
}
offline=PIXELS_W-(pex-psx+1);
addr=(LCD_FRAME_BUF_ADDR+PIXELS_BYTE*(PIXELS_W*psy+psx));
__HAL_RCC_DMA2D_CLK_ENABLE(); //使能DM2D时钟
//DMA2D->CR&=~(DMA2D_CR_START); //先停止DMA2D
DMA2D->CR=DMA2D_M2M; //存储器到存储器模式
DMA2D->FGMAR=(uint32_t)color; //源地址
DMA2D->OMAR=addr; //输出存储器地址
DMA2D->FGOR=0; //前景层行偏移为0
DMA2D->OOR=offline; //设置行偏移
DMA2D->FGPFCCR=0X02; //设置颜色格式
DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16); //设定行数寄存器
DMA2D->CR|=DMA2D_CR_START; //启动DMA2D
while((DMA2D->ISR&(DMA2D_FLAG_TC))==0) //等待传输完成
{
}
DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志
}
2 安富莱
将大小 128*128,颜色格式为 RGB565 的位图绘制到 LCD 起始坐标为(328, 20)的区域,输出颜色格
式也配置为 RGB565。
1. _DMA2D_Copy((uint32_t *)_acmickey, /* 位图地址 */
2. (uint32_t *)(SDRAM_LCD_BUF1 + g_LcdWidth*20*2 + 328*2), /* 显示起始地址(328, 20) */
3. 128, /* 位图长 */
4. 128, /* 位图高 */
5. 0, /* 位图行偏移 */
6. g_LcdWidth-128, /* 目标区行偏移 */
7. LTDC_PIXEL_FORMAT_RGB565); /* 目标区颜色格式 */
第 1 行是位图首地址。
第 2 行,根据设置的起始坐标,计算起始坐标在 LCD 显存中的具体位置。
SDRAM_LCD_BUF1 表示 LCD 显存首地址。
g_LcdWidth*20*2 计算的是行数占用的字节数。
328*2 计算的是所在行的具体地址。
乘以 2 是因为 RGB565 颜色格式的 1 个像素占用两个字节。
第 5 行是位图的行偏移,行偏移的意思就是一行结束到下一行开始的距离,单位像素个数。由于整个
位图都要绘制,所有行偏移就是 0。
第 6 行,输出行偏移的,由于输出区需要的长度是 128,那么行偏移就是 LCD 的长度减去 128。
/*
*********************************************************************************************************
* 函 数 名: _DMA2D_Copy
* 功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
* 形 参: pSrc 颜色数据源地址
* pDst 颜色数据目的地址
* xSize 目的区域的X轴大小,即每行像素数
* ySize 目的区域的Y轴大小,即行数
* OffLineSrc 前景层图像的行偏移
* OffLineDst 输出的行偏移
* PixelFormat 目标区颜色格式
* 返 回 值: 无
*********************************************************************************************************
*/
static void _DMA2D_Copy(void * pSrc,
void * pDst,
uint32_t xSize,
uint32_t ySize,
uint32_t OffLineSrc,
uint32_t OffLineDst,
uint32_t PixelFormat)
{
/* DMA2D采用存储器到存储器模式, 这种模式是前景层作为DMA2D输入 */
DMA2D->CR = 0x00000000UL | (1 << 9);
DMA2D->FGMAR = (uint32_t)pSrc;
DMA2D->OMAR = (uint32_t)pDst;
DMA2D->FGOR = OffLineSrc;
DMA2D->OOR = OffLineDst;
/* 前景层和输出区域都采用的RGB565颜色格式 */
DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
DMA2D->OPFCCR = LTDC_PIXEL_FORMAT_RGB565;
DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize;
/* 启动传输 */
DMA2D->CR |= DMA2D_CR_START;
/* 等待DMA2D传输完成 */
while (DMA2D->CR & DMA2D_CR_START) {}
}
3 模式 3:存储器到存储器模式,带颜色格式转换
此函数用于前景层和目标区域的颜色混合,并将混合后的图像输出到目标区域。
第 24 行,DMA2D 采用存储器到存储器模式, 这种模式把前景层和背景层作为 DMA2D 输入,且支
持颜色格式转换和颜色混合。
第 25 行,设置前景层数据首地址。
第 26 行,设置背景层数据首地址,这里是把输出区中的数据作为背景层。
第 27 行,设置输出存储器首地址。
第 28 行,设置前景层行偏移。
第 29 行,设置背景层行偏移。
第 29 行,设置输出区行偏移。
第 33-37 行,前景层,背景层和输出区都采用 RGB565 格式,并且为前景层配置一个 Alpha 值。另
外注意,如果是输出到 LCD 显存,那么输出颜色格式要与 LCD 颜色格式一致,否则显示不正常。
第 39 行,高 16 位用于设置每行的像素数,低 16 位用于设置行数,合并起来决定总传输次数。
第 42-45 行,启动传输,并等待传输完成。
使用举例:
将大小 128*128,颜色格式为 RGB565 的位图绘制到 LCD 起始坐标为(176, 168)的区域,输出颜色格
式也配置为 RGB565,透明度设置为 200(255 表示完全不透明,0 表示完全透明)。
1. _DMA2D_MixColorsBulk((uint32_t *)_achuoying, /* 位图地址 */
2. 0, /* 位图行偏移 */
3. (uint32_t *)(SDRAM_LCD_BUF1 + g_LcdWidth*168*2 + 176*2), /* 显示起始地址(176, 168) */
4. g_LcdWidth-128, /* 目标区行偏移 */
5. 128, /* 目标区长 */
6. 128, /* 目标区高 */
7. 200); /* 位图显示透明度 200 */
第 1 行是位图首地址。
第 2 行是位图的行偏移,行偏移的意思就是一行结束到下一行开始的距离,单位像素个数。由于整个
位图都要绘制,所有行偏移就是 0。
第 3 行,根据设置的起始坐标,计算起始坐标在 LCD 显存中的具体位置。
SDRAM_LCD_BUF1 表示 LCD 显存首地址。
g_LcdWidth*168*2 计算的是行数占用的字节数。
176*2 计算的是所在行的具体地址。
乘以 2 是因为 RGB565 颜色格式的 1 个像素占用两个字节。
第 4 行,输出行偏移的,由于输出区需要的长度是 128,那么行偏移就是 LCD 的长度减去 128。
/*
*********************************************************************************************************
* 函 数 名: _DMA2D_MixColorsBulk
* 功能说明: 前景层和目标区域的颜色混合
* 形 参: pColorFG 前景层数据源地址
* OffLineSrcFG 前景层图像的行偏移
* pColorDst 目标区数据地址
* OffLineDst 目标区的行偏移
* xSize 目的区域的X轴大小,即每行像素数
* ySize 目的区域的Y轴大小,即行数
* Intens 设置前景层的透明度,255表示完全不透明,0表示完全透明
* 返 回 值: 无
*********************************************************************************************************
*/
static void _DMA2D_MixColorsBulk(uint32_t * pColorFG,
uint32_t OffLineSrcFG,
uint32_t * pColorDst,
uint32_t OffLineDst,
uint32_t xSize,
uint32_t ySize,
uint8_t Intens)
{
/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */
DMA2D->CR = 0x00020000UL | (1 << 9);
DMA2D->FGMAR = (uint32_t)pColorFG;
DMA2D->BGMAR = (uint32_t)pColorDst;
DMA2D->OMAR = (uint32_t)pColorDst;
DMA2D->FGOR = OffLineSrcFG;
DMA2D->BGOR = OffLineDst;
DMA2D->OOR = OffLineDst;
/* 前景层,背景层和输出区都是用的RGB565格式 */
DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565
| (1UL << 16)
| ((uint32_t)Intens << 24);
DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
DMA2D->OPFCCR = LTDC_PIXEL_FORMAT_RGB565;
DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize;
/* 启动传输 */
DMA2D->CR |= DMA2D_CR_START;
/* 等待DMA2D传输完成 */
while (DMA2D->CR & DMA2D_CR_START) {}
}
4 模式 4:存储器到存储器模式,带颜色格式转换和混合
此函数用于前景层和背景层的颜色混合,并将混合后的图像输出到目标区域。
第 26 行,DMA2D 采用存储器到存储器模式, 这种模式把前景层和背景层作为 DMA2D 输入,且支
持颜色格式转换和颜色混合。
第 27 行,设置前景层数据首地址。
第 28 行,设置背景层数据首地址。
第 29 行,设置输出存储器首地址。
第 30 行,设置前景层行偏移。
第 31 行,设置背景层行偏移。
第 32 行,设置输出区行偏移。
第 35-37 行,前景层,背景层采用 ARGB8888 格式,输出区采用 RGB565 格式。另外注意,如果是
输出到 LCD 显存,那么输出颜色格式要与 LCD 颜色格式一致,否则显示不正常。
第 38 行,高 16 位用于设置每行的像素数,低 16 位用于设置行数,合并起来决定总传输次数。
第 41-44 行,启动传输,并等待传输完成。
使用举例:
将两个大小 128*128,颜色格式为 ARGB8888 的位图混合后绘制到 LCD 起始坐标为(24, 168)的区域,
输出颜色格式配置为 RGB565。
1. _DMA2D_AlphaBlendingBulk((uint32_t *)_aclufei, /* 前景层位图地址 */
2. 0, /* 前景层行偏移 */
3. (uint32_t *)_acsuolong, /* 背景层位图地址 */
4. 0, /* 背景层行偏移 */
5. (uint32_t *)(SDRAM_LCD_BUF1 + g_LcdWidth*168*2 + 24*2), /* 显示起始地址(24, 168) */
6. g_LcdWidth-128, /* 目标区行偏移 */
7. 128, /* 目标区长 */
8. 128); /* 目标区高 */
第 1 行是前景层位图首地址。
第 2 行是位图的行偏移,行偏移的意思就是一行结束到下一行开始的距离,单位像素个数。由于整个
位图都要绘制,所有行偏移就是 0。
第 3 行是背景层位图首地址。
第 4 行是背景层行偏移。
第 5 行,根据设置的起始坐标,计算起始坐标在 LCD 显存中的具体位置。
SDRAM_LCD_BUF1 表示 LCD 显存首地址。
g_LcdWidth*168*2 计算的是行数占用的字节数。
24*2 计算的是所在行的具体地址。
乘以 2 是因为 RGB565 颜色格式的 1 个像素占用两个字节。
第 6 行,输出行偏移的,由于输出区需要的长度是 128,那么行偏移就是 LCD 的长度减去 128。
/*
*********************************************************************************************************
* 函 数 名: _DMA2D_AlphaBlendingBulk
* 功能说明: 前景层和背景层的颜色混合
* 形 参: pColorFG 前景层源数据地址
* OffLineSrcFG 前景层源数据行偏移
* pColorBG 背景层源数据地址
* OffLineSrcBG 背景层源数据行偏移
* pColorDst 目标区地址
* OffLineDst 目标区行偏移
* xSize 目标区域的X轴大小,即每行像素数
* ySize 目标区域的Y轴大小,即行数
* 返 回 值: 无
*********************************************************************************************************
*/
static void _DMA2D_AlphaBlendingBulk(uint32_t * pColorFG,
uint32_t OffLineSrcFG,
uint32_t * pColorBG,
uint32_t OffLineSrcBG,
uint32_t * pColorDst,
uint32_t OffLineDst,
uint32_t xSize,
uint32_t ySize)
{
/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */
DMA2D->CR = 0x00020000UL | (1 << 9);
DMA2D->FGMAR = (uint32_t)pColorFG;
DMA2D->BGMAR = (uint32_t)pColorBG;
DMA2D->OMAR = (uint32_t)pColorDst;
DMA2D->FGOR = OffLineSrcFG;
DMA2D->BGOR = OffLineSrcBG;
DMA2D->OOR = OffLineDst;
/* 前景层,背景层采用ARGB8888格式,输出区采用RGB565格式 */
DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
DMA2D->OPFCCR = LTDC_PIXEL_FORMAT_RGB565;
DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize;
/* 启动传输 */
DMA2D->CR |= DMA2D_CR_START;
/* 等待DMA2D传输完成 */
while (DMA2D->CR & DMA2D_CR_START) {}
}
5 模式 5:存储器到存储器模式,带颜色格式转换和混合,前景色是固定的
此函数用于在指定位置显示 ARGB8888 格式位图。
第 24 行,DMA2D 采用存储器到存储器模式, 这种模式把前景层和背景层作为 DMA2D 输入,且支
持颜色格式转换和颜色混合。
第 25 行,设置前景层数据首地址。
第 26 行,设置背景层数据首地址,这里是把输出区中的数据作为背景层。
第 27 行,设置输出存储器首地址。
第 28 行,设置前景层行偏移。
第 29 行,设置背景层行偏移。
第 30 行,设置输出区行偏移。
第 33-35 行,前景层颜色格式是 LTDC_PIXEL_FORMAT_ARGB8888,即位图的颜色格式。背景层和
输出区颜色格式可配置。另外注意,如果是输出到 LCD 显存,那么输出颜色格式要与 LCD 颜色格式
一致,否则显示不正常。
第 36 行,高 16 位用于设置每行的像素数,低 16 位用于设置行数,合并起来决定总传输次数。
第 39-42 行,启动传输,并等待传输完成。
使用举例:
将大小 128*128,颜色格式为 ARGB8888 的位图绘制到 LCD 起始坐标为(176, 20)的区域,输出颜色
格式配置为 RGB565。
1. _DMA2D_DrawAlphaBitmap((void *)(SDRAM_LCD_BUF1 + g_LcdWidth*20*2 + 176*2), /* 显示起始地址(176, 20) */
2. (void *)_aclufei, /* 位图地址 */
3. 128, /* 位图长 */
4. 128, /* 位图高 */
5. 0, /* 位图行偏移 */
6. g_LcdWidth-128, /* 目标区行偏移 */
7. LTDC_PIXEL_FORMAT_RGB565); /* 目标区颜色格式 */
第 1 行,根据设置的起始坐标,计算起始坐标在 LCD 显存中的具体位置。
SDRAM_LCD_BUF1 表示 LCD 显存首地址。
g_LcdWidth*20*2 计算的是行数占用的字节数。
176*2 计算的是所在行的具体地址。
乘以 2 是因为 RGB565 颜色格式的 1 个像素占用两个字节
第 2 行是位图首地址。
第 5 行是位图的行偏移,行偏移的意思就是一行结束到下一行开始的距离,单位像素个数。由于整个
位图都要绘制,所有行偏移就是 0。
第 6 行,输出行偏移的,由于输出区需要的长度是 128,那么行偏移就是 LCD 的长度减去 128。
/*
*********************************************************************************************************
* 函 数 名: _DMA2D_DrawAlphaBitmap
* 功能说明: ARGB8888格式位图显示
* 形 参: pDst 目标区地址
* pSrc 源数据地址,即位图首地址
* xSize 目标区域的X轴大小,即每行像素数
* ySize 目标区域的Y轴大小,即行数
* OffLineSrc 源数据行偏移
* OffLineDst 目标区行偏移
* PixelFormat 目标区颜色格式
* 返 回 值: 无
*********************************************************************************************************
*/
static void _DMA2D_DrawAlphaBitmap(void * pDst,
void * pSrc,
uint32_t xSize,
uint32_t ySize,
uint32_t OffLineSrc,
uint32_t OffLineDst,
uint32_t PixelFormat)
{
/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */
DMA2D->CR = 0x00020000UL | (1 << 9);
DMA2D->FGMAR = (uint32_t)pSrc;
DMA2D->BGMAR = (uint32_t)pDst;
DMA2D->OMAR = (uint32_t)pDst;
DMA2D->FGOR = OffLineSrc;
DMA2D->BGOR = OffLineDst;
DMA2D->OOR = OffLineDst;
/* 前景层颜色格式是LTDC_PIXEL_FORMAT_ARGB8888,即位图的颜色格式,背景层和输出区颜色格式可配置 */
DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
DMA2D->BGPFCCR = PixelFormat;
DMA2D->OPFCCR = PixelFormat;
DMA2D->NLR = (uint32_t)(xSize << 16) | (uint16_t)ySize;
/* 启动传输 */
DMA2D->CR |= DMA2D_CR_START;
/* 等待DMA2D传输完成 */
while (DMA2D->CR & DMA2D_CR_START) {}
}