基于ARM的LCD(800*480)触摸屏实现音频、视频播放、图像显示功能 您所在的位置:网站首页 gec6818电子相册登录 基于ARM的LCD(800*480)触摸屏实现音频、视频播放、图像显示功能

基于ARM的LCD(800*480)触摸屏实现音频、视频播放、图像显示功能

2023-07-31 23:16| 来源: 网络整理| 查看: 265

更多资料请点击:我的目录 本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。

完整工程代码、素材请点击!

设计目标: ①实现用户注册、用户名、密码输入登录功能 ②实现bmp图片居中显示、左右切换、缩放 ③实现音乐(MP3)的播放、暂停、切歌、播放模式设定 ④实现视频(WMV)的播放、暂停、切换

后续更新: LCD显示屏加入百叶窗特效显示BMP图片

在这里插入图片描述

在这里插入图片描述

部分效果如下:

视频操作部分 视频操作部分

点击切换 点击切换

划动切换与缩小 划动切换与缩小

划动退出 划动退出

**注意!注意!**编译命令是用 arm-linux-gcc,而不是gcc的

主头文件(各部分通用的函数、定义) myhead.h

#include #include #include #include #include #include #include #include #include #include #include #include #ifndef MYHEAD_H #define MYHEAD_H struct input_event myevent; //定义输入子系统模型有关的结构体变量 int tsfd ; //触摸屏驱动 int dst; //显示屏驱动 int tx1 = 0,ty1 = 0,tx2 = 0,ty2 = 0; //触摸屏返回值 //重置触摸屏坐标返回值 void clear() { tx1 = 0, ty1 = 0,tx2 = 0,ty2 = 0; } //打开显示屏 int display_open() { dst = open("/dev/fb0",O_RDWR); //打开显示屏驱动 if(dst == -1) { printf("显示屏打开失败!\n"); return -1; } } //关闭显示屏 int display_close() { close(dst); } //打开触摸屏 int touch_open() { tsfd=open("/dev/input/event0",O_RDWR); //打开触摸屏驱动 if(tsfd==-1) { perror("打开触摸屏失败!\n"); return -1; } return 0; } //关闭触摸屏 int touch_close() { close(tsfd); return 0; } //显示任意位置大小缩放的BMP图片 bool showbmp(char *bmppath, int n) { int w = 0; int h = 0; int src = open(bmppath , O_RDWR); lseek(src, 18 ,SEEK_SET); //获取BMP图片的宽w信息 read(src, &w, 4); lseek(src, 22 ,SEEK_SET); //获取BMP图片的高h信息 read(src, &h, 4); char bmpbuf[w*h*3]; int lcdbuf[w*h]; int tempbuf[w*h]; int lcdbuf1[] = {0}; lseek(src, 54, SEEK_SET); //跳过BMP图片头信息字节 int rubbish = (4-(w*3)%4)%4; //BMP图片字节不能被4整除时,加入的垃圾字节数 for(int i = 0; i lcdbuf[i] = 0x00 tempbuf[(h-1-j)*w+i] = lcdbuf[j*w+i]; //BMP像素点上下反转 } } //内存映射 int *mmap_bmp = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, dst, 0); for(int i=0; i //任意位置(480-h/n)/2)、(800-w/n)/2)、缩小倍数n *(mmap_bmp+800*(((480-h/n)/2)+i)+((800-w/n)/2)+k) = tempbuf[j]; } } //解除内存映射 munmap(mmap_bmp, 800*480*4); close(src); } int get_xy(int *x1, int *y1,int *x2, int *y2) //获取触摸屏的坐标值 { int count = 0; while(1) { //读取触摸屏的坐标 read(tsfd,&myevent,sizeof(myevent)); if(myevent.type==EV_ABS && count == 0) //判断触摸屏事件 { if(myevent.code==ABS_X) //x坐标 { *x1 = ((myevent.value*800)/1024); //初次碰到触摸屏时的x值 } } if(myevent.type==EV_ABS && count == 0) //判断触摸屏事件 { if(myevent.code==ABS_Y) //y坐标 { *y1 = ((myevent.value*480)/600); //初次碰到触摸屏时的y值 count++; } } if(myevent.type==EV_ABS && count != 0) //判断触摸屏事件 { if(myevent.code==ABS_X) //x坐标 { *x2 = ((myevent.value*800)/1024); //离开触摸屏时的x值 } } if(myevent.type==EV_ABS && count != 0) //判断触摸屏事件 { if(myevent.code==ABS_Y) //y坐标 { *y2 = ((myevent.value*480)/600); //离开触摸屏时的y值 } } if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0) //保存松开前的x2,y2 { break; //退出循环 } } } //设置节点 struct node { char *data; struct node *next; struct node *prev; }; //初始化链表 struct node *list_init(char *newdata) { struct node *head = malloc(sizeof(struct node)); head->data = newdata; head->next = head; head->prev = head; return head; } //创建新节点 struct node *newnode(char *newdata) { struct node *new = malloc(sizeof(struct node)); new->data = newdata; new->next = NULL; new->prev = NULL; } //加入新节点 int addnode(struct node *new,struct node *list) { struct node *p = list; while(p->next != list) { p = p->next; } new->prev = list->prev; new->next = list; list->prev = new; new->prev->next = new; } #endif

图像头文件(控制相册) album.h

#include "myhead.h" #ifndef ALBUM_H #define ALBUM_H //相册控制 int album_control() { printf("成功进入相册!!\n"); char buf[20]; label: showbmp("firstp.bmp",1); //显示缩略图,控制缩小的参数:1为原大小,2为原图的1/2 get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 int x_dif = tx2 - tx1; int y_dif = ty2 - ty1; if(tx1 > 0 && tx1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/001.bmp"); showbmp(buf,1); } if(ty1 > 160 && ty1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/011.bmp"); showbmp(buf,1); } } if(tx1 > 160 && tx1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/002.bmp"); showbmp(buf,1); } if(ty1 > 160 && ty1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/012.bmp"); showbmp(buf,1); } } if(tx1 > 320 && tx1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/003.bmp"); showbmp(buf,1); } if(ty1 > 160 && ty1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/013.bmp"); showbmp(buf,1); } } if(tx1 > 480 && tx1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/004.bmp"); showbmp(buf,1); } if(ty1 > 160 && ty1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/014.bmp"); showbmp(buf,1); } } if(tx1 > 640 && tx1 showbmp("background.bmp",1); sprintf(buf,"%s","bmp/005.bmp"); showbmp(buf,1); } if(ty1 > 160 && ty1 y_dif = 0 ; printf("成功退出相册!\n"); return 0; } clear(); //重置触摸屏坐标返回值 struct node *list = list_init("010.bmp"); //初始化双向循环链表 char *path = "bmp"; DIR *dp = opendir(path); struct dirent *p; while(p = readdir(dp)) //遍历目录文件 { if(p->d_type == DT_REG) { if(strstr(p->d_name,".bmp")) //判断是否为.bmp文件 { struct node *new = newnode(p->d_name); //创建新节点 addnode(new,list); //插入新节点 } } } struct node *head = list->next; while(1) { clear(); get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 x_dif = tx2 - tx1; y_dif = ty2 - ty1; if(x_dif > 100 || tx1 > 600) //右翻 { x_dif = 0; head = head->next; bzero(buf,20); sprintf(buf,"%s/%s",path,head->data); showbmp("background.bmp",1); //背景图刷屏 showbmp(buf,1); //显示BMP图片 } if(x_dif -600 || tx1 y_dif = 0 ; showbmp("background.bmp",1); showbmp(buf,2); //显示BMP图片,缩小为原图1/2 } if(y_dif printf("成功打开音乐播放器!\n"); showbmp("background06.bmp",1); //音乐播放器界面-----默认自动播放 //system("madplay music/*.mp3 -z &"); //列表随机播放 system("madplay music/*.mp3 -r &"); //列表循环播放 struct node *list = list_init("1.mp3"); //初始化双向循环链表 char *path = "music"; DIR *dp = opendir(path); struct dirent *p; while(p = readdir(dp)) //遍历目录文件 { if(p->d_type == DT_REG) { if(strstr(p->d_name,".mp3")) //判断是否为.mp3文件 { struct node *new = newnode(p->d_name); //创建新节点 addnode(new,list); //插入新节点 } } } char buf[20]; //用于存放拼接后的字符串 struct node *head = list->next; for(;;) { get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 if(ty1 > 260 && ty1 350 && tx1 clear(); system("killall -STOP madplay &"); } if(tx1 > 470 && tx1 115 && ty1 clear(); system("killall -9 madplay"); head = head->prev; bzero(buf,20); sprintf(buf,"madplay %s/%s &",path,head->data); system(buf); } if(ty1 > 260 && ty1 470 && tx1 printf("成功打开视频播放器!\n"); int flag = 0; showbmp("start.bmp",1); struct node *list = list_init("02.wmv"); //初始化双向循环链表 char *path = "movie"; DIR *dp = opendir(path); struct dirent *p; while(p = readdir(dp)) //遍历目录文件 { if(p->d_type == DT_REG) { if(strstr(p->d_name,".wmv")) //判断是否为.mp3文件 { struct node *new = newnode(p->d_name); //创建新节点 addnode(new,list); //插入新节点 } } } char buf[40]; struct node *head = list->next; for(;;) { get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 printf("你点击的坐标位置X坐标是:%d\n", tx1); printf("你点击的坐标位置Y坐标是:%d\n", ty1); if(tx1 > 360 && tx1 410 && ty1 clear(); showbmp("stop.bmp",1); system("mplayer movie/03.wmv -zoom -x 800 -y 420 &"); flag = 1; continue; } if(flag == 1) //停止播放 { clear(); showbmp("start.bmp",1); system("killall -STOP mplayer"); flag = 2; continue; } if(flag == 2) //继续播放 { clear(); showbmp("stop.bmp",1); system("killall -CONT mplayer"); flag = 1; continue; } } if(tx1>445 && tx1410 && ty1 clear(); showbmp("stop.bmp",1); system("killall -KILL mplayer"); head = head->prev; bzero(buf,40); sprintf(buf,"mplayer %s/%s -zoom -x 800 -y 420 &",path,head->data); system(buf); } if(tx1>700 && tx1410 && ty1 0}; char name_buf1[]= {0}; char name_buf2[]= {0}; char name[30] = {0}; char keys[30] = {0}; int input(); //账号密码输入 int sign_in(); //登录 int logon(); //注册 int main() { display_open(); //打开显示屏 touch_open(); //打开触摸屏 showbmp("interface1.bmp",1); //登录界面 for(;;) { get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 input(); //账号密码输入 sign_in(); //登录 logon(); //注册 } touch_close(); //关闭触摸屏 display_close(); //关闭显示屏 } //账号密码输入 int input() { char username[]= {0}; char password[]= {0}; for(;;) { if(tx1 > 240 && tx1 160 && ty1 clear(); printf("请输入密码:\n"); scanf("%s",password); } bzero(name_buf1,30); sprintf(name_buf1,"%s%s",username,password); break; } } //登录 int sign_in() { int flag = 0; get_xy(&tx1, &ty1,&tx2, &ty2); //获取触摸屏的坐标 if(tx1 > 185 && tx1 360 && ty1 fgets(name_buf2, 30, dst1); if(strncmp(name_buf2,name_buf1,strlen(name_buf2) == 0)) { printf("登陆成功!\n"); flag = 1; break; } bzero(name_buf2, 30); } if(feof(dst1) && flag == 0) { printf("你输入的用户名与密码不匹配!\n请重新输入!\n\n"); flag = 0; return 0; } label0: showbmp("interface2.bmp",1);//跳转到主界面 while(1) { get_xy(&tx1, &ty1,&tx2, &ty2);//获取触摸屏的坐标 if(ty1 > 80 && ty1 200 && tx1 video_control();//视频播放器控制部分 goto label0; } if(ty1 > 300 && ty1 200 && tx1 goto label0; } } } } //注册 int logon() { if( tx1 > 510 && tx1 360 && ty1 if(tx1 > 280 && tx1 160 && ty1 clear(); bzero(name_buf,30); printf("请输入密码:\n"); scanf("%s",keys); dst1 = fopen("1.txt", "a+");//打开文件 fwrite(keys,1,strlen(keys),dst1);//写入内容 fprintf(dst1,"\n");//换行 fclose(dst1);//关闭文件 get_xy(&tx1, &ty1,&tx2, &ty2);//获取触摸屏的坐标 } if(tx1 > 565 && tx1 355 && ty1 clear(); ("interface1.bmp",1);//登录界面 return 0; } } } }

总结: 最终效果也算是中规中矩,并没有什么特别效果、新奇的算法,只是最普通的实现功能。这里记录一下全过程的想法: ①注册登录部分:运行程序显示登录界面,点击注册方框,跳出注册方框,点击用户名方框输入字符串到char型数组name中,通过文件IO的读写,将用户名字符串写入txt文本,再点击密码方框输入字符串到keys数组中,同样通过文件IO的读写功能,将密码字符串追加到txt文本的同一行,再通过fprintf(dst1,“\n”);进行换行操作。点击确定方框又回到登录界面,分别点击用户名、密码进行键盘输入,将输入的字符串分别存放于两个数组中,通过sprintf()函数将两个数组的字符串拼接在一起,最后点击登录方框时,使用fgets()函数(单行读取)循环读取txt文本内容,然后会通过strcmp将文本读出的每一行内容与拼接后的字符串相比较,完全相同则登录成功,进入到主界面。 ②音频部分:主界面显示三个图标,设置好对应位置,当点击音频图标位置,会跳转到音频界面(默认列表循环自动播放)。歌曲的列表是通过双向循环链表存放目录文件下 所有(.MP3 )文件实现。同样的音频界面也设置好对应的按钮位置,当点击暂停按钮,就会通过system(“killall -STOP madplay &”); 输入命令,暂停当前歌曲的播放。点击开始按钮,会继续播放刚暂停了的歌曲(暂停位置开始)。而上一首、下一首的切换时,我是通过命令关闭播放器,再重新打开播放器,播放下一首、上一首歌曲。点击终止按钮则退回到主界面。 ③视频部分:与音频部分基本相似,当点击视频图标位置,会跳转到视频频界面。视频的列表也是通过双向循环链表存放目录文件下所有(.WMV )文件实现。同样的视频界面也设置好对应的按钮位置,点击开始按钮会播放视频,当点击暂停按钮则暂停当前视频的播放,再点击开始按钮会继续播放刚暂停了的视频(暂停位置开始)。而上一个、下一个视频的切换,我也是通过命令关闭播放器,再重新打开播放器,播放上一个、下一个视频。点击终止按钮则退回到主界面。 ④BMP相册部分:当点击相册图标时,则会跳转到"缩略图"页面,点击其中一个“缩略图”就会打开对应的BMP原图,然后可以通过左右点击或者左右划屏进行图片上一张、下一张的切换,下滑可以缩小图片(大小为原图的1/2),缩小倍数通过传参给函数设置,而上划则退回到“缩略图”页面,再上划则退回主界面。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有