实验目的

  • 利用粤嵌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 ab = 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