项目概述

本项目是基于GEC6818开发板成功开发了一款功能完备的多媒体智能终端系统。系统集成了图片浏览、音乐播放、视频播放和团队介绍四大核心功能,为用户提供了直观友好的触摸屏交互体验。

系统架构设计

硬件平台

  • 核心处理器:GEC6818开发板

  • 显示设备:800×480分辨率LCD触摸屏

  • 存储设备:支持FAT32格式U盘

  • 音频输出:3.5mm音频接口

软件架构

应用层:用户界面、功能模块
中间层:FrameBuffer图形显示、触摸事件处理
底层:Linux驱动、mplayer多媒体框架
系统软件流程

功能模块详解

1. 主界面系统

采用四宫格设计,清晰划分功能区域:

// 主界面触摸区域划分
if(p_ts->x>0 && p_ts->x<270 && p_ts->y>0 && p_ts->y<360) {
    // 相册功能
} else if(p_ts->x>270 && p_ts->x<540) {
    // 音乐播放
} else if(p_ts->x>540 && p_ts->x<800) {
    // 视频播放
} else if(p_ts->x>0 && p_ts->x<270 && p_ts->y>360 && p_ts->y<480) {
    // 团队介绍
}

界面特点

  • 布局简洁直观

  • 触摸响应灵敏

  • 视觉反馈明确

2. 相册浏览模块

支持多种图片浏览模式:

// 图片显示核心函数
void DisBMP(char *bmppathname, struct lcd_node *plcd) {
    int fd_bmp = OPEN(bmppathname);
    char bmp_buf[800*480*3];
    // 读取BMP文件数据
    lseek(fd_bmp, 54, SEEK_SET);
    read(fd_bmp, bmp_buf, sizeof(bmp_buf));
    
    // 数据格式转换并显示
    for(int i=0; i<480; i++) {
        for(int j=0; j<800; j++) {
            plcd->lcd_map[i*800+j] = 0x00<<24 |
                bmp_buf[3*((479-i)*800+j)+2]<<16 |
                bmp_buf[3*((479-i)*800+j)+1]<<8 |
                bmp_buf[3*((479-i)*800+j)]<<0;
        }
    }
    close(fd_bmp);
}

功能特性

  • 支持BMP格式图片

  • 手动切换(左右滑动)

  • 自动轮播模式

  • 快速退出功能

3. 音乐播放模块

基于mplayer实现完整的音乐播放控制:

// 音乐播放控制逻辑
sprintf(p_buf, "mplayer %s &", music_path[flag_musicpath]);
system(p_buf);  // 后台播放

// 播放控制
if(state >= 1) {
    system("killall -SIGSTOP mplayer");  // 暂停
} else {
    system("killall -SIGCONT mplayer");  // 继续
}

控制功能

  • 播放/暂停

  • 下一首

  • 上一首

  • 退出播放

4. 视频播放模块

支持多种视频格式播放:

// 视频播放与控制
system("mplayer -zoom -x 720 -y 480 video/1.avi &");

// 视频控制
if(VideoState <= 0) {
    system("killall -SIGCONT mplayer");  // 继续播放
} else {
    system("killall -SIGSTOP mplayer");  // 暂停播放
}

视频特性

  • 自适应屏幕分辨率

  • 流畅播放体验

  • 完整的播放控制

  • 多视频文件支持

5. 团队介绍模块

展示开发团队信息:

  • 成员姓名展示

  • 专业背景信息

  • 项目分工说明

核心技术实现

FrameBuffer图形显示

void Init_LCD(struct lcd_node *plcd) {
    plcd->lcd_fd = OPEN("/dev/fb0");
    plcd->lcd_map = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
                        MAP_SHARED, plcd->lcd_fd, 0);
}

直接操作显存,实现高效图形刷新。

触摸屏事件处理

void Get_xy(struct TS_node *p) {
    while(1) {
        read(p->ts_fd, &(p->myevent), sizeof(p->myevent));
        if(p->myevent.type == EV_ABS) {
            if(p->myevent.code == ABS_X) {
                p->x = p->myevent.value * 800 / 1024;
                p->count++;
            }
            if(p->myevent.code == ABS_Y) {
                p->y = p->myevent.value * 480 / 600;
                p->count++;
            }
        }
        if(p->count == 2) {
            p->count = 0;
            break;
        }
    }
}

精确获取触摸坐标,实现灵敏交互。

系统软、硬件调试过程

使用mplayer命令报错

没下载mplayer文件,将mplayer放入/usr/bin中。

使用mplayer命令无反应

开发板故障,换一个开发板解决。

播放音频时触频操作无反应

使用串行命令导致前台运行播放音频无法即时操作,使用mplayer命令在尾部加上&使其后台播放,实现即时操作效果。

u盘插入开发板后无法读取文件

u盘的文件系统为exFAT,开发板不支持,使用文件系统为FAT32的u盘即可读取。

系统完整代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>

#include <strings.h>
#include <linux/input.h>   //结构体所使用的头文件
#include <stdlib.h>


#include <pthread.h>   //线程头文件


//声明结构体类型
struct lcd_node{
	int lcd_fd;      //lcd描述符
	int *lcd_map;    //lcd显存映射
	
};  //lcd结构体

//声明一个触摸屏结构体
struct TS_node {
		int ts_fd;
		struct input_event	myevent;
		int x;
		int y;
		int count;
	
};





/************函数声明********************/
void DisBMP(char *bmppathname,struct lcd_node *plcd);	//	显示图片
int OPEN(char *pathname);            //打开设备
void Init_LCD(struct lcd_node *plcd );        //	初始化LCD
void Init_TS(struct TS_node *p);
void Get_xy(struct TS_node *p);

/******************************************************************************/

int main()
{	
	char bg_path[4][100]={
		 "/mnt/udisk/technology/bg/main.bmp",
		 "/mnt/udisk/technology/bg/book.bmp",
		 "/mnt/udisk/technology/bg/music.bmp",
		 "/mnt/udisk/technology/bg/video.bmp",
	 };
	int flag_bgpath = 0;

	char bmp_path[4][100]={
		 "/mnt/udisk/technology/book/1.bmp",
		 "/mnt/udisk/technology/book/2.bmp",
		 "/mnt/udisk/technology/book/3.bmp",
		 
	 };
	int flag_bmppath = 0;
	int i = 0;


	char music_path[4][100]={
		 "/mnt/udisk/technology/music/1.mp3",
		 "/mnt/udisk/technology/music/2.mp3",
		 "/mnt/udisk/technology/music/3.mp3",
	 };
	int flag_musicpath = 0;
        int state ;

	char video_path[4][100]={
		 "/mnt/udisk/technology/video/1.avi",
		 "/mnt/udisk/technology/video/2.avi",
		 "/mnt/udisk/technology/video/3.avi",
	 };
	int flag_videopath = 0;
	int VideoState ;
		




	struct lcd_node *p_lcd=calloc(1,sizeof(struct lcd_node));//申请内存空间
	struct TS_node *p_ts=calloc(1,sizeof(struct TS_node));//申请内存空间

	char p_buf[100];
	//初始化
	Init_LCD(p_lcd); 
	Init_TS(p_ts);
	while(1)
	{
		//显示图片-主界面
		DisBMP("bg/main.bmp",p_lcd);
		printf("=====Home=====\n");
		//获取坐标
		Get_xy(p_ts);

		//坐标判断
		if(p_ts->x>0 &&p_ts->x<270 && p_ts->y>0 && p_ts->y<360) //电子书
		{
			p_ts->x = 0;
			p_ts->y = 0;
			flag_bmppath = 0;
			DisBMP(bmp_path[flag_bmppath],p_lcd);
			printf("=====Show Picture=====\n");
			while(1)
			{					
				Get_xy(p_ts);
				if(p_ts->x>540 && p_ts->x<800 && p_ts->y>120 && p_ts->y<480)  //下一张
					{
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_bmppath>=2)
						{
							flag_bmppath = -1;
						}
						flag_bmppath++;
						DisBMP(bmp_path[flag_bmppath],p_lcd);	
						printf("Picture %d \n", flag_bmppath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>120 && p_ts->y<480)  //上一张
					{
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_bmppath <= 0)
						{
							flag_bmppath = 3;
						}
						flag_bmppath--;
						DisBMP(bmp_path[flag_bmppath],p_lcd);	
						printf("Picture %d \n", flag_bmppath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>0 && p_ts->y<120)//退出图片浏览
				{								
					p_ts->x = 0;
					p_ts->y = 0;
					printf("=====Quit!=====\n");
					break;
				}
				if(p_ts->x>600 && p_ts->x<800 && p_ts->y>0 && p_ts->y<120)
				{
					p_ts->x = 0;
					p_ts->y = 0;
					
					while(1)
					{	
						if(i==3)
						{
						i=0;
						break;
						}
					    if (flag_bmppath>=2)
						{
							flag_bmppath = -1;
						}
						flag_bmppath++;
						DisBMP(bmp_path[flag_bmppath],p_lcd);	
						printf("Picture %d \n", flag_bmppath);
						sleep(1);
						i++;
					}

					
				}
						
			}
				
							
		}
		
		if(p_ts->x>0 &&p_ts->x<270 && p_ts->y>360 && p_ts->y<480) //团队信息
		{
			p_ts->x = 0;
			p_ts->y = 0;
			flag_bmppath = 0;
			DisBMP("bg/staff.bmp",p_lcd);
			printf("=====Staff=====\n");
			while(1)
			{					
				Get_xy(p_ts);
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>0 && p_ts->y<120)//退出团队浏览
				{								
					p_ts->x = 0;
					p_ts->y = 0;
					printf("=====Quit!=====\n");
					break;
				}		
			}
				
							
		}



		if(p_ts->x>270 &&p_ts->x<540) //音乐播放
		{
			DisBMP("bg/music.bmp",p_lcd);
			p_ts->x = 0;
			p_ts->y = 0;
			flag_musicpath = 0;
			sprintf(p_buf,"mplayer %s &",music_path[0]);
			system(p_buf);
			state = 1;
			// system("mplayer house.mp3");
			printf("=====Play Music=====\n");
			while(1)
			{	
								
				Get_xy(p_ts);
				printf("Music %d \n", flag_musicpath);
				if(p_ts->x>540 && p_ts->x<800 && p_ts->y>360 && p_ts->y<480)  //下一张
					{
						system("killall -SIGKILL mplayer");
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_musicpath>=2)
						{
							flag_musicpath = -1;
						}
						flag_musicpath++;
						sprintf(p_buf,"mplayer %s &",music_path[flag_musicpath]);
						system(p_buf);	
						printf(p_buf);
						printf("Music %d \n", flag_musicpath);
						printf("Music %d \n", flag_musicpath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>360 && p_ts->y<480)  //上一张
					{
						system("killall -SIGKILL mplayer");
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_musicpath<=0)
						{
							flag_musicpath = 3;
						}
						flag_musicpath--;
						sprintf(p_buf,"mplayer %s &",music_path[flag_musicpath]);
						system(p_buf);	
						printf(p_buf);
						printf("Music %d \n", flag_musicpath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>0 && p_ts->y<120)//退出音乐浏览
				{								
					p_ts->x = 0;
					p_ts->y = 0;
					system("killall -SIGKILL mplayer");
					printf("=====Quit!=====\n");
					break;
				}
				if(p_ts->x>270 && p_ts->x<540 && p_ts->y>160 && p_ts->y<360)  //暂停
					{
						p_ts->x = 0;
						p_ts->y = 0;
						if (state <= 0)                                 //继续播放
						{
						system("killall -SIGCONT mplayer");	
						printf("Continue Play %d \n", flag_musicpath);
						state = 1;
						continue;
						}
						if (state >=1)                                 //暂停播放
						{
						system("killall -SIGSTOP mplayer");	
						printf("Pause Play %d \n", flag_musicpath);
						state = 0;
						continue;
						}
					}		
			}
				
							
		}

		if(p_ts->x>540 &&p_ts->x<800) //视频播放
		{
			p_ts->x = 0;
			p_ts->y = 0;
			flag_videopath = 0;
			VideoState = 1;
			// DisBMP(bmp_path[flag_bmppath],p_lcd);
			system("mplayer zoom -x 720 -y 480 video/1.avi &");
			printf("=====Play video=====\n");
			while(1)
			{					
				Get_xy(p_ts);
				if(p_ts->x>540 && p_ts->x<800 && p_ts->y>360 && p_ts->y<480)  //下一张
					{	
						system("killall -SIGKILL mplayer");
						VideoState = 1;
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_videopath>=2)
						{
							flag_videopath = -1;
						}
						flag_videopath++;
						
						sprintf(p_buf,"mplayer -zoom -x 720 -y 480 %s &",video_path[flag_videopath]);
						printf(p_buf);
						system(p_buf);	
						printf("Video %d \n", flag_videopath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>360 && p_ts->y<480)  //上一张
					{	
						system("killall -SIGKILL mplayer");
						VideoState = 1;
						p_ts->x = 0;
						p_ts->y = 0;
						if (flag_videopath<=0)
						{
							flag_videopath = 3;
						}
						flag_videopath--;
						
						sprintf(p_buf,"mplayer -zoom -x 720 -y 480 %s &",video_path[flag_videopath]);
						printf(p_buf);
						system(p_buf);	
						printf("Video %d \n", flag_videopath);
					}
				if(p_ts->x>0 && p_ts->x<270 && p_ts->y>0 && p_ts->y<120)//退出视频浏览
				{		
					VideoState = 0;						
					p_ts->x = 0;
					p_ts->y = 0;
					system("killall -SIGKILL mplayer");
					printf("=====Quit!=====\n");
					break;
				}
				if(p_ts->x>270 && p_ts->x<540 && p_ts->y>160 && p_ts->y<360)  //暂停
					{
						p_ts->x = 0;
						p_ts->y = 0;
						if (VideoState <= 0)                                 //继续播放
						{
						system("killall -SIGCONT mplayer");	
						printf("Continue Play %d \n", flag_videopath);
						VideoState = 1;
						continue;
						}
						if (VideoState >= 1)                                 //暂停播放
						{
						system("killall -SIGSTOP mplayer");	
						printf("Pause Play %d \n", flag_videopath);
						VideoState = 0;
						continue;
						}
					}	
		
			}
				
							
		}



	}
		
//关闭触摸屏

	close(p_lcd->lcd_fd);
	close(p_ts->ts_fd);
	
// 关闭映射
	 munmap(p_lcd->lcd_map, 800*480*4);
	 
	return 0;
		
}

/******************文件打开函数*********

功能:文件打开
函数:OPEN()
参数:pathname 

***************************************/
	
	
int OPEN(char *pathname)
{
	//1、打开lcd液晶屏
	int fd;
	fd=open(pathname,O_RDWR);
	if(fd==-1)
	{
		printf("open %s failed!!!\n",pathname);
	}
	return fd;
}

/******************LCD初始化*********

功能:LCD初始化
函数:Init_LCD()
参数:

***************************************/

void Init_LCD(struct lcd_node *plcd )
{
		
	//打开lcd液晶屏
	
	plcd->lcd_fd=OPEN("/dev/fb0");
	
	//开启映射
	plcd->lcd_map= mmap(NULL,800*480*4,PROT_READ|PROT_WRITE, MAP_SHARED,plcd->lcd_fd,0);
	if(plcd->lcd_map == MAP_FAILED)
	{
		perror("mmap is error\n");
		exit(-1);
	}
	return;  //不需要返回
	
}

/******************图片显示*********

功能:图片显示
函数:DisBMP();
参数:

***************************************/

void DisBMP(char *bmppathname,struct lcd_node *plcd)	
{
	//1、打开bmp图片
	int fd_bmp;   //图片文件描述符
	fd_bmp=OPEN(bmppathname);
	
char buf[20];
//2、读bmp图片
	char bmp_buf[800*480*3];    //用于存放图片文件大小
	bzero(bmp_buf,sizeof(bmp_buf));
	lseek(fd_bmp,54,SEEK_SET);
	read(fd_bmp,bmp_buf,sizeof(bmp_buf));
//3、关闭BMP
	close(fd_bmp );

//4、数据格式转换,
//int lcd_buf[800*480];  //定义一个数组,作为显存
	int i,j;
		
	for(i=0;i<480;i++)
			for(j=0;j<800;j++)
			plcd->lcd_map[i*800+j]= 0x00<<24|
									bmp_buf[3*((479-i)*800+j)+2]<<16|
									bmp_buf[3*((479-i)*800+j)+1]<<8|
									bmp_buf[3*((479-i)*800+j)]<<0;
	
}


/*****************触摸屏初始化函数***********************

功能:触摸屏初始化
函数:void Init_TS(struct TS_node *p);


*******************************************************/

void Init_TS(struct TS_node *p)
{

//打开触摸屏
	p->ts_fd=OPEN("/dev/input/event0");
}	

/*****************触摸屏坐标获取函数***********************

功能:触摸屏坐标值获取
函数:void Get_xy(struct TS_node *p);


*******************************************************/




void Get_xy(struct TS_node *p)
{
	while(1)
	{
	//读取触摸屏数据
	read(p->ts_fd,&(p->myevent),sizeof(p->myevent));       //等待输入数据,读到哪里,读多少数据
	
	if(p->myevent.type==EV_ABS)         //触摸屏事件
	{
		if(p->myevent.code==ABS_X)
		{
			p->x=p->myevent.value*800/1024;
			p->count++;
			
		}
		if(p->myevent.code==ABS_Y)
		{
			p->y=p->myevent.value*480/600;
			p->count++;
			
		}
	}
	if(p->count==2)
	{
		p->count=0;
		printf("(%d,%d)\n",p->x,p->y);
		break;
	}
	return ;		
		
	}
	
}

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐