历史上的今天
返回首页

历史上的今天

今天是:2025年06月19日(星期四)

正在发生

2020年06月19日 | STM32CubeMX系列教程22:LCD-TFT控制器(LDTC)

2020-06-19 来源:eefocus

一、LTDC简介        

LCD-TFT(液晶显示器 —— 薄膜晶体管)显示器控制器提供并行数字 RGB(红色、绿色、蓝色)以及水平同步、垂直同步、像素时钟和数据使能信号,这些信号直接输出到不同 LCD和 TFT 面板的接口。本章通过Open746I-C开发板控制微雪7inch Capacitive Touch LCD (F)型LCD。其原理图如下:(注:本章介绍的是通过LDTC控制RGB接口的屏幕,即屏幕是不带控制器的,与带控制芯片的8080系列接口的屏幕不同)

LTDC框图如下,最高24条RGB数据线(RGB888),两个可以显示图层,可以进行图像层叠加处理。


RGB时序图如下,RGB接口的屏幕是通过MCU不断发送显示数据到屏幕,逐行扫描显示。

VSYNC: 帧同步信号,表示扫描1帧的开始,一帧也就是LCD显示的一个画面。

HSYNC: 行同步信号,表示扫描1行的开始。

VDEN:数据使能信号。


        MCU会用一部分内存来存储显示的数据,即显存,LDTC控制器不断将显存内的数据发送到屏幕扫描显示。屏幕是通过MCU扫描显示的,要改变显示的图片,只需要改变显存的数据即可。而显存的数据存储的格式和图像的格式有关,例如ARGB8888,RGB888,RGB565等,其中A为透明度,R表示红色,G表示绿色,B表示蓝色。例如RGB565格式的图形,一个像素点只需两个字节存储。ARGB8888一个像素点要四个字节存储。


二、DMA2D简介        

Chrom-Art Accelerator™ (DMA2D) 是专用于图像处理的专业 DMA。由前面介绍可知,显示的图形是通过一定格式存储在内存中,要改变显示的内容,只需将新的数据存储在对应的显存中即可,可以通过DMA传输数据。DMA2D和普通的DMA通道不一样是,它是专用于图像处理的专用DMA,他可以执行下列操作。

  • 用特定颜色填充目标图像的一部分或全部

  • 将源图像的一部分(或全部)复制到目标图像的一部分(或全部)中

  • 通过像素格式转换将源图像的一部分或全部复制到目标图像的一部分或全部中

  • 将像素格式不同的两个源图像部分和 / 或全部混合,再将结果复制到颜色格式不同的部分或整个目标图像中。

三、显示图片实验。       

实验中用SDRAM作为屏幕的显存, 复制上一章SDRAM的工程,修改文件夹名。击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置,LTDC接口类型选择RGB888(24 bits)。启动DMA2D。


配置引脚如下,其中PA3是PWM的背光,这里简单的做为GPIO_OUT进行初始化,设置用户标签为BL。注意:由于CubeMX会默认帮你选择好相关的引脚,但有时和你实际的硬件有冲突(它认为它是最优的,但有时会觉得这功能很烦),这时需要强制配置某些引脚的功能(比较花时间的一步,需要对着原理图仔细检查是否有错误)

配置时钟,系统时钟为216MHz,LCD-TFT为32MHz,如果LCD时钟过高会刷新不过来出现花屏,如果频率过低显示的图像会出现闪烁。

DMA2D主要配置Color Mode 和 DMA2D Input Color Mode。Color Mode为显存的存储格式,此处为RGB565。DMA2D Input Color Mode为源图像的格式,此处配置为RGB565。如果要显示的图形为RGB888格式,则设置为RGB888,DMA2D会转为显存的格式(此处为RGB565)再存储到显存中。

LTDC参数设置,实验LCD分辨率是1024X600,所以Active Width和Active Height 分别为1024和600。关于Synchronization for Width和Synchronizaion for Height里剩余的6个参数为SYNC的时序值,需要按你的LCD数据手册进行调整。实际很多LCD供应商都没有提供像样数据手册,但没数据手册也没关系,如果你使用下面的数据,发现显示不是全屏,其实只要在下面参数的基础上进行微调就可以了。多改几次参数,看一下现像就懂了,不多解释。使用下面的参数,显示效果基本都在可接受的范围内。



简单科普一下:一般的LCD都有DE和SYNC模式。如果使用的是DE模式(一般LCD模块默认是DE模式),对下面SYNC的参数就没有具体要求(想怎么填就怎么填),如果使用SYNC模式,那就乖乖的调吧。可能有人会问,怎么知道自己的LCD模块是什么模式,以上面的LCD的数据手册结合原理图可知:R22 = NC ,R23 = 10K时为SYNC模式R22 = 10K,R23 = NC 时为DE模式(不要问我怎么有数据手册的,地上捡的!)

好像讲的太远了,回来回来。。。。 图层配置如下:


下面详细说明,各个选项的配置:

Windows Position栏设置显示窗口的位置大小,此处设置图层1,图层2大小为512x300,(0,0)位置开始。显存显示显示格式为RGB565。

Alpha constant for blending相当于设置层的透明度,0xff表示透明度为100%,0x00表示透明度为0(不显示)。其中layer0为底层,layer1为顶层,顶层如果有显示,就会遮盖底层,即如果把顶层的透明度设置为0xff,那就可以100%遮盖底层,此处设置为0x7F,两个图层叠加显示。(有用过photoshop之类的软件,应该比较容易理解层的概念)
其它实际也没什么好说的,注意一下分配显存的地址空间,此处使用SDRAM作为显存,由上一章可知Open746I-C开发板SDRAM接到区域2,起始地址为0xD000 0000。由于有两个层,注意内存地址间要有一定的间距。BackGroun Color为背景颜色,此处为默认黑色。注意:LDTC输出管脚设置GPIO Settings需要把所有LCD管脚的最大输出速度(Maximum output speed)设置为高速(High),否则会导致LCD刷新不过来等问题。

在CORTEX_M7 Configuration中,把CPU ICache和CPU DCache使能,其它保持默认。使用ICache和DCache可以大幅度提高程序的运行速度。

在DMA2里配置一个从内存到内存的DMA通道,其它保持默认

在Pin Configuration里,把背光默认设置为输出低电平,否则屏幕背光不亮不显示图像。

生成报告以及初始化代码,编译程序。若程序没有出错,下载这个两个头文件添加进工程目录Inc文件夹里面。


这个两头文件保存的是图像信息,是通过STemWin中的BmpCvt.exe软件将图片转换C语言的。此软件可在固件库里面找到:STM32Cube_FW_F7_V1.3.0MiddlewaresSTSTemWinSoftware

下面简单讲解一下如何将图片转为C语言。以.jpg?imageView2/2/w/550格式的图片为例。先用Windows自带的画图工具打开图片,调整图片的像素大小,然后另存为BMP 图片。

用BmpCvt.exe软件打开BMP图片,选择File->Save as ... 另存为,保存类型选择位图。

图片格式选择为RGB565格式,红蓝交换。

添加头文件,将刚才的图片包含进工程


1/* USER CODE BEGIN Includes */
2#include "stm32746g_sdram.h"
3#include "image1.h"
4#include "image2.h"
5/* USER CODE END Includes */


再main函数里面,while循环前面添加应用程序。程序中先初始化SDRAM,然后通过DMA2D将要显示的图片传输到显存中,图片的大小为512 x 300。上面的设置Layer 0显存起始地址为0xD0000 0000,Layer 1显存起始地址为0xD0100 0000。

01/* USER CODE BEGIN 2 */
02printf("rn LDTC DMA2D example !!!rn");
03/* Program the SDRAM external device */
04/*##-1- Configure the SDRAM device #########################################*/
05/* SDRAM device configuration */
06BSP_SDRAM_Init();
07
08/*##-2- Start DMA2D transfer ###############################################*/ 
09if(HAL_DMA2D_Start_IT(&hdma2d, (uint32_t)image1, (uint32_t)0xD0000000, 512, 300) != HAL_OK)  //(uint32_t)SDRAM_DEVICE_ADDR
10{
11
12HAL_Delay(500);
13
14if(HAL_DMA2D_Start_IT(&hdma2d, (uint32_t)image2, (uint32_t)0xD0100000, 512, 300) != HAL_OK)  //(uint32_t)SDRAM_DEVICE_ADDR
15{
16
17/* USER CODE END 2 */


编译程序并下载到开发板中,接上屏幕,可以看到右上角显示两张图片层叠。上面显示的为静态图片,下载添加程序可以让图片动起来。在while循环中添加如下程序。

01/* USER CODE BEGIN WHILE */
02while (1)
03{
04/* USER CODE END WHILE */
05
06/* USER CODE BEGIN 3 */
07    for (tobuttom = 1; tobuttom < 181; tobuttom++)
08    {
09        /* move the picture */
10        /* reconfigure the layer1 position */
11        HAL_LTDC_SetWindowPosition(&hltdc, (tobuttom*4), 100, 0);
12        /* reconfigure the layer2 position */
13        HAL_LTDC_SetWindowPosition(&hltdc, (720 - (tobuttom*4)), 200, 1);
14        HAL_Delay(50);
15    }
16    HAL_Delay(500);
17    for (totop = 1; totop < 181; totop++)
18    {
19        /* move the picture */
20        /* reconfigure the layer1 position */
21        HAL_LTDC_SetWindowPosition(&hltdc, (720 - (totop*4)), 100, 0);
22        /* reconfigure the layer2 position */
23        HAL_LTDC_SetWindowPosition(&hltdc, (totop*4), 200, 1);
24        HAL_Delay(50);
25    }
26    HAL_Delay(500);
27}
28/* USER CODE END 3 */



程序中调用HAL_LTDC_SetWindowPosition函数设置图片显示的位置。通过不断这是图片的显示位置可以让图片实现左右移动的效果。最后添加声明变量。

1/* USER CODE BEGIN 1 */
2uint32_t tobuttom = 0;
3uint32_t totop = 0;
4/* USER CODE END 1 */

重新编译程序并下载到开发板中,可以看到两个张图片左右移动,并且可以层叠显示。


四、显示字符程序           

复制刚才的的工程修改文件夹名。打开工程重新配置LDTC,显示窗口设置为1024x600,单层显示。

生成报告以及初始化代码,编译程序。若程序没有出错,下载下面的应用程序解压并添加进工程中。

打开原来的工程目录,添加一个BSP和一个Fonts文件夹

BSP文件夹中包含sdram驱动文件和lcd驱动文件,Fonts文件夹中包含各种大小的字体。

将这两个目录中的路径添加到工程中,添加stm32746_lcd.c文件。

在stm32746g_lcd.h头文件中可以看到LCD的控制操作函数,包括显示字符,画图等操作。删除前面添加的应用程序,在main.c中添加头文件导入stm32746_lcd驱动文件。

1/* USER CODE BEGIN Includes */
2#include "stm32746g_sdram.h"
3#include "stm32746g_LCD.h"
4/* USER CODE END Includes */


在main函数中添加应用程序,程序首先初始化SDRAM,然后初始化LCD。设置单层显示,红色背景,蓝色字体,最后在屏幕上显示字符串。

01/* USER CODE BEGIN 2 */
02BSP_SDRAM_Init();  
03BSP_LCD_Init();
04
05BSP_LCD_SelectLayer(1);
06BSP_LCD_SetLayerVisible(1, DISABLE);
07
08/* Set Foreground Layer */
09BSP_LCD_SelectLayer(0);
10BSP_LCD_SetBackColor(LCD_COLOR_RED);
11BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
12BSP_LCD_Clear(LCD_COLOR_RED);
13
14BSP_LCD_SetFont(&Font24);
15BSP_LCD_DisplayStringAtLine(1, (uint8_t*)" WaveShare Open7XXI-C  Board");
16BSP_LCD_DisplayStringAtLine(3, (uint8_t*)" www.waveshare.com  ");
17BSP_LCD_DisplayStringAtLine(4, (uint8_t*)" www.waveshare.net  ");
18BSP_LCD_DisplayStringAtLine(6, (uint8_t*)" 7inch 1024x600 LCD");
19/* USER CODE END 2 */



编译程序并下载到开发板上可以看到 LCD屏幕上显示对应的字符。五、滚动显示字符。

复制刚才的的工程修改文件夹名,打开工程keil 工程。    


下载上面应用程序解压到工程目录下,Log包含下面三个文件,把lcd_log.c添加到工程中,并添加log文件夹路径到工程中。

在main文件中添加 lcd_log.h头文件。

1/* USER CODE BEGIN Includes */
2#include "stm32746g_sdram.h"
3#include "stm32746g_LCD.h"
4#include "lcd_log.h"
5/* USER CODE END Includes */

打开 lcd_log_comf.h头文件可以看到如下代码。修改宏定义可以设置字体大小和颜色以及显示行数。

代码中以及重构了fputc函数,所以使用printf函数输出时,实际上是输出到显示屏上显示,不在是通过串口发送到电脑上显示。故把usart.c中的函数重构注释删掉或者注释掉。

01/* USER CODE BEGIN 1 */
02//#ifdef __GNUC__
03//  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
04//     set to 'Yes') calls __io_putchar() */
05//  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
06//#else
07//  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
08//#endif /* __GNUC__ */
09///**
10//  * @brief  Retargets the C library printf function to the USART.
11//  * @param  None
12//  * @retval None
13//  */
14//PUTCHAR_PROTOTYPE
15//{
16//  /* Place your implementation of fputc here */
17//  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
18//  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
19
20//  return ch;
21//}
22/* USER CODE END 1 */

在main函数中添加以下应用程序,程序先初始化SDRAM以及LCD,设置单层显示。

01/* USER CODE BEGIN 2 */
02/* Initialize the SDRAM */
03BSP_SDRAM_Init();
04/* Initialize the LCD */ 
05BSP_LCD_Init();
06
07BSP_LCD_SetLayerVisible(1, DISABLE);
08BSP_LCD_SelectLayer(0);
09
10/* Initialize LCD Log module */
11LCD_LOG_Init();
12
13/* Show Header and Footer texts */
14LCD_LOG_SetHeader((uint8_t *)"Waveshare Electronics");
15LCD_LOG_SetFooter((uint8_t *)"WaveShare Open7XXI-C board");
16/* USER CODE END 2 */
17
18/* Infinite loop */
19/* USER CODE BEGIN WHILE */
20while (1)
21{
22/* USER CODE END WHILE */
23
24/* USER CODE BEGIN 3 */
25    LCD_UsrLog ("  Hello World ... %dn",i);
26    LCD_ErrLog ("  Hello World ... %dn",i);
27    LCD_DbgLog ("  Hello World ... %dn",i++);
28    HAL_Delay(1000);
29}
30/* USER CODE END 3 */

最后添加变量 i。

1/* USER CODE BEGIN 1 */
2  int i =0;
3/* USER CODE END 1 */

编译程序并下载到开发板上可以看到 LCD屏幕滚动显示字符。

推荐阅读

史海拾趣

AMRI Enterprise Co Ltd公司的发展小趣事

面对国内市场的饱和竞争,AMRI Enterprise Co Ltd积极实施国际化战略,拓展海外市场。公司通过参加国际电子展会、建立海外销售渠道等方式,不断提升品牌知名度和产品影响力。同时,AMRI还针对不同国家和地区的市场需求,调整产品策略,提供定制化的解决方案。这一战略的实施,使得AMRI的产品成功打入多个国际市场,实现了业务的快速增长。

Gems Sensors & Controls公司的发展小趣事

随着技术的不断积累和市场的不断拓展,Gems Sensors & Controls公司成功加盟了全球知名的世界500强企业丹纳赫集团。这一举措不仅为公司带来了更多的资源和支持,也加速了Gems的全球化布局。如今,Gems的生产基地遍布北美、欧洲和亚洲,并在全球范围内设立了销售、设计和服务办事处,能够为客户提供更加全面和便捷的服务。

Gumstix公司的发展小趣事
检查压敏元件是否老化或受到污染,必要时更换新的压敏元件。同时,也可以考虑调整电路参数以提高灵敏度。
AXTAL公司的发展小趣事

自成立以来,AXTAL公司一直致力于提升产品的技术和品质。公司凭借完善的质量管理体系(QMS)确保产品的高质量和可靠性。在产品设计阶段,AXTAL应用了受控设计流程,并在客户应用程序中进行了大量验证步骤和最终验证。同时,公司还拥有记录良好的制造流程过程控制系统,通过大量的在线测试、检查和筛选,确保每一件产品都符合高标准的质量要求。

常州能动(ENDRIVE)公司的发展小趣事

随着环保意识的日益增强,常州能动积极响应国家政策,加大环保投入。公司引进了先进的环保设备和技术,对生产过程中的废弃物进行无害化处理。同时,公司还注重节能减排和资源循环利用,推动公司向绿色、低碳、可持续发展的方向迈进。这些努力不仅提升了公司的社会形象,也为公司的长远发展打下了坚实基础。

Frequency Management International公司的发展小趣事

作为一家有社会责任感的企业,FMI深知可持续发展和环保的重要性。公司积极响应国家环保政策,采用环保材料和生产工艺,减少对环境的影响。同时,FMI还致力于节能减排和资源循环利用等方面的研究和实践工作。这些努力不仅体现了FMI对环境保护的承诺和责任感,也为公司的长期发展奠定了坚实的基础。

综上所述,Frequency Management International公司凭借其创立与早期发展、技术创新与产品线拓展、市场拓展与国际化战略、质量管理与客户服务以及可持续发展与环保责任等方面的努力和发展历程,在电子行业中取得了显著的成就和地位。

问答坊 | AI 解惑

Latch 与 FF

这里先转载网上的几个帖子,让大家对 Latch 和FF有个认识。 latch和flip-flop都是时序逻辑,区别为:latch同其所有的输入信号相关,当输入信号变化时latch就变化,没有时钟端;flip-flop受时钟控制,只有在时钟触发时才采样当前的输入,产生输出。 ...…

查看全部问答>

中国安全防范产品的山寨化是福还是祸?

今年的两会即将召开之际,让我想起去年此时火速蹿红的“山寨”一词。“山寨”一词在2009年3月就被带上了两会,并且再度火了一把, 与“躲猫猫”一起位列热门关键词前二位。     山寨机概念首先出现在IT行业。自从2001年始“联发科”先后在 ...…

查看全部问答>

急切求助,开关电源烧上mos管

现象描述  1 用万用表测量VCC_1V2电源对地阻抗5欧左右。 2 刚上电mos管Q5就被烧掉。 3 断开R272,在R272的第2pin和地之间并一个电容,上电不会烧mos管,但是输出电压为3V。 4  Vous+通过飞线链接到电源输出端 输出电压稳定 ...…

查看全部问答>

FPGA电源芯片的选择

FPGA电源芯片的选择:         FAPGA 电源芯片一般分为内核电源和IO电源。 怎样选择电源芯片的功耗大小这是一门学问。 电源芯片的大小跟所使用的逻辑门容量和速度都有关。速度越快,功耗需求越大。逻辑容量越大 ...…

查看全部问答>

WINCE的内存没有被收回

我写了一个在WINCE(5.0)下运行MFC程序,里面我用new分配了一个空间,然后用delete 释放,可是内存并没有被收回(通过看控制面板里的系统属性,总共内存数和使用内存数)?  代码如下: vector vct5();         fo ...…

查看全部问答>

关于NAND启动Stepping Stone简单问题

三星的2416 有8K的Stepping Stone,2440有4K的Stepping Stone 目前我的EBOOT和NBOOT代码都准备好了。读写NAND FLASH都可以了。 现在我要从NAND启动,2416 NAND flash的前8K会自动复制到Stepping Stone里面去,就是在烧写过程中需要做ECC校验吗? ...…

查看全部问答>

如何制作BFM字体

如何才能制作出bmf字体,出在我只找到制作.c的字体工具,请你指教,谢谢!…

查看全部问答>

cepc下无法识别u盘!!!

我用PB5.0定制了一个系统,其中添加了组件: devices drivers\\usb host\\USB Host Controllers core os\\core os services\\usb host support\\USB Storage Class Driver core os\\file system and data store\\storage manager\\FAT File Syst ...…

查看全部问答>

【连载】【ALIENTEK MiniSTM32 开发板】STM32不完全手册--外部中断实验(实验四)

ALIENTEK开发板购买地址:http://shop62103354.taobao.com/ [ 本帖最后由 正点原子 于 2010-8-30 09:35 编辑 ]…

查看全部问答>

国赛结束了最想干什么

本帖最后由 paulhyde 于 2014-9-15 03:03 编辑    …

查看全部问答>