** 01. **
LTDC
众所周知,STM32H系列作为高性能芯片,大部分都具有专门为LCD屏幕服务的外设。其中LTDC就是专门的控制LCD屏幕的外设。
LTDC全称 Lcd-Tft Display Controller 即LCD刷新控制器,在许多H7系列和其他一些系列上都有。
本期我们以STM32N6为例介绍如何使用STM32中的 LTDC外设 。
LTDC支持多种图像颜色格式,他们通过LTDC的抖动单元统一为RGB格式输出到LCD显示屏中。
LTDC支持 双图层混叠 ,我们可以单独设置两个图层的内容和透明度,以及对图层进行设置,具有非常高的显示性能和操控性。
** 02. **
通讯协议
在了解LTDC之前需要了解LTDC的协议 相关 。
LTDC的协议相较于基础协议较为复杂,不做特别仔细的介绍,仅仅简单的介绍一下。我们仔细来看一看。
LTDC的协议主要分为了四个部分:
同步信号
VSYNC (VSS): 垂直同步信号
HSYNC (HSS): 水平同步信号
DE: 数据使能信号
DCLK: 像素时钟
数据信号
DR[7:0]: 红色数据线
DG[7:0]: 绿色数据线
DB[7:0]: 蓝色数据线
垂直时序
Tv: 一帧的总时间
Tvw: VSYNC脉冲宽度
Tvbp: VSYNC后肩
Tvfp: VSYNC前肩
Vdisp: 垂直显示周期
水平时序
Thw: HSYNC脉冲宽度
Thbp: HSYNC后肩
Thfp: HSYNC前肩
Thdisp: 水平显示周期
需要注意的不同的LCD这些参数各不相同,需要详尽查看芯片手册,不同的LCD之间参数差距会很大的。
参考手册中会给一个 典型值 ,这些典型值是以时钟为单位的,这张表格对于等会能够在STM32中使用LTDC至关重要!
LTDC的 显示区域和屏幕并不相同 ,可以由我们来决定,这也是由Layout层来决定的,其次我们可以轻松的控制它的透明度,底色等等参数。
总之LTDC是一个非常灵活方便的 LCD控制器 。
** 03. **
CubeMX
以STM32N6为例,我们打开CubeMX查看LTDC选项。
由于我们的显示屏是RGB888的,因此设置显示屏刷新模式为RGB888。
参数设置中,按照LCD屏幕手册输入参数,HSYNC Width设置为5,设置为参考数+1,这是要求。所以设置为5的时候, 实际应用的是4 .
设置层数和窗体的起始位置和位置。
这样子就完成了区域设置。
设置帧缓存区的数据格式以及默认透明度,我们 拉满就是不透明 。
最后对帧缓存区进行设置,我们设置为和显示窗口一样的大小。
需要注意的是有一些型号需要在这里填入帧缓存区的地址就是存放我们想要显示的内容的地址。但是N6这里是没有 地址选项 的,我们需要在代码中进行修改。
紧接着我们还需要检查GPIO引脚是否对应LCD的实际引脚,并且开启两个IO控制LCD的亮灭。
最后就是LTDC的始终,根据芯片手册的典型值25MHZ,我们需要从时钟树中拉出来一条 25MHZ 的时钟。
代码实现
** 04. **
我们需要一张图片数据,这里采用ST的例程,一张156X129的RGB565数据。
HAL_LTDC_SetAddress(&hltdc, (uint32_t) dolphin_156x129_565, 0);
设置LTDC的地址,参数分别是ltdc句柄, 图画地址 以及图层索引。
这样子就可以正常的显示图片了。
static int i = 255; i = i-5; if(i < 0) { i = 255; } HAL_LTDC_SetAlpha(&hltdc, i, 0);
我们简单的写一个函数让图层0渐渐黯淡即透明度递减。
除此之外,我们可以在这个的基础上添加一个图层,实现两张图的混叠。
HAL_LTDC_SetAddress(&hltdc, (uint32_t) dolphin_156x129_565, 0); HAL_LTDC_SetAddress(&hltdc, (uint32_t) gImage_123, 1); while (1) { static int i = 255; i = i-5; if(i < 0) { i = 255; } HAL_LTDC_SetAlpha(&hltdc, i, 0); HAL_LTDC_SetAlpha(&hltdc, 255-i, 1); HAL_Delay(50); }
CubeMX的BUG?
** 05. **
当然我目前没用过H7的LTDC,是直接在N6上手的。但是使用的过程中发现一件事情。
N6有 RIF 安全管理机制。在参考ST例程的时候发现,要想正确使用LTDC必须对其安全性做设置。例程代码如下:
RIMC_master.MasterCID = RIF_CID_1;RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_LTDC1 , &RIMC_master);HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDCL1 , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
大体就是赋予LTDC的图层一更高的安全优先级,不然好像无法访问到图片数据。
然后如果要使用图层2的话,也要如此提高LTDC2的优先级。但是问题就在要使用RIMC的这几个函数,就要求需要开启RIF管理。
不过通过层层追逐。发现问题是某个宏定义:
要让CPU处于安全域,然后找了半天 没找到 这个选项,最后灵机一动,直接在CubeMX中搜索RIF.
这时候就会跳出来RIF的配置,勾选选项即可。
这说明有时候太依赖CubeMX难免会出现这个问题。不过没有CubeMX的话,自己琢磨这个玩意儿又不知道得到什么时候,用了CubeMX琢磨一个晚上就弄好了,且行且学吧。