查看: 2993|回复: 0

17..STM32F469I--- LCD硬件加速应用

[复制链接]
  • TA的每日心情
    难过
    2021-2-27 22:16
  • 签到天数: 1568 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2018-1-12 14:48:59 | 显示全部楼层 |阅读模式
    分享到:
    【STM32F469I试用】+ LCD硬件加速应用【转】

    关于STM32F469I-DISCO,这篇帖子只介绍了使用液晶的BSP库,但是这个不是重点,重点是后面的福利——自己之前写的两个有用的模块:简单CUI(命令用户接口)模块,基于超级终端的外置键盘。本帖就分3个部分来讲
    1. 使用液晶的BSP库
    STM32F469I-DISCO板的一大特点就是使用了一块高分屏,这篇帖子就来研究一下使用HAL库和BSP库来使用液晶屏的方法。
    1.1 DSI模式简介
           STM32F469I-DISCO的液晶控制模块LTDC是和DSI模块一起使用的,DSI有两种模式CommandMode和Video mode
    DSI(Video Mode)视频模式.
    这种工作模式与传统RGB接口相似,主机需要持续刷新显示器。由于不使用专用的数据信号传输同步信息,控制信号和RGB数据是以报文的形式通过MIPI总线传输的。因为主机需要定期刷新显示器,显示器就不需要帧缓冲器。
    DCS(Command mode)命令模式
    MIPI总线控制器使用显示命令报文来向显示器发送像素数据流。显示器应该有一个全帧长的帧缓冲器来存储所有的像素数据。一旦数据被放在显示器的帧缓冲器中,定时控制器就从帧缓冲器中取出数据,并自动把它们显示在屏幕上。MIPI总线控制器不需要定期刷新显示器。
    STM32F469使用命令模式时可以手动刷新显示器,也可以自动刷新(消除TearingEffect模式,TE)
    如果想了解更多关于这两种模式的内容,可以看这个博客
    见附件文档
    如果想了解更多关于TE的内容,看下面这个博客
    见附件文档
           在写这篇帖子的过程中对两种方式都进行了测试,发现Command Mode下在刷屏时屏幕上会雪花出现(刷完屏后显示一切正常),理论上来讲,在刷新显存之前,显存RAM内容的改变并不会表现在屏幕上,暂时没有精力去找原因了,帖子的工程中使用了Video Mode

    1.2 工程建立
    接下来开始建立工程,这个工程是从LCD_DSI_VideoMode_DoubleBuffering工程修改而来的
    工程需要的库文件:

    1.jpg

    BSP的LCD库函数需要板载SDRAM,因为显存存放在从地址LCD_FB_START_ADDRESS(0xC0000000)开始的内存中,而这个地址就是SDRAM的起始地址
    Main函数:
           Main函数开头的初始化都是直接调用库函数完成,初始化完成之后,就可以使用LCD的库函数了,包括了画点,画线,画图填充,写字符等函数。

    2.jpg

    2. 简易CUI模块
           PC上的cmd窗口就是CUI的一个例子,相对于GUI,它的实现简单,占用资源少,非常适合嵌入式,本例是一个简单的CUI演示,它有两个特点:软件光标和屏幕卷动。但是屏幕缓冲区只有一屏的内容,因此不能回看。

    2.1 CUI界面配置
           CUI界面只支持字符显示,可以显示固定行数和列数的字符,并且字符只能顺序写入,不能设定光标的位置。
    通过配置文件可以设置界面的行数,列数,字体样式,背景色和前景色。

    3.jpg

    LCD_WIDTH,LCD_HEIGHT:只用来限制显示CUI界面的大小,不必等于真实液晶宽和高
    CUI_FONT:font.c文件有几种字体可选,CUI_WIDTH和CUI_HEIGHT要和所选的字体一致。也可以添加其他字体,字体取模的格式为:纵向取模,从上到下(MSb在上),从左到右,不足8bit的LSb补0
    CURSOR_HEIGHT:光标使用横向的格式,高度从1到FONT_HEIGHT都可以
    CURSOR_BLINK_RATE:光标闪烁频率,这里设置的是1Hz,这个要求定时器中断周期为1ms
    CUI_LINE,CUI_ROW:CUI显示的行数和列数,这两个值设定之后最好保证整个CUI界面小于LCD_WIDTH和LCD_HEIGHT所限定的区域,否则一部分字符会显示不出来

    2.2 移植准备
    移植CUI模块只要2个外部函数,Lcd_SetPixel()和Lcd_GetPixel(),在程序中是要用这两个函数实现画字符的功能,因此可以结合LCD控制器的特点进行优化。
    另外,还需要将Cui_TimerProc()函数在1ms定时器中断程序中调用,用来实现软件光标。
    2.3应用接口:

    4.jpg

    接口函数只有4个,Cui_Putc和Cui_Puts可以像C标准库里的那样使用,重定位之后可以直接printf了
    2.4 基于STM32F469I-DISCO的优化
    使用上面未优化的方法,移植到STM32F469I-DISCO,全屏幕时,屏幕卷动的速度很慢,因为屏幕卷动一次需要将当前屏幕整体往上移动一行字符的高度,未优化时,是直接重新给整个屏幕填充字符,一个字符一个字符画出来,当然消耗时间,如果有方法将整个屏幕整体拷贝,这个过程将提速N倍。MCU接口的LCD的驱动IC一般支持窗口函数,这种使用软件去描点就类似于这种拷贝了,但是RGB接口的显存都是线性的,无法实现这种方法,而STM32F469的硬件加速器正是为了这种拷贝而设计的,假如有一组图片数据,颜色格式为ARGB8888,但是图片大小是100x100的,现在要将图片拷贝到屏幕的(320,240)的位置,如果使用软件拷贝就要对每一行数据计算起始RAM地址,拷贝一行,接着计算下一行的起始RAM地址,拷贝下一行…,并且图片数据的格式和显存中的格式还不一样,拷贝之前还要先转换一下,但是使用DMA2D硬件加速器,这个过程变得非常简单迅速,设置一下图片数据的起始地址(源),在显存中存放的起始地址(目的),图片的颜色格式,图片的宽和高,启动DMA2D,然后等着硬件拷贝完成就行了。
           经过上面的分析,就知道了该怎样优化了,可以有两种方法优化:
    优化1:优化画字符的函数,这种方法对CUI的软件改变最小,但是要求取字模时,一个点要用4个字节表示,而不再是1bit,字模体积最大为原来的32倍,虽说STM32F469的Flash有2M,还有16M的QSPI,也不能这么任性,关键是如果屏幕颜色数据改变了,字模岂不是要随着改变,所以这个优化先排除掉
    优化2:在终端中输入字符时,只要当前屏幕未满,显示速度都是飞快的,毕竟只显示一个字符,但是如果是上面这种情况,那么,整个屏幕都要上移一行,未优化的方法都是重新写满屏数据,这个过程比较慢,但是如果能将当前屏幕从第二行开始拷贝到从第一行开始,再将最后一行清除,那么就相当于把整屏往上移动了一行,这就是这种优化的思想;
        遗憾的是,并没有发现可以将屏幕显存的一部分拷贝到另外一个位置的方法,例程中使用DMA2D的拷贝只是将一个图片数据拷贝到屏幕的某个位置,如果只拷贝图片的一部分,就不知道该怎么处理了,所以只能绕个路,每次拷贝一行像素,如果CUI界面占用了整个屏幕倒是可以整个拷贝。这种方法其实使用普通的DMA也可实现。
    注1:后来实际测试了一下普通的DMA,发现速度非常慢,显示效果还不如不用优化,也许是我没配置好,对这个结果不满意的坛友可以研究一下,看是不是可以更快。另外实测DMA从SDRAM拷贝到SDRAM所用时间大约是Flash到RAM时间的4~5倍。
           附件工程中提供了未优化和用DMA2D优化这两种方法,可以通过命令行启动或关闭加速,对比一下效果吧。

    注2:调试程序时发现BSP库中关于BSP_LCD_ReadPixel()函数有一处错误:

    5.jpg

    红圈中的2应该改为4,ARGB格式一个点占4个字节,不是两个

    附件3_STM32F469-DISCO_CUI 超级终端外置键盘.pdf (615.2 KB, 下载次数: 0, 售价: 2 与非币)
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-20 07:36 , Processed in 0.155538 second(s), 24 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.