接口/总线/驱动
下面分别在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.双区域滚动
双区域滚动还是行列设置先开两个窗,然后分别滚动两个窗口,但是这样会有个问题,就是两个图片滚动时一直会有原图片显示在初始位置。
通过调试,发现在执行“把滚动区域第i行作为顶端固定区域下的第一行”时,另一张图片也会跟着把滚动区域第i行作为顶端固定区域下的第一行,但是图片那样已经超过了另一张图片的窗口范围,所以图片显示在一开始写入时的位置,这样就达不到想要的显示效果。由此可知通过硬件是没办法直接滚动两个窗口的。
所以这里需要另外编写算法来实现双区域滚动。调用滚动函数时会影响其他图片的位置,所以多区域时就不考虑调用滚动函数了。只能通过在区域内重新写入图片,写入时不再像之前一样按顺序写入,而是按照需要滚动的行数,把原来图片下半部分先写入滚动后的前半部分,再把原来图片的上半部分写入滚动后的下半部分。
另外,为了函数的通用性,写入图片的宽度和高度不能设置为固定数字,可以通过Image2LCD生成的数据的数据头,其中第2-3位为图片的宽度,4-5位为图片的高度。生成的数据为字符型变量,要把这两个数据读出并强制转化为整型变量,方便使用。
具体算法封装如下
//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,即在图片的高度范围内滚动
}
}
}
```双区域图片滚动实现了,那么更多区域滚动不同尺寸的图片也就同样能够实现了。
全部0条评论
快来发表一下你的评论吧 !