STM32F429discovery 显示初探

来源:互联网 发布:oracle linux download 编辑:程序博客网 时间:2024/05/16 07:58

         第一次写技术博客,记录我的学习历程,希望能和大家多交流,有些理解错误和不到位的地方,还恳请大家多多指导,谢谢!

        拿到ST的板子,从官网上下载了最新的cube库,以前用过STM32F407discovery,觉得ST的库还是挺好用的,但是这次更新的cube库,不太熟悉,感觉略微混乱。自己新建了一个工程,把新的库函数移植进去,算是一个demo,以后可以随时拷贝以及添加修改文件。

        以前没有写过屏幕的程序,所以首先打开官方的例程来看。...\STM32Cube_FW_F4_V1.1.0\Projects\STM32F429I-Discovery\Examples\LTDC\LTDC_Display_2Layers,这个工程实现的功能是在屏幕显示两张图片,上下各一张,然后让两张图片不停地相向运动。

        初始化函数是在main.c中定义的,初始化函数中,先是初始化ili9341(spi),然后设定屏幕的一些参数,再设定屏幕的两个图层,图层1在图层0上面,所以图层1在设置的时候Alpha设置的是200,貌似起一个有透明度的效果。图层初始化的时候,还涉及到设置窗口大小,frame buffer的地址(要显示的图片的地址),以及像素格式设置。关于这个例程,在初始化函数里面,没有找到初始化LTDC引脚的代码,所以怀疑他直接用spi来控制屏幕的,至于怎么去控制的,还不了解。

        之后看了看...\Examples\DMA2D里面的例程,感觉也差不多。在...\STM32F429I-Discovery\Applications\Display\LTDC_Paint里面找到一个工程,这是一个能在屏幕上画画并能将图像保存到优盘里的程序。当然现在先不用管USB以及触摸那一块,先把屏幕显示搞定了再说。试着把里面的代码移植到我的demo里面去。这个工程里的代码,使用的是stm32f429i_discovery_lcd.h里的函数来实现各个外设的初始化,BSP_LCD_Init()里,首先把设定LTDC的一些参数,其他例程的差不多,然后调用MspInit(),初始化LTDC的引脚,再调用BSP_SDRAM_Init(),初始化sdram和DMA2D。

        关于MspInit()这个函数,吐一下槽。在stm32f429i_discovery_lcd和stm32f429i_discovery_sdram两个文件里都有这个函数,不过都是在.c里声明的(应该算是一个private函数吧~),所以按理说lcd.c里的函数只能调用对应文件里的这个函数的。因为BSP_SDRAM_Init()(属于sdram.c)也会调用这个函数,所以就有问题了。在官方给的工程里面,lcd.c里的函数调用到了sdram.c里的这个函数,而sdram.c里的函数却调用lcd.c里的,不过还好能用。而我自己移植后的程序里,两次都调用到了sdram里的MspInit(),导致初始化失败。排查了各种设置,最后对比两个工程的执行过程,发现了这个问题。所以建议把两个文件里的这个函数名字都改一下~

        调用BSP_LCD_Init()的过程中,没有发现调用ili9341_Init(),所以更加觉得examples里面的屏幕是用spi来读写数据的~之后需要初始化图层了,由于lcd.h里只定义了BSP_LCD_LayerDefaultInit()来初始化图层,里面的一些参数设置与最开始建立的工程里的设置不一样,所以继续用main.c里自己写的函数初始化,把初始化函数里一开始的那些设置屏幕参数的代码删除掉,只保留图层设置的代码,然后又出问题了~最后找到的问题的原因,是因为一个结构体LtdcHandler,它是一个lcd.c里的全局变量,在BSP_LCD_Init()里初始化,在调用lcd.c里的其他函数时,都要用到这个结构体。在最开始建立的工程里的main.c里设置了一个名为LtdcHandle的全局变量给初始化使用,当我删除了初始化屏幕参数后,该结构体没有得到初始化,所以也就导致了图层初始化失败。最后我在lcd.c里新建一个函数来初始化图层,问题得到解决。

        lcd.c里的BSP_LCD_LayerDefaultInit()设置的像素格式是LTDC_PIXEL_FORMAT_ARGB8888,这导致了我显示RGB565格式的图片有问题,只能把这项参数改掉。通过BSP_LCD_SetLayerAddress(),可以显示想要显示的图片,但是这样用的话,该图层就没法画图和添加文字,要显示文字和实现画图功能,只能把该图层的地址设置为LCD_FRAME_BUFFER_LAYER1或者LCD_FRAME_BUFFER_LAYER0,这个是在main.h里定义的,

而LCD_FRAME_BUFFER又定义在stm32f429i_discovery_lcd.h

当图层的地址没有指向图片的时候,最好调用BSP_LCD_Clear()清除一下图层。

        由于文字和画图的代码里面的像素格式都是ARGB8888,最后还是只能把默认的像素格式换回去,然后自己在lcd.c里加了一个函数,void LTDC_SetPixelFormat(uint32_t Pixelformat, uint32_t LayerIdx),这个函数其实是调用stm32f4xx_hal_ltdc.c里的HAL_LTDC_SetPixelFormat(&LtdcHandler,Pixelformat,LayerIdx),涉及到了LtdcHandler这个结构体里的参数,所以在lcd.c里建立一个函数来实现像素格式的设定。

        因为液晶控制可以分为两层,两层有独立的数据空间,可以实现两层的混合或者独立显示,可以将图层1用来显示文字和画图,图层0用来显示图片,注意图片的数据格式一定要设置好哦~通过BSP_LCD_SetTransparency()可以设置图层的透明度;BSP_LCD_SetLayerVisible()可以设置图层是否显示;BSP_LCD_SetColorKeying()可以屏蔽掉设定的颜色......对于图层1,可以设置一个背景颜色,通过BSP_LCD_SetColorKeying()函数把这种颜色屏蔽掉,从而实现上面层清晰的显示文字和作图、下面层清晰显示图片--的功能~如果只是设置透明度,下面层始终会被上面层的颜色影响到,看到的图片也会很朦胧~~~

        我大概就学到了这么多,表述能力不怎么好,有些地方没有描述清楚,希望大家互相帮助,共同进步~有问题的地方,请不吝赐教~




0 0
原创粉丝点击