本篇详细的记录了如何使用STM32CubeMX配置 STM32F767IGT6 的 LTDC 外设驱动 TFT-LCD (RGB)屏幕。
1. 准备工作
硬件准备
- 开发板:首先需要准备一个开发板,这里我准备的是STM32F767IGT6的核心板+底板。
- TFT-LCD(RGB)屏幕:正点原子7寸RGB屏幕。
开发板底板(只用到了图中的核心板+底板):
RGB屏幕(v1.3):
软件准备
- STM32CubeMX:6.2.1
- Keil MDK:5.3.0
2. STM32 LTDC外设概述
2.1. 什么是LTDC
LTDC全称 LCD-TFT Display Controller,LCD显示控制器,提供了RGB信号和控制信号来直接控制外部LCD显示屏。
为什么是直接控制呢?
一般 TFT-LCD 屏幕中带有驱动IC,并集成有显存,其内部就在不断的将显存内容显示到LCD面板上,我们驱动这类屏幕时往往是直接去操作驱动IC,通过发送操作命令来设置显示模式,通过发送显示数据来修改显存内容,如图:
还有一些屏幕称为RGB屏幕,内部没有驱动IC,操作这种屏幕时往往使用MCU内部集成的LCD控制器直接去控制LCD显示,显存空间当然也是在MCU内部,按照空间大小可以选择放在内部SRAM或者外部SDRAM中,如图:
2.2. 颜色格式
LCD的原理可以理解为一个像素阵,常见的参数如下:
- 屏幕尺寸:对角线长度,单位英寸;
- 屏幕分辨率:像素点的数量,800*480表示一行有800个像素点、有480行;
- 色彩格式:像素点的颜色;
色彩格式是个很重要的参数,用来控制每个像素点的颜色。
单色屏的每个像素点只需要 1bit 来表示(非黑即白),而彩色屏的每个像素点则是由RGB三原色的值混合而成,常用有两种格式:
- RGB888(3B):R值8位、G值8位、B值8位
- RGB565(2B):R值5位、G值6位、B值5位
显然,RGB888 比 RGB565 表示的颜色更多、LTDC也支持RGB888格式,但是RGB888每个像素点需要24bit(3个字节)的显存空间来存储。在资源紧张的嵌入式系统中,在一般屏幕显示需求中过于浪费珍贵的SRAM空间,所以在不影响显示的情况下,建议使用RGB565格式,每个像素点只需要16bit(两个字节)的显存空间就够了。
除此之外,LTDC还支持透明颜色格式:
- ARGB8888(4B):在RGB888的基础上增加了8位A值(Alpha),0x00表示完全透明、0xFF表示不透明;
- ARGB1555(2B):在RGB565的基础上砍掉一位,用作A值,0表示完全透明、1表示不透明;
2.3. LTDC外设功能框图
2.4. LTDC的关键时序参数(重要)
LCD_CLK:像素时钟,每个脉冲刷新一个像素点,所有时序以此为基本单位;
名称 | 作用 |
---|---|
HSYNC width | 水平同步宽度 |
HBP | 水平后沿周期 |
Active width | 有效宽度 |
HFP | 水平前沿周期 |
VSYNC width | 垂直同步宽度 |
VBP | 垂直后沿周期 |
Active height | 有效高度 |
VFP | 垂直前沿周期 |
Active width 和 Active height是可见的LCD显示面板分辨率,所以称为有效宽度和有效高度。
但是在LCD刷新显示的过程中需要水平消隐和垂直消隐:
- 水平消隐(行切换,从上一行到下一行):HSYNC width + HBP + HFP
- 垂直消隐(帧切换,整屏刷新完毕):VSYNC width + VBP + VFP
有效显示宽度和消隐宽度合在一起就是总宽度(Total width),有效显示高度和消隐高度合在一起就是总高度(Total height)。
2.5. LTDC的层和窗口
LTDC有三个层:背景层(BG)、图层1(Layer1)、图层2(Layer2),如图:
① 背景层只能是RGB888格式,并且是一个常量值,在LTDC初始化结构体中由 Backcolor 成员指定;
② 图层用来显示内容;
- 大小是之前我们设置的 Active width 和 Active height,称为有效区域,图中黄色部分;
- 在这个图层的有效区域中可以设置一个任意大小的窗口用于显示,称为Window,图中绿色部分;
- 当窗口小于图层有效区域时,窗口之外的区域会显示该图层背景色;
③ 图层混合
首先要清楚一点,背景和图层的大小都是 Active width 和 Active height。
背景层在最下面,如果开了单个图层,则显示结果为背景层和单个图层混合结果;如果两个图层都开,则显示结果为背景层先和图层1混合,混合结果再与图层2混合的结果。
图层混合在LTDC硬件上是一直开启的,可以直接配置该图层用于混合的Alapha常量来调节整层透明度,范围为0-255,0为完全透明、255为不透明、127为半透明。
如果配合ARGB数据格式可以玩出更多的花样,在此不再展开,后续专门写篇文章玩玩。
3. 使用STM32CubeMX生成工程
选择芯片型号
打开STM32CubeMX,打开MCU选择器:
搜索并选中芯片STM32F767IGT6
:
配置时钟源
- 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
- 如果使用默认内部时钟(HSI),这一步可以略过;
这里我都使用外部时钟:
配置串口
配置USART1用于打印日志,需要注意引脚:
配置SDRAM
本实验中需要在SDRAM中分配显存空间,参考教程:
配置LTDC
RGB LCD 原理图
本文使用的 RGB LCD 提供的接口示意图如下:
除了用来控制LCD背光的LCD_BL引脚连接到普通GPIO上,其余所有引脚都连接到LTDC外设对应的引脚上。
LCD的扫描方向控制引脚LCD_LR和LCD_UD由屏幕背面焊接的电阻决定,默认LCD_LR上拉、LCD_UD下拉:
LCD_LR对应屏幕引脚SHLR,LCD_UD对应屏幕引脚UPDN,根据默认上下拉情况得到默认扫描方向:从左到右,从上到下。
屏幕的上下左右标识如下:
为了同一个底板支持不同分辨率的屏幕,原子搞了一个垃圾设计,用LCD R7、LCD G7、LCD B7三个引脚来读取RGB屏幕的ID,从而判断是哪种类型的分辨率。
这里为了方便起见,使用例程测试出是 1024*600 分辨率的7寸RGB屏幕。
为什么说这是垃圾设计呢?因为我们一般情况下使用的是RGB565接口,参考手册中给出,接线方式是LCD R[0:4] <—> LTDC R[7:3],R值低位是空余的,应该利用这三个去检测ID。
颜色格式配置
本文中使用RGB565颜色格式:
原子的板子设计和cubemx默认配置并不符合,需要手动检查修改GPIO。
屏幕时序参数配置
查阅屏幕的数据手册:
屏幕时序极性配保持默认即可:
背景颜色配置保持默认即可:
层配置
本文中为了演示层混合效果,使用两层配置。
① 图层上的窗口设置如下,有交叉部分,方便观察效果:
② 设置背景色和混合参数:
③ 设置显存空间:
本文中将帧缓存buffer创建在SDRAM中,SDRAM的起始地址为 0xC0000000
,由于使用 RGB565 格式,每个像素点需要两个字节显存,所以整个显存空间为:10246002 = 1228800 B。
不设置显存空间,则该层窗口显示颜色会是黑框,与层1的窗口进行区分。
LTDC GPIO速度配置
LTDC的通信引脚一定要配置为高速度,否则无法驱动屏幕:
配置GPIO
LCD背光控制引脚接在PB5,配置为输出模式:
配置时钟树
STM32F767IG的最高主频到216M,使HCLK = 216Mhz
即可:
LCD_DCK时钟在数据手册中给出的范围是:
保持默认的 48Mhz即可:
生成工程设置
代码生成设置
最后设置生成独立的初始化文件:
生成代码
点击GENERATE CODE
即可生成MDK-V5工程:
4. 背景层显示测试
背景层的显示无需SDRAM,可以用来检查LTDC是否配置成功。
① 修改 main 函数,在LTDC初始化之前,GPIO初始化之后,打开背光:
② 修改ltdc.c中的 MX_LTDC_Init
函数,设置背景色为蓝色,并卡在初始化后等待:
如果配置无误,则屏幕会显示蓝色:
5. 添加SDRAM驱动
参考教程:STM32CubeMX | 31-使用硬件FMC读写SDRAM(W9825G6KH)
SDRAM驱动添加之后,需要在LTDC外设初始化之前,FMC外设初始化之后,添加SDRAM初始化函数:
6. 图层混合测试
图层1+背景层混合测试
保持背景层设置为蓝色不变,开启第1层显示,将while(1) 挪动到图层1初始化完毕之后:
显示效果如下,图层1的窗口显示内容从SDRAM中读出(否则会显示黑色),为白色区域,其余区域显示窗口1的背景色绿色:
此时,背景层的颜色为蓝色,图层1的颜色为白色+绿色,如果将图层透明度设置为半透明,则会看到图层1+背景层混合的效果:
见证奇迹的时刻来啦:
可以看到,图层1的白色区域和背景层混合,变为蓝色,而图层1的绿色区域与背景层混合,变为,我也不知道这是什么色~
图层2+图层1+背景层混合测试
接着再打开图层2,将while(1)挪至图层2初始化代码之后:
虽然三层都有显示,但是图层2设置为不透明,所以只会显示图层2;图层2的窗口因为没有设置显存,为黑色,窗口之外的区域为图层2的背景色红色,效果如下:
接下来将图层2的透明度也设置为半透明,即可看到三层混合的效果:
见证奇迹:
7. 图片显示
生成图片数组
虽然我们没有配置DMA2D外设,但这不能影响我们愉快的玩耍!DMA2D只是为了方便修改SDRAM中的显存用的。
之前配置的时候图层2没有配置显存空间,我们可以把一张图片编译进代码,然后把图片地址作为LTDC的显存地址,虽然此时显存空间在Flash里,我们没法在程序运行时动态的修改显存内容,但这丝毫不影响LTDC外设去读取显存中的图片内容啊!
之前我们设置图层2的窗口大小是400400,所以先去找一张图片,在画图工具中将大小改为400400像素,并另存为 .bmp 图片。
接着使用STemwin中提供的 BmpCvtST.exe 工具,打开刚刚生成的bmp图片,点击另存为:
选择保存为C文件:
格式选择RGB565、红蓝交换:
添加图片数组到工程中
将该文件复制到工程目录中,添加进MDK工程,因为这是适用于STemwin的,所以该文件需要进行少量修改,改成如下即可,其它的都删除(文件的也有一段代码记得删除)。
在 ltdc.c
中声明该数组:
将图片数组作为显存
将图片数组的地址传递给LTDC,并指定显存的大小为400*400:
编译,下载,见证奇迹:
至此,LTDC外设如何驱动RGB 屏幕讲解完毕,下节我们使用DMA2D来修改显存内容,实现打点画线字符等多样显示。
更多精彩文章及资源,请关注我的微信公众号:『mculover666』。
版权声明:本文为CSDN博主「Mculover666」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mculover666/article/details/118434161
暂无评论