基于GEC6818开发板的多媒体智能终端设计与实现
·
项目概述
本项目是基于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 ;
}
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)