实验目的

  • 利用粤嵌LinuxGEC6818开发板实现电子相册,要求如下:
    • 实验操作必须在Linux操作系统下完成
    • 源代码模块化设计
    • 实现水平或者垂直滑动切换图片

实验步骤

  • 因为操作需要在Linux下运行,所以首先安装VM虚拟机,此次安装的系统是Ubuntu18,这里不再进行介绍。
  • 涉及ARM编译,gcc编译的可执行文件,它只适合在X86架构上运行的linux上运行,并不能在ARM架构上的linux上运行。所以需要采用交叉开发。
  • 交叉开发
    • 有些产品(或设备)并不适合编辑编译代码。比如:51单片机,STM32…
      把编辑编译和运行分开,我们在X86的机器上(电脑)编辑编译代码,再把可执行文件传输到产品(或设备)上运行。
    • gcc编译的可执行文件,它只适合在X86架构上运行的linux上运行。并不能在ARM架构上的linux上运行。
      arm-linux-gcc编译的文件只适合在arm架构上的linux上运行。
  • 因为需要让屏幕显示内容,必须先对屏幕进行坏点测试,排除屏幕坏点问题,全屏显示蓝色,程序如下:
#include "lcd.h"

/*宏定义*/
#define BLUE 0x0000FF
#define LCD_PATH "/dev/fb0"

//全局变量
int fd = -1;
int *plcd = NULL;

//lcd初始化
int lcd_init()
{
    //1.打开屏幕文件
    fd = open(LCD_PATH,O_RDWR);//可读可写打开
    if(fd<0)
    {
        perror("open fail");
        return -1;
    }
    //2.映射 
    plcd = mmap(NULL, 
                800*480*4, 
                PROT_READ | PROT_WRITE, 
                MAP_SHARED,
                fd,
                0);
    if(plcd == MAP_FAILED)
    {
        perror("MAP fail");
        return -1;
    }
    return 0;
}


//LCD关闭
void lcd_close()
{
    munmap(plcd,800*480*4);
    close(fd);
}

//指定的点上显示指定的颜色
void display_point(int x,int y,int color)  //x为高,y为宽
{
    if(x >= 0 && x < 800 && y >= 0 && y < 480)
    {
        *(plcd + 800 * y + x) = color;
    }
}

//LCD测试
void lcd_test()
{
    lcd_init();

    int x,y;
    for(y=0;y<480;y++)//遍历每一行
    {
        for(x=0;x<800;x++)//遍历每一列
        {
            display_point(x,y,BLUE);
        }
    }
    // //写数据
    // write(fd,color,480*800*4);

    lcd_close(fd);
}

  • 确认屏幕没有坏点后,可以将图片写入屏幕中,让屏幕显示图片,在主函数中调用show_bmp(char * filename,int x0,int y0),即可显示让屏幕图片,filename为文件名,x0跟y0是屏幕显示的起始坐标,左上角为起始位(0,0)。程序如下:
#include "Bmp.h"
#include "lcd.h"

//显示图片
int show_bmp(char * filename,int x0,int y0)
{


    //1.打开bmp图片
    int fd = open(filename,O_RDWR);
    //判断读入图片是否错误
    if (-1 == fd)
    {
        printf("Open %s Fail!\n",filename);
        perror("--->");
        return -1;
    }

    //2.判断到底是不是一张bmp图片
	unsigned char buf[4];
	read(fd,buf,2);
	if(buf[0]!= 0x42 || buf[1]!= 0x4d)//若果不是B M 的ASCII码
	{
		printf("NOT BMP\n");
		goto ERROR_END;
	}

    //3.读取数据
    
    int width,height;
    short depth;
	lseek(fd,0x12,SEEK_SET);
	read(fd,buf,4);
	
	width=(buf[3]<<24)|
		  (buf[2]<<16)|
		  (buf[1]<<8)|
		  (buf[0]);

	lseek(fd,0x16,SEEK_SET);
	read(fd,buf,4);
	
	height=(buf[3]<<24)|
		  (buf[2]<<16)|
		  (buf[1]<<8)|
		  (buf[0]);

	lseek(fd,0x1c,SEEK_SET);
	read(fd,buf,2);
	
	depth=(buf[1]<<8)|
		  (buf[0]);

	//只支持色深为24和32的
	if(!(depth == 24 || depth == 32))
	{
		printf("NOT Support!\n");
		goto ERROR_END;
	}
	printf("%s:%d*%d depth=%d\n",filename,width,height,depth);

	//4.获取像素数组
	int line_valid_bytes = abs(width)*depth/8;//一行有效字节数
	int line_bytes;//一行总字节数=有效字节数+赖子数 
	int laizi = 0;
	
	if(line_valid_bytes%4)
	{
		laizi = 4-line_valid_bytes%4;
	}
	
	line_bytes = line_valid_bytes + laizi;
	
	int total_bytes = line_bytes*abs(height);//整个像素数组的大小


	//开辟一块动态内存
	unsigned char *piexl = (unsigned char *)malloc(total_bytes);    //用完后需要释放内存

	lseek(fd,54,SEEK_SET);
	read(fd,piexl,total_bytes);

    
	unsigned char a,r,g,b;
	int color;
	int i = 0;

	int x,y;
	for(y=0;y<abs(height);y++)
	{
		for(x=0;x<abs(width);x++)
		{
			//a r g b 0xargb 小端模式  b g r a
			b = piexl[i++];
			g = piexl[i++];
			r = piexl[i++];
			if(depth == 32)
			{
				a = piexl[i++];
			}
			else
			{
				a = 0;//不透明
			}
			color=(a<<24)|(r<<16)|(g<<8)|(b);

			//在屏幕对应的位置显示
			display_point(width>0?x0+x:x0+abs(width)-x-1, 
							height>0?y0+abs(height)-y-1:y0+y,
							color);
		}
		//每一行的末尾 有可能填充几个赖子
		i += laizi;
	}

    //释放内存
    free(piexl);
    //关闭显示
	close(fd);
    ERROR_END:
		close(fd);
		return -2;
}



//图片数组
// char * bmpname[] = {"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp","6.bmp"};

//循环显示图片
void bmp_player(int i)
{
//     int i = 0;
//     while (1)
//     {
        //循环显示
        // show_bmp(bmpname[i],0,0);

    //     延时5s
        // sleep(5);
        // i++;
        // if (6 == i)
        // {
        //     i = 0;
        // }
        
    // }
    
}
  • 接下来获取手指触摸触摸坐标,程序如下:
#include "touch.h"
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4


//宏定义
//设备文件
#define TOUCH_PATH "/dev/input/event0"

int GetDirection()
{
    //1.打开触摸屏 
    lcd_init();
    
    int fd = open(TOUCH_PATH,O_RDONLY);//只读打开
    if(fd<0)
    {
        perror("open fail");
        return 0;
    }

    int x_start=-1,y_start=-1;	//坐标的初值
    int x_end = -1,y_end = -1;    //坐标终点
    
    struct input_event ev;
    while(1)
    {
        //2.不停地从文件中读取数据
        read(fd, &ev, sizeof(struct input_event));
        
        //3.解析数据
        if(ev.type == EV_ABS)   //触摸事件 
        {
            if(ev.code == ABS_X)
            {
                if (-1 == x_start)        //x轴
                {
                    x_start = ev.value;	//起点
                }
                x_end = ev.value;      //终点
                
            }
            if(ev.code == ABS_Y)		//y轴
            {
                if (-1 == y_start)
                {
                    y_start = ev.value;
                }
                y_end = ev.value;      //终点
                
            }
            if(ev.code ==ABS_PRESSURE && ev.value == 0)
            {
                if(x_start != -1 && y_start != -1)
                {
                    break;
                }
            }
        }
        
        if(ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0)   //按键事件
        {
            if(x_start != -1 && y_start != -1)
            {
                break;
            }
        }

        if (abs(x_end - x_start) > (y_end - y_start))
        {
            if (x_end - x_start > 0)
            {
                return 4;
            }
            else
            {
                return 3;
            }
            
        }
        if (abs(x_end - x_start) < (y_end - y_start))
        {
            if (y_end - y_start > 0)
            {
                return 2;
            }
            else
            {
                return 1;
            }
            
        }
        

    }
    
    //打印坐标
    printf("%d , %d\n", x_end, y_start);
    
    //4.关闭触摸屏
    lcd_close();


}

  • 获得手指滑动坐标后,终点坐标减去手指滑动起始坐标,即可判断手指是左滑、右滑还是上滑、下滑,随即再做下切换的图片的指令即可,程序如下:
#include "lcd.h"
#include"Bmp.h"
#include "touch.h"


char * bmpname[] = {"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp","6.bmp"};

//主函数
int main(int argc, char const *argv[])
{
    int rs = 0;
    int i = 0;
    //打开屏幕
    lcd_init();
    
    //单独显示一张图片
    // show_bmp("1.bmp",0,0);
    
    //触摸
    while (1)
    {
        //  bmp_player(i);
        rs = GetDirection();
        printf("%d\n",rs);
        if (1 == rs || 3 == rs)
        {
            if (5 == i)
            {
                i = 0;
            }
            else
                ++i;
            show_bmp(bmpname[i],0,0);
            // bmp_player(i);
        }
        // show_bmp(bmpname[3],0,0);
        else if (2 == rs || 4 == rs)
        {
            if (0 == i)
            {
                i = 5;
            }
            else
                --i;
            // bmp_player(i);
            show_bmp(bmpname[i],0,0);
        }
    }
    
    
    
    //循环显示
    // bmp_player();

    //关闭屏幕
    lcd_close();
    
    
    return 0;
}


总结

  • 整个工程可以正常运行,已上板测试验证,现实中图片是很清楚的,只是网站限制了只能上传5M以内,压缩了画质。GIF如下:水平切换图片
  • 垂直切换图片
  • 垂直切换图片
  • 想要整个工程的可以到以下地方下载,有积分的小伙伴CSDN直接下载即可,没有积分的可以网盘下载。
  • https://download.csdn.net/download/jianfeng_520/60963967
  • 百度网盘:链接:https://pan.baidu.com/s/1_jH3jKXNjSRvEnf1itvvnA
    提取码:iejv
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐