STM32 ILI9341驱动TFTLCD屏(五)LCD滚动显示

接口/总线/驱动

1125人已加入

描述

下面分别在LCD上实现全屏滚动,单区域滚动,双区域滚动。

1.全屏滚动

全屏滚动时,先把图片写入显存,不需要进行行列设置,因为初始化ILI9341完成后默认为全屏操作。设定滚动范围,再依次把滚动区的每一行作为顶端固定区域下的第一行,加上稍微的延时,就能实现滚动效果了。

#include "stm32f4xx.h"
#include "core_cm4.h"
#include "delay.h"
#include "ili9341.h"
#include "0.h"


int main()
{
  u16 i = 0;
  ILI9341_Init();          //ILI9341初始化
  ILI9341_WriteMemory((u16 *)gImage_0,240*320);//全屏写入图片

  ILI9341_VertScrollDef(0,320,0);     //设定垂直滚动范围

  while(1)
  {
    for(i=0;i< 320;i++)
    {
      ILI9341_VertScrollStartAdd(i);//把滚动区域第i行作为顶端固定区域下的第一行
      Delay_ms(20);                  //20ms延时,速度太快人眼识别不了
    }
  }
}

通过修改延时时间可以改变滚动速度。

2.区域滚动

区域滚动只要全屏滚动的基础上先进行行列设置,修改图片尺寸,写入显存,其他操作和全屏显示一样。

#include "stm32f4xx.h"
#include "core_cm4.h"
#include "delay.h"
#include "ili9341.h"
#include "01.h"


int main()
{
  u16 i = 0;
  ILI9341_Init();          //ILI9341初始化

  ILI9341_SetColumnAddr(83,157); //列地址设置
  ILI9341_SetPageAddr(110,209); //页地址设置
  ILI9341_WriteMemory((u16 *)gImage_01,75*100);//区域写入图片

  ILI9341_VertScrollDef(110,100,110);     //设定垂直滚动范围

  while(1)
  {
    for(i=110;i< 210;i++)
    {
      ILI9341_VertScrollStartAdd(i);//把滚动区域第i行作为顶端固定区域下的第一行
      Delay_ms(10);                  //20ms延时,速度太快人眼识别不了
    }
  }
}

循环函数中,i代表顶端固定区域的第i行,所以不是图片的行数0-100,要根据行设置的行数110开始进行循环。

3.双区域滚动

双区域滚动还是行列设置先开两个窗,然后分别滚动两个窗口,但是这样会有个问题,就是两个图片滚动时一直会有原图片显示在初始位置。

LCD屏

通过调试,发现在执行“把滚动区域第i行作为顶端固定区域下的第一行”时,另一张图片也会跟着把滚动区域第i行作为顶端固定区域下的第一行,但是图片那样已经超过了另一张图片的窗口范围,所以图片显示在一开始写入时的位置,这样就达不到想要的显示效果。由此可知通过硬件是没办法直接滚动两个窗口的。

所以这里需要另外编写算法来实现双区域滚动。调用滚动函数时会影响其他图片的位置,所以多区域时就不考虑调用滚动函数了。只能通过在区域内重新写入图片,写入时不再像之前一样按顺序写入,而是按照需要滚动的行数,把原来图片下半部分先写入滚动后的前半部分,再把原来图片的上半部分写入滚动后的下半部分。

另外,为了函数的通用性,写入图片的宽度和高度不能设置为固定数字,可以通过Image2LCD生成的数据的数据头,其中第2-3位为图片的宽度,4-5位为图片的高度。生成的数据为字符型变量,要把这两个数据读出并强制转化为整型变量,方便使用。

LCD屏

具体算法封装如下

//LCD区域滚动一次
//x,y:起点位置
//img:图像
//dir:上到下(0)、下到上(1)
//height:滚动的行数
void LCD_ImageScroll(u16 x, u16 y,u8 *img,u8 dir,u16 height)
{
  u32 i = 0;

  //1. 开窗
  u16 w = 0,h= 0;
  w = *(u16 *)&img[2];//图片宽度
  h = *(u16 *)&img[4];//图片高度

  if(x+w >= 240 ||y+h >=320)//图片超过屏幕范围,退出
    return;

  ILI9341_SetColumnAddr(x,x+w-1);

  //2.根据方向,填充区域
  if(dir == 0)  //从上到下滚
  {
    ILI9341_SetPageAddr(y,y+height-1);
    ILI9341_WriteMemory((u16 *)&img[8+(h-height)*2*w],w*height);//将下半部分写在顶端
    ILI9341_SetPageAddr(y+height,y+h-1);
    ILI9341_WriteMemory((u16 *)&img[8],w*(h-height));            //将下半部分写在顶端
  }
  else if(dir == 1)  //从下往上滚
  {
    ILI9341_SetPageAddr(y,y+h-1-height);
    ILI9341_WriteMemory((u16 *)&img[8+height*2*w],w*(h-height));//将下半部分写在顶端
    ILI9341_SetPageAddr(y+h-height,y+h-1);
    ILI9341_WriteMemory((u16 *)&img[8],w*(height));              //将下半部分写在顶端
  }    
}

开窗时从起点开始,所以宽度和高度都要在头数据读出的图片宽度和高度上减1,否则显示时多了一行和一列,图片就会倾斜。

主文件如下

#include "stm32f4xx.h"
#include "core_cm4.h"
#include "delay.h"
#include "ili9341.h"
#include "00.h"
#include "01.h"


int main()
{
  u16 i = 0;
  u16 h1 = *(u16 *)&gImage_00[4];  //读出图片00高度
  u16 h2 = *(u16 *)&gImage_01[4];  //读出图片01高度
  ILI9341_Init();                  //ILI9341初始化

  while(1)
  {
    for(i=0;;i++)      
    {
      LCD_ImageScroll(9,10,(u16 *)gImage_00,0,i%h1);    //取余后小于h1,即在图片的高度范围内滚动
      LCD_ImageScroll(154,208,(u16 *)gImage_01,1,i%h2);  //取余后小于h2,即在图片的高度范围内滚动
    }
  }
}
```双区域图片滚动实现了,那么更多区域滚动不同尺寸的图片也就同样能够实现了。
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分