STM32----LTDC与DMA2D

一、硬件环境

       第一代野火F429开发板,MCU为stm32f429IGT6。板载IS42S16400J SDRAM,16bit位宽 8M容量。

      TFT为RG888接口,分辨率为800*480。

 

 

二、LTCD初始化

(1)初始化GPIO与SDRAM

(2)初始化相关时钟

  //2、LTDC相关时钟初始化
  /* 配置 PLLSAI 分频器,它的输出作为像素同步时钟CLK*/
  /* PLLSAI_VCO 输入时钟 = HSE_VALUE/PLL_M = 1 Mhz */
  /* PLLSAI_VCO 输出时钟 = PLLSAI_VCO输入 * PLLSAI_N = 420 Mhz */
  /* PLLLCDCLK = PLLSAI_VCO 输出/PLLSAI_R = 420/6  Mhz */
  /* LTDC 时钟频率 = PLLLCDCLK / DIV = 420/6/8 = 8.75 Mhz */
  /* LTDC时钟太高会导花屏,若对刷屏速度要求不高,降低时钟频率可减少花屏现象*/
  /* 以下函数三个参数分别为:PLLSAIN,PLLSAIQ,PLLSAIR,其中PLLSAIQ与LTDC无关*/

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE);
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE);
	
   RCC_PLLSAIConfig(420, 6, 6);  
	 
   RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8);
	 
   RCC_PLLSAICmd(ENABLE);
	 
   while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET);

(3)初始化LTDC结构体

        //背景色
	 LTDC_InitStruct.LTDC_BackgroundBlueValue = 0;
	 LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;
	 LTDC_InitStruct.LTDC_BackgroundRedValue = 0;
	 
	 //极性
	 LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL;
	 LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL;
	 LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC;
	 LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL;

	 //横纵信号宽度
         LTDC_InitStruct.LTDC_AccumulatedActiveW = HBP + HSW + LCD_PIXEL_WIDTH  - 1;	
	 LTDC_InitStruct.LTDC_AccumulatedActiveH = VBP + VSW + LCD_PIXEL_HEIGHT - 1;	 
	 LTDC_InitStruct.LTDC_AccumulatedVBP = VSW + VBP - 1;
	 LTDC_InitStruct.LTDC_AccumulatedHBP = HSW + HBP - 1;
	 LTDC_InitStruct.LTDC_VerticalSync   = VSW - 1;
	 LTDC_InitStruct.LTDC_HorizontalSync = HSW - 1;
	 LTDC_InitStruct.LTDC_TotalHeigh = VBP + VSW + LCD_PIXEL_HEIGHT + VFP -1;
	 LTDC_InitStruct.LTDC_TotalWidth = HBP + HSW + LCD_PIXEL_WIDTH   + HFP -1;
	 
         LTDC_Init(&LTDC_InitStruct);
	 
	 LTDC_Cmd(ENABLE);

具体的HBP\VBP\HSW\VSW\HFP\VFP等参数,参考液晶的参考手册

(4)初始化层结构体

void LCD_LayerInit(void)
{
  //使能2层,刷500次纯色5.5S
  //使能1层,刷500次纯色4.3S
  LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct; 
  
  /* 层窗口配置 */   
  //起始像素点与结束像素点
  LTDC_Layer_InitStruct.LTDC_HorizontalStart = HBP + HSW;
  LTDC_Layer_InitStruct.LTDC_HorizontalStop = HSW+HBP+LCD_PIXEL_WIDTH-1;
  LTDC_Layer_InitStruct.LTDC_VerticalStart =  VBP + VSW; 
  LTDC_Layer_InitStruct.LTDC_VerticalStop = VSW+VBP+LCD_PIXEL_HEIGHT-1;
	
  /* 像素格式配置*/
  LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_RGB888;
  LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255;  //透明度     
	
  LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0xFF;        
  LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0xFF;       
  LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0xFF;         
  LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0xFF;   
	
  LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA;  //背景层恒定Alpha值
  LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA;  //第一层使用像素Alpha x 
  
  /* 该成员应写入(一行像素数据占用的字节数+3)
  Line Lenth = 行有效像素个数 x 每个像素的字节数 + 3 
  行有效像素个数 = LCD_PIXEL_WIDTH 
  每个像素的字节数 = 2(RGB565/RGB1555)/ 3 (RGB888)/ 4(ARGB8888) 
  */
  LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_PIXEL_WIDTH * 3) + 3);
  /* 从某行的起始位置到下一行起始位置处的像素增量
  LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_PIXEL_WIDTH * 3);
  
  /* 配置有效的行数 */  
  LTDC_Layer_InitStruct.LTDC_CFBLineNumber = LCD_PIXEL_HEIGHT;
  
  /* 配置本层的显存首地址 */    
  LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_FRAME_BUFFER;
  
  /* 以上面的配置初始化第 1 层*/
  LTDC_LayerInit(LTDC_Layer1, &LTDC_Layer_InitStruct);

  /*配置第 2 层,若没有重写某个成员的值,则该成员使用跟第1层一样的配置 */
  /* 配置本层的显存首地址,这里配置它紧挨在第1层的后面*/     
  LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_FRAME_BUFFER + BUFFER_OFFSET;

	/* 配置混合因子,使用像素Alpha参与混合 */       
  LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA;  //第一层像素Alpha x
  LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA;  //第二层像素Alpha x

  /* 初始化第2层 */
  LTDC_LayerInit(LTDC_Layer2, &LTDC_Layer_InitStruct);
 
 /* 立即重载配置 */  
 LTDC_ReloadConfig(LTDC_IMReload);

 /*使能前景及背景层 */
  LTDC_LayerCmd(LTDC_Layer1, ENABLE); 
  LTDC_LayerCmd(LTDC_Layer2, ENABLE);
 
  /* 立即重载配置 */  
  LTDC_ReloadConfig(LTDC_IMReload);

  /* 设定字体(英文) */    
  LCD_SetFont(&LCD_DEFAULT_FONT); 
}

 

三、DMA2D的使用

网上很多教程只是简单地用了DMA2D的 R_M功能,其他功能的程序找了半天就找到个M_M模式的,其他都自己摸索。。。

提供如下代码供参考,基于野火的第19章节,LTDC显示程序。至于R_M模式的代码就不提供了。。。

 

(1)DMA2D M2M模式:

这个模式主要是用来从一个层把数据复制到另外一个层。不能进行颜色格式转换以及颜色混合

下面的程序实现了把数据从LTDC的层1复制到层2,层1为全红色,层2全蓝色。

void DMA2D_M2M_Config(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
    DMA2D_InitTypeDef      DMA2D_InitStruct;
    DMA2D_FG_InitTypeDef   DMA2D_FG_InitStruct;
 
    //目标区域为LTDC的第二层,源区域为第一层
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE);
    DMA2D_DeInit();
 
    DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M;
    DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB888;
    DMA2D_InitStruct.DMA2D_OutputMemoryAdd = 0xD0000000 + 800*480*3 + 3*(800*Ypos + Xpos);
    DMA2D_InitStruct.DMA2D_NumberOfLine = Height;
    DMA2D_InitStruct.DMA2D_PixelPerLine = Width;
    DMA2D_InitStruct.DMA2D_OutputGreen = 0; //无影响
    DMA2D_InitStruct.DMA2D_OutputBlue = 0; //无影响
    DMA2D_InitStruct.DMA2D_OutputRed = 0; //无影响
    DMA2D_InitStruct.DMA2D_OutputAlpha = 0; //无影响
 
    DMA2D_InitStruct.DMA2D_OutputOffset = (800 - Width);
    DMA2D_Init(&DMA2D_InitStruct);
 

    DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
    DMA2D_FG_InitStruct.DMA2D_FGCM = DMA2D_RGB888;
    DMA2D_FG_InitStruct.DMA2D_FGMA = 0xD0000000+3*(800*Ypos + Xpos);
    DMA2D_FGConfig(&DMA2D_FG_InitStruct);
 
    /* Start Transfer */
    DMA2D_StartTransfer();
 
    /* Wait for CTC Flag activation */
    while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET)
    {
    }
}

 

FPC模式与BLEND模式的主函数:

int main(void)
{
	u32 i;

  /* LED 端口初始化 */
  LED_GPIO_Config();	 
  
  /*初始化液晶屏*/
  LCD_Init();
  LCD_LayerInit();
  LTDC_Cmd(ENABLE);
	
  /*把背景层刷黑色*/


  LCD_SetLayer(LCD_BACKGROUND_LAYER);  
  //LCD_SetTransparency(0xff);
  LCD_Clear(LCD_COLOR_RED);	
	
  LCD_SetLayer(LCD_FOREGROUND_LAYER);  
  //LCD_SetTransparency(0xff);	
  LCD_Clear(LCD_COLOR_BLUE);
	
  LED_RGBOFF;    

  Delay(0xfff);  

  for(i=0;i<1168000;i+=2)
 {
         *(u16*)(0xD0300000+i) = 0xFFE0; //黄色
	 *(u16*)(0xD0500000+i) = 0x07E0; //绿色
 }

  DMA2D_M2M_Config(100, 100, 200, 200);


  while(1)
 {
    //LCD_Test();
 }

}

(2)FPC模式DMA2D使用:

此模式主要是将图层颜色格式进行转换后,输出到目标地址

此模式是不能进行颜色混合的

void DMA2D_M2M_Config(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
    DMA2D_InitTypeDef      DMA2D_InitStruct;
    DMA2D_FG_InitTypeDef   DMA2D_FG_InitStruct;

    DMA2D_DeInit();
 
    DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_PFC;  //此模式可进行格式转换,不能进行颜色混合
    DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB888;
    DMA2D_InitStruct.DMA2D_OutputMemoryAdd = 0xD0000000 + 3*(800*Ypos + Xpos) + 800*480*3;
    DMA2D_InitStruct.DMA2D_NumberOfLine = Height;
    DMA2D_InitStruct.DMA2D_PixelPerLine = Width;
	
    DMA2D_InitStruct.DMA2D_OutputAlpha = 0x00; //无影响
    DMA2D_InitStruct.DMA2D_OutputGreen = 0;
    DMA2D_InitStruct.DMA2D_OutputBlue = 0;
    DMA2D_InitStruct.DMA2D_OutputRed = 0;
    DMA2D_InitStruct.DMA2D_OutputOffset = (800 - Width);
    DMA2D_Init(&DMA2D_InitStruct);
  
    DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);  //填充默认值
    DMA2D_FG_InitStruct.DMA2D_FGCM = DMA2D_RGB565;
    DMA2D_FG_InitStruct.DMA2D_FGMA = 0xD0300000 + 2*(800*Ypos + Xpos); 
    DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = COMBINE_ALPHA_VALUE ; //无影响
    DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0x00;
    DMA2D_FGConfig(&DMA2D_FG_InitStruct);
 
    /* Start Transfer */
    DMA2D_StartTransfer();
 
    /* Wait for CTC Flag activation */
    while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET)
    {
    }
}	

(3)BLEND模式DMA2D使用:

此模式可以进行颜色格式转换以及颜色混合

颜色混合,指的是将前景与背景的颜色混合后输出到目标区域,所以这里需要初始化前景与背景的结构体

void DMA2D_M2M_Config(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
    DMA2D_InitTypeDef      DMA2D_InitStruct;
    DMA2D_FG_InitTypeDef   DMA2D_FG_InitStruct;
    DMA2D_BG_InitTypeDef   DMA2D_BG_InitStruct;

    DMA2D_DeInit();
 
    DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_BLEND;
    DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB888;
    DMA2D_InitStruct.DMA2D_OutputMemoryAdd = 0xD0000000+ 3*(800*Ypos + Xpos) + BUFFER_OFFSET;
    DMA2D_InitStruct.DMA2D_NumberOfLine = Height;
    DMA2D_InitStruct.DMA2D_PixelPerLine = Width;
    DMA2D_InitStruct.DMA2D_OutputAlpha = 0x00;  //在DMA2D_M2M_BLEND下无影响
    DMA2D_InitStruct.DMA2D_OutputGreen = 0;
    DMA2D_InitStruct.DMA2D_OutputBlue = 0;
    DMA2D_InitStruct.DMA2D_OutputRed = 0;
    DMA2D_InitStruct.DMA2D_OutputOffset = (800- Width);
    DMA2D_Init(&DMA2D_InitStruct);
 
  
    DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);  //填充默认值
    DMA2D_FG_InitStruct.DMA2D_FGCM = DMA2D_RGB565;
    DMA2D_FG_InitStruct.DMA2D_FGMA = 0xD0300000 + 2*(800*Ypos + Xpos); 
    DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = COMBINE_ALPHA_VALUE ;
    DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0x10; //前景层的透明值
    DMA2D_FGConfig(&DMA2D_FG_InitStruct);
 
 
    DMA2D_BG_StructInit(&DMA2D_BG_InitStruct);
    DMA2D_BG_InitStruct.DMA2D_BGCM = DMA2D_RGB565;
    DMA2D_BG_InitStruct.DMA2D_BGMA = 0xD0500000 + 2*(800*Ypos + Xpos); 
    DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_MODE  = COMBINE_ALPHA_VALUE;
    DMA2D_BG_InitStruct.DMA2D_BGPFC_ALPHA_VALUE = 0x80; //背景层的透明值
    DMA2D_BGConfig(&DMA2D_BG_InitStruct);
 
 
    /* Start Transfer */
    DMA2D_StartTransfer();
 
    /* Wait for CTC Flag activation */
    while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET)
    {
    }
}	

实际效果:

(1)M_M

(2)FPC

(3)BLEND

因为前景黄色透明度0x10,背景绿色透明度0x80,所以实际图像绿中带一点黄

NOTE:(1)在进行图层数据的复制时,源区域与目标区域大小一致。

                      因为前景层与后景层的Height与Width取自DMA2D_InitTypeDef的结构体成员DMA2D_NumberOfLine与

                      DMA2D_PixelPerLine

              (2)前景或者后景层源起始区域是可变的

                      通过以下结构体成员设置前景层偏移值。

uint32_t DMA2D_FGMA;

                       背景层偏移值:

 uint32_t DMA2D_BGMA;     

                        比如800*480的分辨率下,将RGB565格式坐标为100*100大小为50*50的前景层区域复制到RBG888格式坐标为

30*30大小为50*50的目标区域,前景层DMA2D_FGMA填充值为:前景层起始地址 + 2*(100*100)

                                                            目标地址DMA2D_OutputOffset填充:目标地址 + 3*(30*30)

DMA2D_NumberOfLineDMA2D_PixelPerLine分别填充50的值即可。前景层Height与Width也是取自这两个结构体成员。

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值