使用STM32CubeMX进行STM32F429 LCD编程<二>层配置

来源:互联网 发布:泳衣品牌 知乎 编辑:程序博客网 时间:2024/06/06 05:54
一.配置重载
所有层的寄存器均执行影子操作。一旦对某个寄存器执行写操作,便不应在重载完成前再次进行修改。
因此,如果在尚未重载时对同一寄存器执行新的写操作,则将覆盖之前的配置。
该控制通过配置寄存器SRCR来完成。
在HAL_LTDC_ConfigLayer(stm32f4xx_hal_ltdc.c中)函数中有:
/* Set the Immediate Reload type */
hltdc->Instance->SRCR = LTDC_SRCR_IMR;
或使用宏:
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);

二.层和层混合
最多可单独使能、禁止和配置两个层。层显示顺序固定,即自下而上。如果使能两个层,则层2为顶部显示窗口。

层混合
混合操作始终有效,两层可按照 LTDC_LxBFCR 寄存器中配置的混合系数进行混合。
混合顺序固定,即由下至上。如果使能了两层,首先第 1 层将与背景色混合,随后第 2 层与第 1 层和背景的混合颜色结果再次混合。
请参见下图。

所以层1(layer 0)为背景层,层2(layer 1) 为前景层。
#define LCD_BACKGROUND_LAYER     0x0000
#define LCD_FOREGROUND_LAYER     0x0001
当使用1024x768分辨率的液晶时,最好只使用一层,即上述的第1层,否则,当使用2层时,只能显示静态的画面,动态刷新就会闪烁。
因为每一层都占用一个SDRAM缓冲区,当液晶分辨率过大时,所需要刷新的缓冲区(从SDRAM到LCD)的数据量就越大。当使用2层时,刷新的数据量翻倍。
LTDC会始终在两层间执行混合操作,即便其中一层禁止也是如此(即使使用控制寄存器禁止了某层)。

三.层窗口
可为每个层定位和调整大小,各个层必须位于有效显示区域内。
窗口位置和大小通过左上和右下的 X/Y 位置以及包含同步、后沿大小和有效数据区域的内部时序发生器配置。请参见 LTDC_LxWHPCR 和 LTDC_WVPCR 寄存器。
可编程层位置和大小定义了一行中的第一个/最后一个可见像素和窗口中的第一个/最后一个可见行。它允许显示完整的图像帧,也允许只显示图像帧的一部分。
请参见图 83。
· 层中的第一个和最后一个可见像素通过配置 LTDC_LxWHPCR 寄存器中的 WHSTPOS[11:0]和 WHSPPOS[11:0] 进行设置。
· 层中的第一个和最后一个可见行通过配置 LTDC_LxWVPCR 寄存器中的 WHSTPOS[11:0]和 WHSPPOS[11:0] 进行设置。


相关配置寄存器LTDC_LxWHPCR
LTDC Layerx Window Horizontal Position Configuration Register
LTDC 第 x 层窗口水平位置配置寄存器 (LTDC_LxWHPCR)(其中 x=1..2)
此寄存器定义第 1 层或第 2 层窗口的水平位置(第一个和最后一个像素)。
一行的第一个可见像素是在 LTDC_BPCR 寄存器中编程的 AHBP[10:0] bits + 1 的值。
一行的最后一个可见像素是在 LTDC_AWCR 寄存器中编程的 AAW[10:0] bits 的值。此范围内的所有值均为允许值。
如在上面的LCD同步时序配置中,将AHBP[10:0] bits设定为6(HSW + HBP- 1:6 + 1 - 1),那么
此处的LTDC_LxWHPCR寄存器一行的第一个可见像素的值就为6 +1= 7。
其他同此。
再次引用图82:

窗口要定义在上图中的有效显示区域内。
从上图可以清楚的看出,一行的第一个有效显示像素坐标为HSYNC(HSW) + HBP,下面的代码描述了它们之间的关系:
/*代码见STM32CubeMX代码仓库中STM32F429I-Discovery下的LCD示例代码*/
/* Windowing configuration */
/* In this case all the active display area is used to display a picture then :
Horizontal start = horizontal synchronization + Horizontal back porch = 30
Horizontal stop = Horizontal start + window width -1 = 30 + 240 -1
Vertical start   = vertical synchronization + vertical back porch     = 4
Vertical stop   = Vertical start + window height -1  = 4 + 320 -1      */     
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;

STM32CubeMX中相关的配置:

生成的代码如下:
pLayerCfg.WindowX0=7;
pLayerCfg.WindowX1=1030;
pLayerCfg.WindowY0=7;
pLayerCfg.WindowY1=774;   
...
if(HAL_LTDC_Init(&hltdc)!=HAL_OK)
{
    _Error_Handler(__FILE__,__LINE__);
}

四.默认颜色
注意它和全局配置中的背景色的区别。
背景色是上面图8.4中的背景层的颜色,这里的默认颜色是层窗口外的颜色---当层窗口的区域小于显示窗口时,之外的区域的颜色。
每层可具有 ARGB 格式的默认颜色,该颜色在定义的层窗口外使用或在层禁止时使用。
默认颜色通过 LTDC_LxDCCR 寄存器配置。
始终在两层间执行混合操作,即便其中一层禁止也是如此。要避免层禁止时显示默认颜色,需将 LTDC_LxBFCR 寄存器中此层的混合系数设置为其复位值。

这是针对层的,因为只有层才有窗口的概念。
STM32CubeMX生成的相应代码如下:
//层配置
pLayerCfg.Backcolor.Blue=0;
pLayerCfg.Backcolor.Green=0;
pLayerCfg.Backcolor.Red=0;
if(HAL_LTDC_ConfigLayer(&hltdc,&pLayerCfg,0)!=HAL_OK)
{
    Error_Handler(__FILE__,__LINE__);
}

层禁止和默认颜色
如同时打开了2层,层0和层1,然后禁止层1:
 __HAL_LTDC_LAYER_DISABLE(&hltdc, 1);
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);
层1禁止后,该层的颜色还是会参与到混合的,只是混合时使用的颜色是层默认颜色值(参见层默认颜色说明)。
1.禁止掉层1后,该层还是会参与颜色混合的。
2.禁止掉层1后,该层使用默认颜色来参与颜色混合。
3.要避免层禁止时显示默认颜色,需将 LTDC_LxBFCR 寄存器中此层的混合系数设置为其复位值。由于层1是前景层,
  只有 此时才会显示层0(除非把层1的alpha值设定为0).

在LCD层初始化时,没有初始化层1,此时也是只使用层0。因为此时层1相关寄存器的设定值为其复位值。
见上面3所说,此时会禁止显示默认颜色。

五. 颜色帧缓冲区长度和颜色帧缓冲区间距
颜色帧缓冲区长度Color Frame Buffer Length
Every layer has a total line length setting for the color frame buffer in bytes and a number of
lines in the frame buffer configurable in the LTDC_LxCFBLR and LTDC_LxCFBLNR
register respectively.
The line length and the number of lines settings are used to stop the prefetching of data to
the layer FIFO at the end of the frame buffer.
• If it is set to less bytes than required, a FIFO underrun interrupt is generated if it has
been previously enabled.
• If it is set to more bytes than actually required, the useless data read from the FIFO is
discarded. The useless data is not displayed.
每层均设置颜色帧缓冲区的总行长(单位为字节)和行数,二者可分别通过 LTDC_LxCFBLR和 LTDC_LxCFBLNR 寄存器进行配置。
行长和行数的设置用于阻止将数据预取到帧缓冲区末尾的层 FIFO 中。
· 如果设置为低于所需字节,则会产生 FIFO 下溢中断(如果之前已使能)。
· 如果设置为高于实际所需字节,则将丢弃从 FIFO 中读取的无用数据。无用数据不会显示。

颜色帧缓冲区间距Color Frame Buffer Pitch
Every layer has a configurable pitch for the color frame buffer, which is the distance between
the start of one line and the beginning of the next line in bytes. It is configured through the
LTDC_LxCFBLR register.
每层的颜色帧缓冲区均具有可配置间距,此间距是一行的开始与下一行开始的距离(以字节为单位)。
它通过 LTDC_LxCFBLR 寄存器配置。

LTDC_LxCFBLR(LTDC Layerx Color Frame Buffer Length Register)  寄存器
LTDC 第 x 层颜色帧缓冲区长度寄存器

示例:
· 采用 RGB565(每像素 2 个字节)格式且宽度为 256 像素的帧缓冲区(每行总字节数
为 256x2=512)需要向此寄存器写入值 0x02000203(其中,间距 = 行长)。
· 采用 RGB888(每像素 3 个字节)格式且宽度为 320 像素的帧缓冲区(每行总字节数
为 320x3=960)需要向此寄存器写入值 0x03C003C3(其中,间距 = 行长)。

LTDC_LxCFBLNR(LTDC Layerx ColorFrame Buffer Line Number Register )寄存器
LTDC 第 x 层颜色帧缓冲区行数寄存器 (LTDC_LxCFBLNR)(其中 x=1..2)
此寄存器定义颜色帧缓冲区中的行数。
位 10:0 CFBLNBR[10:0]:帧缓冲区行数 (Frame Buffer Line Number)
这些位定义帧缓冲区中高电平有效宽度对应的行数。
注意: 行数和行长设置定义针对每层从每个帧中获取的数据量。如果配置为低于所需字节,则会产
生 FIFO 下溢中断(如果使能)。
另一方面,起始地址和间距设置定义存储器中每行的正确起始位置。

STM32CubeMX中相关的配置:

STM32CubeMX生成的相应代码如下:
//层配置
pLayerCfg.ImageWidth=1024;
pLayerCfg.ImageHeight=768;
...
if(HAL_LTDC_ConfigLayer(&hltdc,&pLayerCfg,0)!=HAL_OK)
{
    _Error_Handler(__FILE__,__LINE__);
}

//HAL_LTDC_ConfigLayer-->LTDC_SetConfig 函数内代码:
if(HAL_LTDC_ConfigLayer(&hltdc,&pLayerCfg,0)!=HAL_OK)
{
    Error_Handler(__FILE__,__LINE__);
}
/* Configure the color frame buffer pitch in byte */
LTDC_LAYER(hltdc,LayerIdx)->CFBLR &=~(LTDC_LxCFBLR_CFBLL|LTDC_LxCFBLR_CFBP);
LTDC_LAYER(hltdc,LayerIdx)->CFBLR =(((pLayerCfg->ImageWidth*tmp)<<16U)|(((pLayerCfg->WindowX1-pLayerCfg->WindowX0)*tmp) +3U));
/* Configure the frame buffer line number */
LTDC_LAYER(hltdc,LayerIdx)->CFBLNR &=~(LTDC_LxCFBLNR_CFBLNBR);
LTDC_LAYER(hltdc,LayerIdx)->CFBLNR =(pLayerCfg->ImageHeight);
/* Enable LTDC_Layer by setting LEN bit */ 
LTDC_LAYER(hltdc,LayerIdx)->CR|=(uint32_t)LTDC_LxCR_LEN;

六. 层混合参数Alpha
alpha其实是一个0-1之间的系数,以百分比表示透明度,0表示完全透明,1表示完全不透明。另外alpha混合基于alpha的取值有不同的算法。
STM32F29 LTDC中使用的通用混合公式为:
BC = BF1 x C + BF2 x Cs
  • BC = 混合后的颜色
  • BF1 = 混合系数 1
  • C = 当前层颜色
  • BF2 = 混合系数 2
  • Cs = 底层混合后的颜色
上面的Cs是底层混合后的颜色,由于STM32F29 LTDC中的层混合是逐步进行的,即先是第0层和背景层混合,然后是第1层和上面混合后的颜色再次混合,所以,这是是底层混合后的颜色。
BF1和BF2通过寄存器LTDC_LxBFCR来配置,并结合LTDC_LxCACR寄存器完成混合颜色的计算输出。

LTDC_LxCACR恒定 Alpha 配置寄存器
LTDC Layerx Constant Alpha Configuration Register
此寄存器定义在 alpha 混合中使用的恒定 alpha 值(由硬件实现 255 分频)。
位 7:0 CONSTA[7:0]:恒定 Alpha (Constant Alpha)
这些位配置混合时使用的恒定 Alpha。恒定 Alpha 由硬件实现 255 分频。
示例:如果编程的恒定 Alpha 为 0xFF,则恒定 Alpha 值为 255/255=1

LTDC 第 x 层混合系数配置寄存器 (LTDC_LxBFCR)(其中 x=1..2)
LTDC Layerx Blending Factors Configuration Register
复位值:0x0000 0607
位 10:8 BF1[2:0]:混合系数 1 (Blending Factor 1)
这些位选择混合系数 F1,其值及其含义如下:
100:恒定 Alpha
110:像素 Alpha x 恒定 Alpha

位 2:0 BF2[2:0]:混合系数 2 (Blending Factor 2)
这些位选择混合系数 F2,其值及其含义如下:
101:1-恒定 Alpha 
        即 1减去 Constant Alpha
111:1 -(像素 Alpha x 恒定 Alpha)
        即1 减去 (Pixel Alpha x Constant Alpha) 

上面的恒定Alpha,是在LTDC_LxCACR寄存器中配置的值,
像素Alpha,是像素值中包含的Alpha值,如如ARGB8888格式中,一个像素为32bits,4字节,最高字节为Alpha的值。上面所有的计算中的Alpha值,
均表示(配置中的整数值/255)。
如当BF1为110时,混合系数F1则为:
(像素中的Alpha整数值 / 255)  x (LTDC_LxCACR恒定 Alpha配置值 / 255)
当BF2为111时,混合系数F2则为:
1 - (像素中的Alpha整数值 / 255)  x (LTDC_LxCACR恒定 Alpha配置值 / 255)

示例:仅使能第 1 层,BF1 配置为恒定 Alpha
BF2 配置为 1-恒定 Alpha
恒定 Alpha:在 LxCACR 寄存器中编程的恒定 Alpha 为 240 (0xF0)。因此,恒定 Alpha 值为
240/255 = 0.94
C:当前层颜色为 128
Cs:背景色为 48
第 1 层与背景色混合。
BC = 恒定 Alpha x C + (1 - 恒定 Alpha) x Cs = 0.94 x 128 + (1- 0.94) x 48 = 123。

STM32CubeMX中相关的配置:


STM32CubeMX生成的相应代码如下:
pLayerCfg.Alpha=255;
pLayerCfg.Alpha0=0;
pLayerCfg.BlendingFactor1=LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2=LTDC_BLENDING_FACTOR2_CA;
//HAL_LTDC_ConfigLayer-->LTDC_SetConfig
/* Configure the default color values */
tmp=((uint32_t)(pLayerCfg->Backcolor.Green)<<8U);
tmp1=((uint32_t)(pLayerCfg->Backcolor.Red)<<16U);
tmp2=(pLayerCfg->Alpha0<<24U);
LTDC_LAYER(hltdc,LayerIdx)->DCCR&=~(LTDC_LxDCCR_DCBLUE|LTDC_LxDCCR_DCGREEN|LTDC_LxDCCR_DCRED|LTDC_LxDCCR_DCALPHA);
LTDC_LAYER(hltdc,LayerIdx)->DCCR=(pLayerCfg->Backcolor.Blue|tmp|tmp1|tmp2);
/* Specifies the constant alpha value */
LTDC_LAYER(hltdc,LayerIdx)->CACR&=~(LTDC_LxCACR_CONSTA);
LTDC_LAYER(hltdc,LayerIdx)->CACR=(pLayerCfg->Alpha);
/* Specifies the blending factors */
LTDC_LAYER(hltdc,LayerIdx)->BFCR&=~(LTDC_LxBFCR_BF2|LTDC_LxBFCR_BF1);
LTDC_LAYER(hltdc,LayerIdx)->BFCR=(pLayerCfg->BlendingFactor1|pLayerCfg->BlendingFactor2);

Default Alpha value
默认的Alpha value是针对层的默认颜色来说的,默认颜色在定义的层窗口外使用或在层禁止时使用。
详见上面第四节默认颜色。
当在窗口外和层禁止时,使用该alpha参数值进行颜色混合,即默认颜色RGB和底层颜色的混合参数。
此时,也应遵循上面的通用混合公式BC = BF1 x C + BF2 x Cs,只是此时BF1、BF2中的参数
恒定 Alpha由此Default Alpha value来取代(STM32F429文档对此没有说明)。
在上面第四节默认颜的描述中,有:
要避免层禁止时显示默认颜色,需将 LTDC_LxBFCR 寄存器中此层的混合系数设置为其复位值。
而LTDC_LxBFCR的复位值为0x0000 0607(见上),即此时BF1为110,BF2为111,
混合系数F1为:
BF1(像素中的Alpha整数值 / 255)  x (LTDC_LxCACR恒定 Alpha配置值 / 255)
混合系数F2为:
1 - (像素中的Alpha整数值 / 255)  x (LTDC_LxCACR恒定 Alpha配置值 / 255)
像素中的Alpha整数值此时应为0,则F1和F2均为0.
那么混合公式BC = BF1 x C + BF2 x Cs
BC = 0.

测试
//液晶全局的背景色为已经配置为0,即黑色
//下面是第0层的配置,且只使用了此一层。
pLayerCfg.WindowX0=7;
pLayerCfg.WindowX1=1030;
pLayerCfg.WindowY0=7;
pLayerCfg.WindowY1=774-100; //层窗口,小于有效显示区域
pLayerCfg.PixelFormat=LTDC_PIXEL_FORMAT_RGB565;
pLayerCfg.Alpha=255;
pLayerCfg.Alpha0=255; //默认颜色中的alpha值,修改此值,层窗口外区域颜色的变化(透明度的变化)
pLayerCfg.BlendingFactor1=LTDC_BLENDING_FACTOR1_PAxCA; //注意此时必须设定为像素参与F1计算,而此时的像素alpha值就是层默认颜色中的相应值
pLayerCfg.BlendingFactor2=LTDC_BLENDING_FACTOR2_PAxCA;  //注意此时必须设定为像素参与F1计算,而此时的像素alpha值就是层默认颜色中的相应值
pLayerCfg.FBStartAdress=0xD0000000;
pLayerCfg.ImageWidth=1024;
pLayerCfg.ImageHeight=768-100; //层窗口,小于有效显示区域
pLayerCfg.Backcolor.Blue=0;
pLayerCfg.Backcolor.Green=0xff;
pLayerCfg.Backcolor.Red=0;

代码完整的示例下载地址:
http://pan.baidu.com/s/1slK5129
阅读全文
0 0