利用粤嵌LinuxGEC6818开发板实现电子相册
粤嵌LinuxGEC6818开发板实现电子相册
·
实验目的
- 利用粤嵌LinuxGEC6818开发板实现电子相册,要求如下:
- 实验操作必须在Linux操作系统下完成
- 源代码模块化设计
- 实现水平或者垂直滑动切换图片
实验步骤
- 因为操作需要在Linux下运行,所以首先安装VM虚拟机,此次安装的系统是Ubuntu18,这里不再进行介绍。
- 涉及ARM编译,gcc编译的可执行文件,它只适合在X86架构上运行的linux上运行,并不能在ARM架构上的linux上运行。所以需要采用交叉开发。
-
交叉开发
- 有些产品(或设备)并不适合编辑编译代码。比如:51单片机,STM32…
把编辑编译和运行分开,我们在X86的机器上(电脑)编辑编译代码,再把可执行文件传输到产品(或设备)上运行。 - gcc编译的可执行文件,它只适合在X86架构上运行的linux上运行。并不能在ARM架构上的linux上运行。
arm-linux-gcc编译的文件只适合在arm架构上的linux上运行。
- 有些产品(或设备)并不适合编辑编译代码。比如:51单片机,STM32…
- 因为需要让屏幕显示内容,必须先对屏幕进行坏点测试,排除屏幕坏点问题,全屏显示蓝色,程序如下:
#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
更多推荐
已为社区贡献1条内容
所有评论(0)