粤嵌GEC6818,基于LVGL和mplayer的音视频播放器
Posted 旧金山路人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了粤嵌GEC6818,基于LVGL和mplayer的音视频播放器相关的知识,希望对你有一定的参考价值。
#include <myplay.h>
pthread_mutex_t mutex_lv;//lvgl线程锁
static char local_music_path[]="/tmp/newwork/8.30big_project/music";//音乐路径
static char local_pic_path[]="/tmp/newwork/photo";//图片路径
static char local_words_path[]="/tmp/newwork/words";//歌词路径
static char local_video_path[]="/tmp/newwork/tv";//视频路径
static char music_path[100][1024];//音乐路径
static char pic_path[100][1024];//图片路径
static char words_path[100][1024];//歌词路径
static char video_path[100][1024];//视频路径
static char words_buf[5*1024]=0;//放歌词的数组
static FILE *fp_mplayer=NULL; //播放器传回的管道,接收播放进度
static FILE *fp_words=NULL; //歌词文件
static int fd_mplayer = 0; //定义管道文件描述符,发送指令给mplayer
static int music_num=0; //音乐数量
static int music_index=-1; //当前音乐的下标值,用于寻找上下首
static int video_index=-1; //当前视频的下标值,用于寻找上下首
static int video_num=0; //视频的数量
static int percent_pos; //当前播放百分比
static float time_length; //歌曲长度
static float time_pos; //当前播放进度
static bool list_flag=1; //开关列表
static bool words_flag=1; //歌词列表
static bool play_flag=0; //播放音乐开关
static bool start=0; //启动,线程读mplayer返回信息
static lv_style_t font_style; //中文
static lv_obj_t *play_mode; //下拉列表对象,播放模式
static lv_obj_t *speed_obj; //下拉列表对象,播放速度
static lv_obj_t * music_list; //音乐列表对象
static lv_obj_t *pic_obj; //图片对象
static lv_obj_t * volume_slider; //音量滑条对象
static lv_obj_t * play_slider; //播放进度条对象
static lv_obj_t * cont; //音乐盒的背景对象
static lv_obj_t * video_list; //视频列表对象
static lv_obj_t *title_label; //图片信息标签
static lv_obj_t *words_label; //歌词标签
static lv_obj_t * volume_label; //音量标签
static lv_obj_t *time_length_label; //时长标签
static lv_obj_t *time_pos_label; //当前时间标签
static lv_obj_t *words_list; //歌词标签
pthread_cond_t cond; //条件变量,用于暂停读取mplayer
pthread_cond_t cond1;
pthread_mutex_t mutex;
pthread_mutex_t mutex1;
pthread_t tid_read; //读mplayer的线程id
pthread_t tid_write; //写mplayer的线程id
//这里为音乐播放器部分
//获取音乐的路径,检测本地歌单
void get_music_path()
//读目录,mp3后缀保存到数组
music_num =0;
DIR *dirp = opendir(local_music_path);
if(dirp==NULL)
perror(local_music_path);
exit(0);
struct dirent* msg;
while(1)
msg = readdir(dirp);
if(msg == NULL)break;
if(msg->d_name[0]=='.')continue;
if(strstr(msg->d_name,".mp3"))
sprintf(music_path[music_num], "%s/%s", local_music_path, msg->d_name);
//拼接图片与歌词路径↓
char name[100]=0;
strcpy(name,strtok(msg->d_name,"."));
sprintf(pic_path[music_num], "S:%s/%s.png", local_pic_path, name);
sprintf(words_path[music_num], "%s/%s.txt", local_words_path, name);
//拼接图片与歌词路径↑
music_num++;
puts(music_path[music_num - 1]);
puts(pic_path[music_num - 1]);
puts(words_path[music_num - 1]);
printf("检索歌单完成 共%d\\n",music_num);
//初始化字体风格
void init_font_style()
/*创建字体*/
static lv_ft_info_t info;
info.name = "/font/simkai.ttf";//字体位置
info.weight = 18;//大小
info.style = FT_FONT_STYLE_NORMAL;//风格
info.mem = NULL;
if(!lv_ft_font_init(&info))
LV_LOG_ERROR("create failed.");
/*给字体设置样式*/
lv_style_init(&font_style);
lv_style_set_text_font(&font_style, info.font);
lv_style_set_text_align(&font_style, LV_TEXT_ALIGN_CENTER);
//lv_obj_add_style(label, &style, 0);
//初始化图片的父对象,即图片都在这个对象中显示
void init_pic_parent_obj()
//在屏幕中创建一个对象
lv_obj_t * img = lv_obj_create(cont);
//取消滚动
lv_obj_clear_flag(img, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(img, 200, 200);
lv_obj_align(img, LV_ALIGN_CENTER, 0, -60);
// lv_obj_set_style_pad_all
//图片对象
pic_obj = lv_img_create(img);
lv_obj_center(pic_obj);
//信号任务
void signal_10_task(int arg)
if (arg == 10)
printf("收到信号 %d 线程任务(读取mplayer)暂停\\n", arg);
pthread_kill(tid_write,12); //停止写
pthread_cond_wait(&cond, &mutex); //停止读
pthread_cond_signal(&cond1);//唤醒获取时间
puts("继续工作,读mplayer");
return;
//信号任务
void signal_12_task(int arg)
//printf("收到信号 %d\\n",arg);
printf("收到信号 %d 线程任务(get_time_pos)暂停\\n", arg);
pthread_cond_wait(&cond1, &mutex1);
puts("继续工作,写mplayer");
return;
static char words_line[1024]=0;
//初始化歌曲信息的父对象
void init_title_obj()
// //在屏幕中创建一个对象
lv_obj_t * title = lv_obj_create(cont);
lv_obj_clear_flag(title, LV_OBJ_FLAG_SCROLLABLE);//禁用滚动
lv_obj_set_size(title, 200, 50);
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
//标题标签
title_label = lv_label_create(title);
//添加字体
lv_obj_add_style(title_label, &font_style, 0);
lv_obj_center(title_label);
lv_label_set_text(title_label, "开启音乐之旅");
//歌词标签
words_label = lv_label_create(cont);
lv_obj_align(words_label,LV_ALIGN_CENTER,0,70);
lv_obj_add_style(words_label, &font_style, 0);
lv_label_set_text(words_label,"歌词");
//找歌词
void *find_words_task(void *arg)
char *p=strstr(words_buf,(char *)arg);//寻找这个时间有没有歌词
if(p!=NULL) //和歌词相同时间
char buf[1024]=0;
sscanf(p,"%s",buf);
char *q = strrchr(buf,']');
sscanf(++q,"%s",buf);
if(strcmp(buf,words_line))//不相同
strcpy(words_line,buf);
//puts(words_line);
//**********歌词标签
//lv_label_set_text(words_label,words_line);
pthread_mutex_lock(&mutex_lv);//上锁
lv_label_set_text(words_label,words_line);
pthread_mutex_unlock(&mutex_lv);
//线程任务 读播放器返回内容
static char show_time_buf[100]=0;
void *read_mplayer_task(void *arg)
//注册一个信号
signal(10, signal_10_task);//收到10就暂停
char line[1024]=0; //返回信息
char *p;
while (1)
memset(line, 0, 1024);
fgets(line,1024,fp_mplayer); //读取进程返回的内容
//printf("返回 %s",line);
if(strstr(line,"ANS_TIME_POSITION"))//当前播放秒数
p=strrchr(line,'=');
p++;
sscanf(p,"%f",&time_pos);
printf("歌曲播放时间 %.2f\\n",time_pos);
char tmp[100]=0;
int tmp_time=time_pos;
sprintf(tmp,"%02d:%02d",tmp_time/60,tmp_time % 60);
if(strcmp(show_time_buf,tmp))//不相同
strcpy(show_time_buf,tmp);
//lv_label_set_text(time_pos_label,show_time_buf); //设置标签
pthread_mutex_lock(&mutex_lv);//上锁
lv_label_set_text(time_pos_label,show_time_buf);
pthread_mutex_unlock(&mutex_lv);//解锁
puts(tmp);//打印时间 00:00
//*********开启线程找歌词**********//
pthread_t tid;
pthread_create(&tid,NULL,find_words_task,tmp);
pthread_detach(tid);
//*******************//
if(strstr(line,"ANS_PERCENT_POSITION"))//播放百分比
p=strrchr(line,'=');//p++;
int percent=0;
sscanf(++p,"%d",&percent);
printf("播放百分比 %d\\n",percent_pos);
if(percent!=percent_pos)
percent_pos=percent;
//lv_slider_set_value(play_slider,percent_pos,LV_ANIM_OFF);//设置进度条值
pthread_mutex_lock(&mutex_lv);//上锁
lv_slider_set_value(play_slider,percent_pos,LV_ANIM_OFF);
pthread_mutex_unlock(&mutex_lv);
if(percent_pos>=99)//播完了
lv_label_set_text(time_pos_label,"0:00");
//播放模式
int mod = lv_dropdown_get_selected(play_mode);
switch (mod)
case 0:
pthread_kill(tid_read,10);//停止读写mplayer
break;
case 1://循环播放
break;
case 2://列表循环
if(++music_index >= music_num)music_index=0;
play_one_music();
break;
case 3://随机播放
srand((unsigned)time(NULL));
music_index = (music_index+rand())%music_num;
play_one_music();
break;
default:
break;
if(strstr(line,"ANS_LENGTH"))//歌曲长度
p=strrchr(line,'=');p++;
sscanf(p,"%f",&time_length);
printf("歌曲长度 %.2f\\n",time_length);
char time_buf[100]=0;
int length=time_length;
sprintf(time_buf,"%02d:%02d",length/60,length % 60);
puts(time_buf);
pthread_mutex_lock(&mutex_lv);//上锁
lv_label_set_text(time_length_label,time_buf); //设置标签
pthread_mutex_unlock(&mutex_lv);//解锁
//线程任务 发送命令给mplayer
void *write_mplayer_task(void *arg)
//注册一个信号
signal(12, signal_12_task);//收到12就暂停
char cmd1[1024]="get_time_pos\\n";
char cmd[1024]="get_percent_pos\\n";
while(1)
write(fd_mplayer,cmd1,strlen(cmd1));//发送获取时间命令
usleep(400*1000);
write(fd_mplayer,cmd,strlen(cmd));//发送获取百分比
usleep(400*1000);
//sleep(1);
//线程任务 创建子进程播放音乐
void *play_music_task(void *arg)
printf("---- %ld线程任务------------------\\n",pthread_self());
//拼接命令
char cmd[1024]="mplayer -slave -quiet -input file=/pipe";
sprintf(cmd,"%s %s",cmd,music_path[music_index]);
//puts(cmd);
//播放音乐
fp_mplayer = popen(cmd, "r");
if (fp_mplayer == NULL)perror("popen fail:");
puts("----线程任务(启动播放音乐)完成 -----------------------\\n");
strcpy(cmd,"get_time_length\\n"); //获取长度
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_time_pos\\n"); //发送获取时间命令
write(fd_mplayer,cmd,strlen(cmd));
pthread_exit(NULL);//线程结束
//播放一首音乐
void play_one_music()
if(play_flag != 0)//看看有没有线程在使用播放器
system("killall -9 mplayer");
play_flag=1;
printf("音乐索引%d\\n", music_index);
//开启线程播放音乐
pthread_t tid;
int pt = pthread_create(&tid, NULL, play_music_task, NULL);
if(pt != 0)
perror("创建进程失败");
return -1;
pthread_detach(tid);//分离属性,自动回收
if(!start)
sleep(1);
//读取mplayer的内容
pthread_create(&tid_read, NULL, read_mplayer_task, NULL);//新建线程
pthread_detach(tid_read);//分离属性,自动回收
//发送获取时间命令
pthread_create(&tid_write, NULL, write_mplayer_task, NULL);
pthread_detach(tid_write);//分离属性,自动收回
printf("tid_read %ld tid_write %ld\\n",tid_read,tid_write);
start=1;
pthread_cond_signal(&cond);//唤醒线程读取mplayer返回的内容
//***************************************************************//
char tmp[100]=0;
char *p = strrchr(music_path[music_index],'/');
strcpy(tmp,++p);
lv_label_set_text(title_label,strtok(tmp,"."));
lv_label_set_text(words_label,strtok(tmp,"."));
//显示音乐图片
lv_img_set_src(pic_obj,pic_path[music_index]);
//打开歌词文件
FILE *fp = fopen(words_path[music_index],"r");
memset(words_buf,0,sizeof(words_buf));
if(fp!=NULL)
fread(words_buf,5*1024,4,fp);
fclose(fp);
//设置播放属性
int ret = lv_dropdown_get_selected(speed_obj);
//音量
int volume=(int)lv_slider_get_value(volume_slider);
char cmd[1024]=0;
sprintf(cmd,"volume %d 1\\n",volume);
write(fd_mplayer,cmd,strlen(cmd));
//修改播放速度
switch (ret)
case 0:
char cmd[1024]="speed_set 1\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 1:
char cmd[1024]="speed_set 1.25\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 2:
char cmd[1024]="speed_set 1.5\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 3:
char cmd[1024]="speed_set 2\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
default:
break;
//播放模式
int mod = lv_dropdown_get_selected(play_mode);
switch (mod)
case 0:
char cmd[1024]="loop -1\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 1:
char cmd[1024]="loop -1\\n";
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"loop 1\\n");write(fd_mplayer,cmd,strlen(cmd));
break;
case 2://列表循环
break;
case 3://随机播放
break;
default:
break;
//列表处理函数,播放列表中的音乐
static lv_event_cb_t event_handler_music_list(lv_event_t * e)
//获取事件码
lv_event_code_t code = lv_event_get_code(e);
//获取事件对象,这里是按钮
lv_obj_t * obj = lv_event_get_target(e);
//如果点击按钮
if(code == LV_EVENT_CLICKED)
//打印按钮中的文本
//LV_LOG_USER("Clicked: %s", lv_list_get_btn_text(music_list, obj));
printf("Clicked %s\\n", lv_list_get_btn_text(music_list, obj));
//当前播放中的音乐下标更新为点击列表的下标
music_index = lv_event_get_user_data(e);
play_one_music();
//显示歌单列表
static void show_list()
//创建列表文本框
music_list = lv_list_create(cont);
//添加风格
lv_obj_add_style(music_list, &font_style, 0);
lv_obj_set_size(music_list, 180, 300);
//列表位置
//lv_obj_center(music_list);
lv_obj_align(music_list, LV_ALIGN_RIGHT_MID, -20, -80);
//添加文本
lv_list_add_text(music_list, "Music list");
/*在列表中添加按钮*/
lv_obj_t *btn;
for(int i = 0; i < music_num; i++)
char tmp[100]=0;
char *p = music_path[i];
p = strrchr(p,'/');
strcpy(tmp,++p);//裁剪到只剩音乐名字 music.mp3
//参数:列表对象,图标宏,按钮名
btn = lv_list_add_btn(music_list, NULL,strtok(tmp,"."));
//列表按钮风格
lv_obj_add_style(music_list, &font_style, 0);
//触发事件,把下标传递
lv_obj_add_event_cb(btn, event_handler_music_list, LV_EVENT_CLICKED, i);
//按钮事件
static void btn_handler(lv_event_t * e)
lv_event_code_t code = lv_event_get_code(e);
//获取传递的参数
char *msg = lv_event_get_user_data(e);
if(code == LV_EVENT_CLICKED) //点击按钮
if(strcmp(msg,"pause") == 0)
if(!start)return;
pthread_kill(tid_read,10);//暂停读mplayer返回内容
system("killall -19 mplayer");
if(strcmp(msg,"play") == 0)
if(!start)return;
system("killall -18 mplayer");//播放器继续
pthread_cond_signal(&cond);//唤醒读写mplayer
usleep(1000);
pthread_cond_signal(&cond);//防止被再次暂停
if(strcmp(msg,"forward") == 0)
if(!start)return;
usleep(1000);
char cmd[1024]="seek +10\\n";
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_percent_pos\\n");
write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令
if(strcmp(msg,"back") == 0)
if(!start)return;
usleep(10000);
char cmd[1024]="seek -10\\n";
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_percent_pos\\n");
write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令
if(strcmp(msg,"next_music") == 0)
usleep(1000);
//播放模式
int mod = lv_dropdown_get_selected(play_mode);
switch (mod)
case 1:
play_one_music();break;
case 0:
case 2://列表循环
if(++music_index >= music_num)music_index=0;
play_one_music();
break;
case 3://随机播放
srand((unsigned)time(NULL));
music_index = (music_index+rand())%music_num;
printf("music_index %d\\n",music_index);
play_one_music();
break;
default:
break;
if(strcmp(msg,"prev_music") == 0)
usleep(1000);
//播放模式
int mod = lv_dropdown_get_selected(play_mode);
switch (mod)
case 1://循环播放
char cmd[1024]="loop -1\\n";write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"loop 1\\n");write(fd_mplayer,cmd,strlen(cmd));play_one_music();break;
case 0://单曲
case 2://列表循环
if(--music_index <= 0)music_index=music_num-1;
play_one_music();
break;
case 3://随机播放
srand((unsigned)time(NULL));
music_index = (music_index+rand())%music_num;
play_one_music();
break;
default:
break;
if(strcmp(msg,"show_list") == 0)
list_flag=!list_flag;
if(list_flag)
lv_obj_clear_flag(music_list,LV_OBJ_FLAG_HIDDEN);
else
lv_obj_add_flag(music_list, LV_OBJ_FLAG_HIDDEN);
//显示按钮
void show_button()
//风格设置
static lv_style_t btn_style;
lv_style_init(&btn_style);
/*Set a background color and a radius*/
lv_style_set_radius(&btn_style,90);
lv_style_set_bg_opa(&btn_style, LV_OPA_COVER);
lv_style_set_bg_color(&btn_style, lv_palette_lighten(LV_PALETTE_BLUE, 1));//按钮色
/*Add a shadow*/
lv_style_set_shadow_width(&btn_style, 55);
lv_style_set_shadow_color(&btn_style, lv_palette_main(LV_PALETTE_BLUE));//背景色
//按钮的标签
lv_obj_t *label;
//暂停按钮
lv_obj_t *btn_pause = lv_btn_create(cont);
//按钮事件
lv_obj_add_event_cb(btn_pause, btn_handler, LV_EVENT_ALL,"pause");
//位置
lv_obj_align(btn_pause, LV_ALIGN_BOTTOM_MID,40,-20);
//大小
lv_obj_set_size(btn_pause,60,60);
//图标
lv_obj_set_style_bg_img_src(btn_pause,LV_SYMBOL_PAUSE,0);
//添加风格
lv_obj_add_style(btn_pause,&btn_style,0);
//播放按钮
lv_obj_t *btn_play = lv_btn_create(cont);
lv_obj_add_event_cb(btn_play, btn_handler, LV_EVENT_ALL,"play");
lv_obj_align(btn_play, LV_ALIGN_BOTTOM_MID,-40,-20);
lv_obj_set_size(btn_play,60,60);
lv_obj_set_style_bg_img_src(btn_play,LV_SYMBOL_PLAY,0);
lv_obj_add_style(btn_play,&btn_style,0);
//快进
lv_obj_t *btn_forward = lv_btn_create(cont);
lv_obj_add_event_cb(btn_forward, btn_handler, LV_EVENT_ALL,"forward");
lv_obj_set_size(btn_forward,60,60);
lv_obj_align(btn_forward, LV_ALIGN_BOTTOM_MID,120,-20);
lv_obj_set_style_bg_img_src(btn_forward,LV_SYMBOL_RIGHT LV_SYMBOL_RIGHT,0);
lv_obj_add_style(btn_forward,&btn_style,0);
//快退
lv_obj_t *btn_back = lv_btn_create(cont);
lv_obj_add_event_cb(btn_back, btn_handler, LV_EVENT_ALL,"back");
lv_obj_set_size(btn_back,60,60);
lv_obj_align(btn_back, LV_ALIGN_BOTTOM_MID,-120,-20);
lv_obj_set_style_bg_img_src(btn_back,LV_SYMBOL_LEFT LV_SYMBOL_LEFT,0);
lv_obj_add_style(btn_back,&btn_style,0);
//下一首
lv_obj_t *btn_next = lv_btn_create(cont);
lv_obj_add_event_cb(btn_next, btn_handler, LV_EVENT_ALL,"next_music");
lv_obj_set_size(btn_next,60,60);
lv_obj_align(btn_next, LV_ALIGN_BOTTOM_MID,200,-20);
lv_obj_set_style_bg_img_src(btn_next,LV_SYMBOL_NEXT,0);
lv_obj_add_style(btn_next,&btn_style,0);
//上一首
lv_obj_t *btn_prev = lv_btn_create(cont);
lv_obj_add_event_cb(btn_prev, btn_handler, LV_EVENT_ALL,"prev_music");
lv_obj_set_size(btn_prev,60,60);
lv_obj_align(btn_prev, LV_ALIGN_BOTTOM_MID,-200,-20);
lv_obj_set_style_bg_img_src(btn_prev,LV_SYMBOL_PREV,0);
lv_obj_add_style(btn_prev,&btn_style,0);
//显示,隐藏 歌单列表
//风格设置
static lv_style_t style;
lv_style_init(&style);
/*设置背景颜色和半径*/
lv_style_set_radius(&style, 5);
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_bg_color(&style, lv_palette_lighten(LV_PALETTE_GREY, 1));
/*添加一个影子*/
lv_style_set_shadow_width(&style, 55);
lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_BLUE));
//歌单列表
lv_obj_t *btn_list = lv_btn_create(cont);
lv_obj_add_event_cb(btn_list, btn_handler, LV_EVENT_ALL,"show_list");
lv_obj_set_size(btn_list,60,60);
lv_obj_align(btn_list, LV_ALIGN_BOTTOM_RIGHT,-20,-90);
label = lv_label_create(btn_list);
lv_obj_add_style(label, &font_style, 0);
lv_label_set_text(label, "menu");
lv_obj_center(label);
lv_obj_add_style(btn_list, &style, 0);
//下拉列表事件
static void dd_handler(lv_event_t * e)
//获取事件码
lv_event_code_t code = lv_event_get_code(e);
//获取传递的参数
char *msg = lv_event_get_user_data(e);
if(code == LV_EVENT_VALUE_CHANGED)//值被修改
if(strcmp(msg,"speed")==0)
//获取事件对象
//lv_obj_t *speed = lv_event_get_target(e);
int ret = lv_dropdown_get_selected(speed_obj);
//printf("ret = %d\\n",ret);
//修改播放速度
switch (ret)
case 0:
char cmd[1024]="speed_set 1\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 1:
char cmd[1024]="speed_set 1.25\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 2:
char cmd[1024]="speed_set 1.5\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
case 3:
char cmd[1024]="speed_set 2\\n";
write(fd_mplayer,cmd,strlen(cmd));
break;
default:
break;
if(strcmp(msg,"play_mode")==0)
//播放模式
int mod = lv_dropdown_get_selected(play_mode);
switch (mod)
case 0:char cmd[1024]="loop -1\\n";write(fd_mplayer,cmd,strlen(cmd));break;
case 1:
char cmd[1024]="loop -1\\n";write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"loop 1\\n");write(fd_mplayer,cmd,strlen(cmd)); break;
case 2://列表循环
break;
case 3://随机播放
break;
default: break;
//显示下拉列表
static void show_drop_down()
static const char * opts = "x1\\n"
"x1.25\\n"
"x1.5\\n"
"x2";
static const char * opts1 = "single\\n"
"circle\\n"
"list\\n"
"random";
//播放速度 创建一个对象
speed_obj = lv_dropdown_create(cont);
//lv_dropdown_set_text(speed_obj, "Speed");
//触发事件
lv_obj_add_event_cb(speed_obj,dd_handler,LV_EVENT_ALL,"speed");
//添加选项
lv_dropdown_set_options_static(speed_obj, opts);
//大小
lv_obj_set_size(speed_obj,80,40);
//位置
lv_obj_align(speed_obj, LV_ALIGN_BOTTOM_RIGHT, -60, -20);
//箭头位置,现在由低朝上
lv_dropdown_set_dir(speed_obj, LV_DIR_BOTTOM);
//列表弹出方向
lv_dropdown_set_symbol(speed_obj, LV_SYMBOL_UP);
//标签
lv_obj_t *speed_label = lv_label_create(cont);
lv_obj_add_style(speed_label, &font_style, 0);
lv_label_set_text(speed_label, "speed");
lv_obj_align_to(speed_label, speed_obj, LV_ALIGN_OUT_TOP_MID, 0, 0);
//播放模式
play_mode = lv_dropdown_create(cont);
//添加字体
//lv_obj_add_style(play_mode, &font_style, 0);
lv_obj_add_event_cb(play_mode,dd_handler,LV_EVENT_ALL,"play_mode");
lv_dropdown_set_options_static(play_mode, opts1);
lv_obj_set_size(play_mode,100,40);
//位置
lv_obj_align(play_mode, LV_ALIGN_BOTTOM_LEFT, 40, -20);
lv_dropdown_set_dir(play_mode, LV_DIR_BOTTOM);
lv_dropdown_set_symbol(play_mode, LV_SYMBOL_UP);
lv_obj_t *mode_label = lv_label_create(cont);
lv_obj_add_style(mode_label, &font_style, 0);
lv_label_set_text(mode_label, "mode");
lv_obj_align_to(mode_label, play_mode, LV_ALIGN_OUT_TOP_MID, 0, 0);
//滑动条事件
static void slider_event_cb(lv_event_t * e)
if(!start)return;
//获取传递的参数
char *msg = lv_event_get_user_data(e);
//puts(msg);
if(strcmp(msg,"volume")==0)
lv_obj_t * slider = lv_event_get_target(e);//获取事件对象
char buf[8];
int volume=(int)lv_slider_get_value(slider);//获取值
lv_snprintf(buf, sizeof(buf), "%d",volume);
lv_label_set_text(volume_label, buf); //更新音量标签值
lv_obj_align_to(volume_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
usleep(100); //修改音量值
char cmd[1024]=0;
sprintf(cmd,"volume %d 1\\n",volume);
write(fd_mplayer,cmd,strlen(cmd));
if(strcmp(msg,"play")==0)
puts("松开了");
if(start)//启动就先暂停
pthread_kill(tid_read,10);//暂停读mplayer返回内容
system("killall -19 mplayer");
int rate = (int)lv_slider_get_value(play_slider);//获取值
float new_time = time_length * rate * 0.01;
int seek_time = new_time - time_pos;
char cmd[1024]=0;
sprintf(cmd,"seek %d\\n",seek_time);
//puts(cmd);
write(fd_mplayer,cmd,strlen(cmd));
system("killall -18 mplayer");//播放器继续
pthread_cond_signal(&cond);//唤醒读写mplayer
usleep(1000);
pthread_cond_signal(&cond);//防止被再次暂停
//显示滑动条
static void show_slider(void)
//音量
volume_slider = lv_slider_create(cont);
lv_obj_align(volume_slider,LV_ALIGN_LEFT_MID,20,20);//位置
lv_obj_add_event_cb(volume_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, "volume");//事件
lv_obj_set_size(volume_slider,18,180);//大小
lv_slider_set_value(volume_slider,100,LV_ANIM_OFF);//初始值
/*标签 音量大小 */
volume_label = lv_label_create(cont);
lv_label_set_text(volume_label, "100");
lv_obj_align_to(volume_label, volume_slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_obj_t *label = lv_label_create(cont);
lv_obj_add_style(label, &font_style, 0);
lv_label_set_text(label, "volume");
lv_obj_align_to(label, volume_label, LV_ALIGN_OUT_TOP_MID, 0, -210);
//播放进度条
play_slider = lv_slider_create(cont);
lv_obj_align(play_slider,LV_ALIGN_CENTER,0,120);//位置
lv_obj_set_width(play_slider,400);//宽度
lv_obj_add_event_cb(play_slider, slider_event_cb, LV_EVENT_RELEASED , "play");//事件
lv_slider_set_value(play_slider,0,LV_ANIM_OFF);//初始值
lv_slider_set_range(play_slider, 0, 100);//范围
/*在滑条下创建标签*/
time_length_label = lv_label_create(cont);
lv_label_set_text(time_length_label, "0:00");
lv_obj_align_to(time_length_label, play_slider, LV_ALIGN_OUT_RIGHT_BOTTOM,0,20);
time_pos_label = lv_label_create(cont);
lv_label_set_text(time_pos_label, "0:00");
lv_obj_align_to(time_pos_label, play_slider, LV_ALIGN_OUT_LEFT_BOTTOM,0,20);
//----------属于返回按钮的函数
void Back_btn(lv_event_t * e)
system("killall -9 mplayer");
lv_obj_del(lv_obj_get_parent((lv_obj_t *)(e->user_data)));
//显示界面
static void display_interface()
//创建背景cont,所有显示基于背景
cont = lv_obj_create(lv_scr_act());//声明一个背景
lv_obj_set_size(cont, 800, 480);//设置背景的范围
lv_obj_set_style_bg_color(cont, lv_palette_main(LV_PALETTE_LIGHT_BLUE), 0);
lv_obj_set_style_bg_grad_color(cont, lv_palette_main(LV_PALETTE_LIGHT_GREEN), 0);
lv_obj_set_style_bg_grad_dir(cont, LV_GRAD_DIR_VER, 0);
//基于cont背景创新返回按钮的对象
lv_obj_t * btn_back = lv_btn_create(cont);
lv_obj_t* lab6 = lv_label_create(btn_back);
lv_label_set_text(lab6, "x");
lv_obj_center(lab6);
lv_obj_set_style_radius(btn_back,5,0);//设置对象边角为圆角 角度自己调整中间值
lv_obj_set_size(btn_back, 30, 30);
lv_obj_set_pos(btn_back, 0, 0);
lv_obj_add_event_cb(btn_back, Back_btn, LV_EVENT_PRESSED, btn_back); //传入按钮父对象的父对象
//初始化图片父对象
init_pic_parent_obj();
init_title_obj();
//显示歌单列表
show_list();
//显示按钮
show_button();
//显示下拉列表
show_drop_down();
//显示滑动条
show_slider();
//*********************************//
//下面是视频的函数
//获取视频的路径,检测本地节目单
void get_video_path()
//读目录,avi后缀保存到数组
video_num =0;
DIR *dirp = opendir(local_video_path);
if(dirp==NULL)
perror(local_video_path);
exit(0);
struct dirent* msg;
while(1)
msg = readdir(dirp);
if(msg == NULL)break;
if(msg->d_name[0]=='.')continue;
if(strstr(msg->d_name,".avi"))
sprintf(video_path[video_num], "%s/%s", local_video_path, msg->d_name);
video_num++;
puts(video_path[video_num - 1]);
printf("检索歌单完成 共%d\\n",video_num);
//线程任务 创建子进程播放视频
void *play_video_task(void *arg)
printf("---- %ld线程任务------------------\\n",pthread_self());
//拼接命令
char cmd[1024]="mplayer -quiet -slave -zoom -x 670 -y 350 -geometry 60:0 -input file=/pipe";
sprintf(cmd,"%s %s",cmd,video_path[video_index]);
printf("命令:%s\\n", cmd);
fp_mplayer = popen(cmd, "r");
if (fp_mplayer == NULL)
perror("popen fail:");
puts("----线程任务(启动播放视频)完成 -----------------------\\n");
strcpy(cmd,"get_time_length\\n"); //获取长度
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_time_pos\\n"); //发送获取时间命令
write(fd_mplayer,cmd,strlen(cmd));
pthread_exit(NULL);//线程结束
//播放一个视频
void play_one_video()
if(play_flag != 0)//看看有没有线程在使用播放器
system("killall -9 mplayer");
play_flag=1;
printf("视频索引%d\\n", video_index);
//打开线程播放视频
pthread_t tid;
int pt = pthread_create(&tid, NULL, play_video_task, NULL);
if(pt != 0)
perror("创建进程失败");
return -1;
pthread_detach(tid);//分离属性,自动回收
if(!start)
sleep(1);
//读取mplayer的内容
pthread_create(&tid_read, NULL, read_mplayer_task, NULL);//新建线程
pthread_detach(tid_read);//分离属性,自动回收
//发送获取时间命令
pthread_create(&tid_write, NULL, write_mplayer_task, NULL);
pthread_detach(tid_write);//分离属性,自动收回
printf("tid_read %ld tid_write %ld\\n",tid_read,tid_write);
start=1;
pthread_cond_signal(&cond);//唤醒线程读取mplayer返回的内容
// *******************************************************************//
//音量
int volume=(int)lv_slider_get_value(volume_slider);
char cmd[1024]=0;
sprintf(cmd,"volume %d 1\\n",volume);
write(fd_mplayer,cmd,strlen(cmd));
//视频按键事件(没写)
static void btn_handler2(lv_event_t * e)
lv_event_code_t code = lv_event_get_code(e);
//获取传递的参数
char *msg = lv_event_get_user_data(e);
if(code == LV_EVENT_CLICKED) //点击按钮
if(strcmp(msg,"pause") == 0)
if(!start)return;
pthread_kill(tid_read,10);//暂停读mplayer返回内容
system("killall -19 mplayer");
if(strcmp(msg,"play") == 0)
if(!start)return;
system("killall -18 mplayer");//播放器继续
pthread_cond_signal(&cond);//唤醒读写mplayer
usleep(1000);
pthread_cond_signal(&cond);//防止被再次暂停
if(strcmp(msg,"forward") == 0)
if(!start)return;
usleep(1000);
char cmd[1024]="seek +10\\n";
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_percent_pos\\n");
write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令
if(strcmp(msg,"back") == 0)
if(!start)return;
usleep(10000);
char cmd[1024]="seek -10\\n";
write(fd_mplayer,cmd,strlen(cmd));
strcpy(cmd,"get_percent_pos\\n");
write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令
if(strcmp(msg,"next_music") == 0)
usleep(1000);
if(++video_index >= video_num)video_index=0;
play_one_video();
if(strcmp(msg,"prev_music") == 0)
usleep(1000);
if(--video_index <= 0)video_index=video_num-1;
play_one_video();
if(strcmp(msg,"music_show_list") == 0)
list_flag=!list_flag;
if(list_flag)
lv_obj_clear_flag(video_list,LV_OBJ_FLAG_HIDDEN);
else
lv_obj_add_flag(video_list, LV_OBJ_FLAG_HIDDEN);
//显示视频按钮
static void show_button_tv()
static lv_style_t btn_style;
lv_style_init(&btn_style);
lv_style_set_radius(&btn_style,90);
lv_style_set_bg_opa(&btn_style, LV_OPA_COVER);
lv_style_set_bg_color(&btn_style, lv_palette_lighten(LV_PALETTE_BLUE, 1));//按钮色
//Add a shadow
lv_style_set_shadow_width(&btn_style, 55);
lv_style_set_shadow_color(&btn_style, lv_palette_main(LV_PALETTE_BLUE));//背景色
//按钮的标签
lv_obj_t *label;
//暂停按钮
lv_obj_t *btn_pause = lv_btn_create(cont);
//按钮事件
lv_obj_add_event_cb(btn_pause, btn_handler2, LV_EVENT_ALL,"pause");
//位置
lv_obj_align(btn_pause, LV_ALIGN_BOTTOM_MID,40,0);
//大小
lv_obj_set_size(btn_pause,60,60);
//图标
lv_obj_set_style_bg_img_src(btn_pause,LV_SYMBOL_PAUSE,0);
//播放按钮
lv_obj_t *btn_play = lv_btn_create(cont);
lv_obj_add_event_cb(btn_play, btn_handler2, LV_EVENT_ALL,"play");
lv_obj_align(btn_play, LV_ALIGN_BOTTOM_MID,-40,0);
lv_obj_set_size(btn_play,60,60);
lv_obj_set_style_bg_img_src(btn_play,LV_SYMBOL_PLAY,0);
//快进
lv_obj_t *btn_forward = lv_btn_create(cont);
lv_obj_add_event_cb(btn_forward, btn_handler2, LV_EVENT_ALL,"forward");
lv_obj_set_size(btn_forward,60,60);
lv_obj_align(btn_forward, LV_ALIGN_BOTTOM_MID,120,0);
lv_obj_set_style_bg_img_src(btn_forward,LV_SYMBOL_RIGHT LV_SYMBOL_RIGHT,0);
//快退
lv_obj_t *btn_back = lv_btn_create(cont);
lv_obj_add_event_cb(btn_back, btn_handler2, LV_EVENT_ALL,"back");
lv_obj_set_size(btn_back,60,60);
lv_obj_align(btn_back, LV_ALIGN_BOTTOM_MID,-120,0);
lv_obj_set_style_bg_img_src(btn_back,LV_SYMBOL_LEFT LV_SYMBOL_LEFT,0);
//下一首
lv_obj_t *btn_next = lv_btn_create(cont);
lv_obj_add_event_cb(btn_next, btn_handler2, LV_EVENT_ALL,"next_music");
lv_obj_set_size(btn_next,60,60);
lv_obj_align(btn_next, LV_ALIGN_BOTTOM_MID,200,0);
lv_obj_set_style_bg_img_src(btn_next,LV_SYMBOL_NEXT,0);
//上一首
lv_obj_t *btn_prev = lv_btn_create(cont);
lv_obj_add_event_cb(btn_prev, btn_handler2, LV_EVENT_ALL,"prev_music");
lv_obj_set_size(btn_prev,60,60);
lv_obj_align(btn_prev, LV_ALIGN_BOTTOM_MID,-200,0);
lv_obj_set_style_bg_img_src(btn_prev,LV_SYMBOL_PREV,0);
//显示,隐藏 歌单列表
//风格设置
static lv_style_t style;
lv_style_init(&style);
//设置背景颜色和半径
lv_style_set_radius(&style, 5);
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_bg_color(&style, lv_palette_lighten(LV_PALETTE_GREY, 1));
//添加一个影子
lv_style_set_shadow_width(&style, 55);
lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_BLUE));
//视频单列表
lv_obj_t *btn_list = lv_btn_create(cont);
lv_obj_add_event_cb(btn_list, btn_handler2, LV_EVENT_ALL,"music_show_list");
lv_obj_set_size(btn_list,60,60);
lv_obj_align(btn_list, LV_ALIGN_BOTTOM_RIGHT,-20,0);
label = lv_label_create(btn_list);
lv_obj_add_style(label, &font_style, 0);
lv_label_set_text(label, "menu");
lv_obj_center(label);
//视频滑动条事件
static void slider_event_cb2(lv_event_t * e)
if(!start)return;
//获取传递的参数
char *msg = lv_event_get_user_data(e);
//puts(msg);
if(strcmp(msg,"volume")==0)
lv_obj_t * slider = lv_event_get_target(e);//获取事件对象
char buf[8];
int volume=(int)lv_slider_get_value(slider);//获取值
lv_snprintf(buf, sizeof(buf), "%d",volume);
lv_label_set_text(volume_label, buf); //更新音量标签值
lv_obj_align_to(volume_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
usleep(100); //修改音量值
char cmd[1024]=0;
sprintf(cmd,"volume %d 1\\n",volume);
write(fd_mplayer,cmd,strlen(cmd));
if(strcmp(msg,"play")==0)
puts("松开了");
if(start)//启动就先暂停
pthread_kill(tid_read,10);//暂停读mplayer返回内容
system("killall -19 mplayer");
int rate = (int)lv_slider_get_value(play_slider);//获取值
float new_time = time_length * rate * 0.01;
int seek_time = new_time - time_pos;
char cmd[1024]=0;
sprintf(cmd,"seek %d\\n",seek_time);
//puts(cmd);
write(fd_mplayer,cmd,strlen(cmd));
system("killall -18 mplayer");//播放器继续
pthread_cond_signal(&cond);//唤醒读写mplayer
usleep(1000);
pthread_cond_signal(&cond);//防止被再次暂停
//视频显示滑动条
static void show_slider_tv(void)
//音量
volume_slider = lv_slider_create(cont);
lv_obj_align(volume_slider,LV_ALIGN_LEFT_MID,0,20);//位置
lv_obj_add_event_cb(volume_slider, slider_event_cb2, LV_EVENT_VALUE_CHANGED, "volume");//事件
lv_obj_set_size(volume_slider,18,180);//大小
lv_slider_set_value(volume_slider,100,LV_ANIM_OFF);//初始值
//标签 音量大小
volume_label = lv_label_create(cont);
lv_label_set_text(volume_label, "100");
lv_obj_align_to(volume_label, volume_slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 5);
lv_obj_t *label = lv_label_create(cont);
lv_obj_add_style(label, &font_style, 0);
lv_label_set_text(label, "volume");
lv_obj_align_to(label, volume_label, LV_ALIGN_OUT_TOP_MID, 0, -210);
//播放进度条
play_slider = lv_slider_create(cont);
lv_obj_align(play_slider,LV_ALIGN_CENTER,0,135);//位置
lv_obj_set_width(play_slider,600);//宽度
lv_obj_add_event_cb(play_slider, slider_event_cb2, LV_EVENT_RELEASED , "play");//事件
lv_slider_set_value(play_slider,0,LV_ANIM_OFF);//初始值
lv_slider_set_range(play_slider, 0, 100);//范围
//在滑条下创建标签
time_length_label = lv_label_create(cont);
lv_label_set_text(time_length_label, "0:00");
lv_obj_align_to(time_length_label, play_slider, LV_ALIGN_OUT_RIGHT_BOTTOM,0,20);
time_pos_label = lv_label_create(cont);
lv_label_set_text(time_pos_label, "0:00");
lv_obj_align_to(time_pos_label, play_slider, LV_ALIGN_OUT_LEFT_BOTTOM,0,20);
//列表处理函数,播放列表中的视频(没写)
static lv_event_cb_t event_handler_video_list(lv_event_t * e)
//获取事件码
lv_event_code_t code = lv_event_get_code(e);
//获取事件对象,这里是按钮
lv_obj_t * obj = lv_event_get_target(e);
//如果点击按钮
if(code == LV_EVENT_CLICKED)
printf("Clicked %s\\n", lv_list_get_btn_text(video_list, obj));
//当前播放中的video下标更新为点击列表的下标
video_index = lv_event_get_user_data(e);
play_one_video();
//显示节目单列表
static void show_list2()
//创建列表文本框
video_list = lv_list_create(cont);
//添加风格
lv_obj_add_style(video_list, &font_style, 0);
lv_obj_set_size(video_list, 75, 300);
//列表位置
//lv_obj_center(music_list);
lv_obj_align(video_list, LV_ALIGN_RIGHT_MID, 5, -80);
//添加文本
lv_list_add_text(video_list, "list");
//在列表中添加按钮
lv_obj_t *btn;
for(int i = 0; i < video_num; i++)
char tmp[100]=0;
char *p = video_path[i];
p = strrchr(p,'/');
strcpy(tmp,++p);//裁剪
// 参数:列表对象,图标宏,按钮名
btn = lv_list_add_btn(video_list, NULL,strtok(tmp,"."));
//列表按钮风格
lv_obj_add_style(video_list, &font_style, 0);
// 触发事件,把下标传递
lv_obj_add_event_cb(btn, event_handler_video_list, LV_EVENT_CLICKED, i);
static void k(lv_event_t *e)
system("killall -9 mplayer");
//视频显示界面
static void display_interface2()
//创建背景cont,所有显示基于背景
cont = lv_obj_create(lv_scr_act());//声明一个背景
lv_obj_set_size(cont, 800, 480);//设置背景的范围
lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE);
//基于cont背景创新返回按钮的对象
lv_obj_t *btn_back = lv_btn_create(cont);
lv_obj_t *lab6 = lv_label_create(btn_back);
lv_label_set_text(lab6, "x");
lv_obj_center(lab6);
lv_obj_set_style_radius(btn_back,5,0);//设置对象边角为圆角 角度自己调整中间值
lv_obj_set_size(btn_back, 30, 30);
lv_obj_set_pos(btn_back, 0, 0);
lv_obj_add_event_cb(btn_back, Back_btn, LV_EVENT_PRESSED, btn_back); //传入按钮父对象的父对象
//整一个杀视频的按钮
lv_obj_t* btn01 = lv_btn_create(cont);
lv_obj_align(btn01, LV_ALIGN_BOTTOM
粤嵌gec6818LED屏幕上画图 太极图 图片显示 电子相册 2048小游戏 实现识别触摸坐标的识别 电子自助点餐设计等项目
交叉开发
在一个有编辑/编译功能的PC机上进行编辑/编译,生成的可执行文件通过
交叉开发工具下载到目标机(GEC-6818)
开发板 --- Linux内核 --- Linux指令
首先创建自己的工作目录
mkdir xxx
下载交叉编译生成的可执行文件:
rx 可执行文件名
传输 --- 发送xmodem --- 浏览到我们所要发送的文件 --- 选中 --- 发送
如果发送的是一个可执行文件,没有可执行的权限
chmod +x 可执行文件名 --- 再去运行
!!! 下载可执行文件必须是交叉编译生成的
arm-linux-gcc 源文件名 -o 可执行文件名
2 屏幕操作
屏幕分辨率:800*480
800 一行有800个像素点 480行
像素点:显示颜色的最小单位
颜色:ARGB --- 每个分量一个字节
A:透明度
R:红色分量 0 - ff
G:绿色分量
B:蓝色分量
绿色:0x0000ff00
如果我们想要绿屏:
每个像素点全部显示绿色:0x0000ff00
打开屏幕
int lcd_fd = open("/dev/fb0",O_RDWR);
if(lcd_fd == -1)
perror("open lcd fail");
return -1;
操作屏幕
//写入数据
int color[800*480]=0;
for(int i=0;i<480;i++)
for(int j=0;j<800;j++)
color[i*800+j]=0x0000ff00;
write(lcd_fd,color,800*480*4);
关闭屏幕
close(lcd_fd);
因为引用了 #include<math.h>
切记 切记 Liunx 编译时 要加 -lm
类似 arm-linux-gcc 1.c -lm
画太极图
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/mman.h>
#include<unistd.h>
#include<math.h>
int *plcd = NULL;
#define WHITE 0x00FFFFFF
#define BLAK 0x00000000
void draw_point(int x, int y, int color)
if (x >= 0 && x<800 && y >= 0 && y<480)
*(plcd + y * 800 + x) = color;
void draw_circle(int x, int y,double r ,int color)
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void draw_circle_b(int x, int y,double r ,int color)
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
if(i<x)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void clear(int color)
int x,y;
for(y=0;y<480;y++)
for(x=0;x<800;x++)
draw_point(x,y,color);
int main()
int lcd_fd = open("/dev/fb0",O_RDWR);
if (lcd_fd == -1)
perror("open lcd fail");
plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
if (plcd==NULL)
perror("mmao fail");
int color = 0x0000FFFF;
clear(0x00666666);
draw_circle(240, 400,200, BLAK);
draw_circle_b(240, 400,200, WHITE);
draw_circle(240, 300,100, WHITE);
draw_circle(240, 500,100, BLAK);
draw_circle(240, 300,25, BLAK);
draw_circle(240, 500,25, WHITE);
// draw_circle(240, 400,50, color);
close(lcd_fd);
munmap(plcd,800*480*4);
return 0;
画笑脸
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/mman.h>
#include<unistd.h>
#include<math.h>
#define WHITE 0x00FFFFFF
#define BLAK 0x00000000
#define org 0x00CDAD00
#define gray 0x00CD853F
int *plcd = NULL;
void draw_point(int x, int y, int color)
if (x >= 0 && x<800 && y >= 0 && y<480)
*(plcd + y * 800 + x) = color;
void draw_circle(int x, int y,double r ,int color)//HUAYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void draw_circle_b(int x, int y,double r ,int color)//BANYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
if(i<x)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void draw_circle_c(int x, int y,double r ,int color)//BANYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
if(i>x)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void clear(int color)
int x,y;
for(y=0;y<480;y++)
for(x=0;x<800;x++)
draw_point(x,y,color);
int main()
int lcd_fd = open("/dev/fb0",O_RDWR);
if (lcd_fd == -1)
perror("open lcd fail");
plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
if (plcd==NULL)
perror("mmap fail");
int color = 0x0000FFFF;
clear(0x00666666);
draw_circle(240, 400,200, org);//画橙底
//draw_circle(180, 480,30, HUI);//眼睛1
//draw_circle(180, 320,30, HUI); //眼睛2
draw_circle_b(170, 300,50, gray);
draw_circle_b(170, 300,40, org);
draw_circle_b(170, 500,50, gray);
draw_circle_b(170, 500,40, org);
//draw_circle(240, 300,25, BLAK);
//draw_circle(240, 500,25, WHITE);
draw_circle_c(250, 400,150, WHITE);
// draw_circle(240, 400,50, color);
int x,y;
for(y=0;y<480;y++)
for(x=0;x<800;x++)
if (x >=400 && x<402 && y >=250 && y<400 )
draw_point(x,y,BLAK);
if (x >=300 && x<302 && y >=250 && y<362 )
draw_point(x,y,BLAK);
if (x >=500 && x<502 && y >=250 && y<362 )
draw_point(x,y,BLAK);
close(lcd_fd);
munmap(plcd,800*480*4);
return 0;
画微笑
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/mman.h>
#include<unistd.h>
#include<math.h>
#define WHITE 0x00FFFFFF
#define BLAK 0x00000000
#define org 0x00CDAD00
#define HUI 0x00CD853F
int *plcd = NULL;
void draw_point(int x, int y, int color)
if (x >= 0 && x<800 && y >= 0 && y<480)
*(plcd + y * 800 + x) = color;
void draw_circle(int x, int y,double r ,int color)//HUAYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void draw_circle_b(int x, int y,double r ,int color)//BANYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
if(i>x)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void clear(int color)
int x,y;
for(y=0;y<480;y++)
for(x=0;x<800;x++)
draw_point(x,y,color);
int main()
int lcd_fd = open("/dev/fb0",O_RDWR);
if (lcd_fd == -1)
perror("open lcd fail");
plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
if (plcd==NULL)
perror("mmao fail");
int color = 0x0000FFFF;
clear(0x00666666);
draw_circle(240, 400,200, org);//画橙底
draw_circle(180, 480,30, HUI);//眼睛1
draw_circle(180, 320,30, HUI); //眼睛2
draw_circle_b(270, 400,50, HUI);
draw_circle_b(270, 400,40, org);
//draw_circle(240, 300,25, BLAK);
//draw_circle(240, 500,25, WHITE);
// draw_circle(240, 400,50, color);
close(lcd_fd);
munmap(plcd,800*480*4);
return 0;
四叶草 彩虹
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/mman.h>
#include<unistd.h>
#include<math.h>
#define WHITE 0x00FFFFFF
#define BLAK 0x00000000
#define org 0x00CDAD00
#define HUI 0x00CD853F
int *plcd = NULL;
void draw_point(int x, int y, int color)
if (x >= 0 && x<800 && y >= 0 && y<480)
*(plcd + y * 800 + x) = color;
void draw_circle(int x, int y,double r ,int color)//HUAYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void draw_circle_b(int x, int y,double r ,int color)//BANYUAN
if (x >= 0 && x<480 && y >= 0 && y<800)
for (double i = 0; i < 480; i++)
for (double j = 0; j < 800; j++)
if(i>x)
double all=(i-x)*(i-x)+(j-y)*(j-y);
double fc=sqrt(all);
if(r>fc)
draw_point(j, i, color);
// printf("fc=%lf\\n",fc);
void clear(int color)
int x,y;
for(y=0;y<480;y++)
for(x=0;x<800;x++)
draw_point(x,y,color);
int main()
int lcd_fd = open("/dev/fb0",O_RDWR);
if (lcd_fd == -1)
perror("open lcd fail");
plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
if (plcd==NULL)
perror("mmao fail");
int color = 0x0000FFFF;
clear(0x00666666);
while(1)
int x,y;
for(x=0;x<800;x++)
for(y=0;y<480;y++)
if(y<160)
*(plcd + y * 800 + x) = 0x0000ff00;
else if(y<320)
*(plcd + y * 800 + x) = 0x000000ff;
else
*(plcd + y * 800 + x) = 0x00ff0000;
draw_circle(240, 400,200, org);//画橙底
draw_circle_b(270, 400,50, HUI);
draw_circle_b(270, 400,40, org);
draw_circle(180, 480,30, HUI);//眼睛1
draw_circle(180, 320,30, HUI); //眼睛2
int i,j;
int cir_color[480][800];
for(i=0;i<480;i++)
for(j=0;j<800;j++)
if((i-480)*(i-480) + (j-400)*(j-400)<51*51)
cir_color[i][j]=0x00FF0033;
else if((i-480)*(i-480) + (j-400)*(j-400)<107*107)
cir_color[i][j]=0x00FF6600;
else if((i-480)*(i-480) + (j-400)*(j-400)<168*168)
cir_color[i][j]=0x00FFFF00;
else if((i-480)*(i-480) + (j-400)*(j-400)<234*234)
cir_color[i][j]=0x0000FF00;
else if((i-480)*(i-480) + (j-400)*(j-400)<307*307)
cir_color[i][j]=0x0000FFFF;
else if((i-480)*(i-480) + (j-400)*(j-400)<385*385)
cir_color[i][j]=0x000000FF;
else
cir_color[i][j]=0x00FF00CC;
lcd_fd = open("/dev/fb0",O_RDWR);
if(-1 == lcd_fd)
printf("open lcd error\\n");
write(lcd_fd,cir_color,800*480*4);
sleep(2);
int si_color[480][800];
for(i=0;i<480;i++)
//遍历二维数组每一行的每一列
for(j=0;j<800;j++)
int a = (i-150)*(i-150) + (j-300)*(j-300);
int b = (i-330)*(i-330) + (j-300)*(j-300);
int c = (i-150)*(i-150) + (j-500)*(j-500);
int d = (i-330)*(i-330) + (j-500)*(j-500);
int r2 = 150*150;
if (a<r2 && b<r2)
si_color[i][j]=0x00FF0033;
else if(a<r2 && c<r2)
si_color[i][j]=0x00FF6600;
else if(b<r2 && d<r2)
si_color[i][j]=0x00FFFF00;
else if(c<r2 && d<r2)
si_color[i][j]=0x0000FF00;
else
si_color[i][j]=0x00FF00CC;
lcd_fd = open("/dev/fb0",O_RDWR);
if(-1 == lcd_fd)
printf("open lcd error\\n");
write(lcd_fd,si_color,800*480*4);
sleep(1);
close(lcd_fd);
munmap(plcd,800*480*4);
return 0;
切记 切记 Liunx 编译时 要加 -lm
电子相册代码实现
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <math.h>
#include <stdlib.h>
int * p = NULL ;
void draw_point(int x,int y,int color)
if(x>=0 && x<800 && y>=0 && y<480 )
*(p+800*y+x) = color ;
void show_bmp (char * pathname ,int x ,int y)
int fd = open(pathname,O_RDONLY);
if(fd == -1)
perror("open error\\n");
return ;
int fd1 = open("/dev/fb0",O_RDWR);
if(fd1 == -1)
perror("open error\\n");
return ;
printf("open success\\n");
p = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED ,fd1,0);
if(p == NULL )
perror("mmap error\\n");
return ;
int width,height;
short depth;
unsigned char buf[4] ;
//读取宽度
lseek(fd,0x12,SEEK_SET);
read(fd,buf,4);
width = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取高度
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];
//打印信息
printf("width = %d height = %d depth = %d \\n",width,height,depth);
int line_valid_bytes = abs(width) * depth / 8 ;
int laizi=0;
if( (line_valid_bytes % 4) !=0 )
laizi = 4 - line_valid_bytes%4;
int line_bytes = line_valid_bytes + laizi ;
int total_bytes = line_bytes * abs(height) ;
unsigned char * p1 = malloc(total_bytes);
lseek(fd,54,SEEK_SET);
read(fd,p1,total_bytes);
unsigned char a ,r ,g, b ;
int i = 0;
int x0=0,y0=0;
int color ;
for(y0=0;y0<abs(height);y0++)
for(x0=0;x0<abs(width);x0++)
b = p1[i++];
g = p1[i++];
r = p1[i++];
if(depth == 32)
a=p1[i++];
if(depth == 24)
a = 0;
color = a << 24 | r << 16 | g << 8 | b ;
draw_point(width>0?x+x0:abs(width)+x-1-x0,
height>0? y+height-1-y0 : y+y0,color);
i = i +laizi ;
free(p1);
close(fd1);
munmap(p,800*480*4);
close(fd);
int main()
while(1)
show_bmp("1.bmp",0 ,0);// 自己存储的图片
sleep(2);
show_bmp("2.bmp",0 ,0);
sleep(2);
show_bmp("3.bmp",0 ,0);
sleep(2);
show_bmp("4.bmp",0 ,0);
sleep(2);
show_bmp("5.bmp",0 ,0);
sleep(2);
return 0;
横行打开
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <math.h>
#include <stdlib.h>
#define RGB_SIZE 800*480*3
#define LCD_SIZE 800*480
int *plcd=NULL;
int photo(char *a)
// 1. 打开触摸屏文件
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
printf("Open lcd failed!!\\n");
return -1;
// 2. 打开bmp图片
int bmp_fd = open(a, O_RDWR);
// 3. 偏移bmp格式头, 54个字节
off_t offset = lseek(bmp_fd, 54, SEEK_SET);
if (offset == -1)
printf("Offset failed!\\n");
return -1;
// 4. 读取bmp图片的RGB值,将读到的值存进bmp_rgb数组中
char bmp_buf[RGB_SIZE] = ;
size_t re_ret = read(bmp_fd, bmp_buf, RGB_SIZE);
// 5. 24位数据-->32位数据:bmp图片rgb占3个字节,lcdargb占4个字节. char占1个字节大小,int占4个字节大小
int lcd_buf[LCD_SIZE] = ;
int i;
for (i=0; i<LCD_SIZE; i++)
lcd_buf[i] = bmp_buf[i*3+2]<<16 | bmp_buf[i*3+1]<<8 | bmp_buf[i*3+0]<<0;
// 6. 翻转180°
int fli_buf[LCD_SIZE];
int x, y;
for(y = 0; y < 480; y++)
for(x = 0; x < 800; x++)
fli_buf[y*800+x] = lcd_buf[(479-y)*800+x];
// 7. 写入LCD
plcd=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(plcd == NULL)
perror("mmap fail");
for(int x=0;x<800;x++)
for(int y=0;y<480;y++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
// 8. 关闭文件
close(lcd_fd);
close(bmp_fd);
return 0;
int photo2(char *a)
// 1. 打开触摸屏文件
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
printf("Open lcd failed!!\\n");
return -1;
// 2. 打开bmp图片
int bmp_fd = open(a, O_RDWR);
// 3. 偏移bmp格式头, 54个字节
off_t offset = lseek(bmp_fd, 54, SEEK_SET);
if (offset == -1)
printf("Offset failed!\\n");
return -1;
// 4. 读取bmp图片的RGB值,将读到的值存进bmp_rgb数组中
char bmp_buf[RGB_SIZE] = ;
size_t re_ret = read(bmp_fd, bmp_buf, RGB_SIZE);
// 5. 24位数据-->32位数据:bmp图片rgb占3个字节,lcdargb占4个字节. char占1个字节大小,int占4个字节大小
int lcd_buf[LCD_SIZE] = ;
int i;
for (i=0; i<LCD_SIZE; i++)
lcd_buf[i] = bmp_buf[i*3+2]<<16 | bmp_buf[i*3+1]<<8 | bmp_buf[i*3+0]<<0;
// 6. 翻转180°
int fli_buf[LCD_SIZE];
int x, y;
for(y = 0; y < 480; y++)
for(x = 0; x < 800; x++)
fli_buf[y*800+x] = lcd_buf[(479-y)*800+x];
// 7. 写入LCD
plcd=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(plcd == NULL)
perror("mmap fail");
for(int y=0;y<480;y++)
for(int x=0;x<800;x++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
// 8. 关闭文件
close(lcd_fd);
close(bmp_fd);
return 0;
int photo3(char *a)
// 1. 打开触摸屏文件
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
printf("Open lcd failed!!\\n");
return -1;
// 2. 打开bmp图片
int bmp_fd = open(a, O_RDWR);
// 3. 偏移bmp格式头, 54个字节
off_t offset = lseek(bmp_fd, 54, SEEK_SET);
if (offset == -1)
printf("Offset failed!\\n");
return -1;
// 4. 读取bmp图片的RGB值,将读到的值存进bmp_rgb数组中
char bmp_buf[RGB_SIZE] = ;
size_t re_ret = read(bmp_fd, bmp_buf, RGB_SIZE);
// 5. 24位数据-->32位数据:bmp图片rgb占3个字节,lcdargb占4个字节. char占1个字节大小,int占4个字节大小
int lcd_buf[LCD_SIZE] = ;
int i;
for (i=0; i<LCD_SIZE; i++)
lcd_buf[i] = bmp_buf[i*3+2]<<16 | bmp_buf[i*3+1]<<8 | bmp_buf[i*3+0]<<0;
// 6. 翻转180°
int fli_buf[LCD_SIZE];
int x, y;
for(y = 0; y < 480; y++)
for(x = 0; x < 800; x++)
fli_buf[y*800+x] = lcd_buf[(479-y)*800+x];
// 7. 写入LCD
plcd=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(plcd == NULL)
perror("mmap fail");
for(int x=0;x<400;x++)
for(int y=0;y<240;y++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
for(int x=400;x<800;x++)
for(int y=0;y<240;y++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
for(int x=0;x<400;x++)
for(int y=240;y<480;y++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
for(int x=400;x<800;x++)
for(int y=240;y<480;y++)
*(plcd+x+y*800)=fli_buf[x+y*800];
sleep(0.1);
// 8. 关闭文件
close(lcd_fd);
close(bmp_fd);
return 0;
void main()
while(1)
photo3("./1.bmp");
sleep(0.5);
photo3("./2.bmp");
sleep(0.5);
photo("./3.bmp");
sleep(0.5);
如何使用触摸屏
Linux为输入事件提供了一个专门的结构体
#include <linux/input.h>
struct input_event
struct timeval time;//记录事件发生的时间
_u16 type; //记录事件的类型
type == EV_ABS 触摸屏事件
type == EV_KEY 按键事件
_u16 code; //随着type的改变而改变
type == EV_ABS
code == ABS_X x轴
code == ABS_y y轴
type == EV_KEY
code == BTN_TOUCH
_s32 value; //随着code的变化而变化
code == ABS_X
value = x x值
code == ABS_Y
value = y y值
code == BTN_TOUCH
value == 0 表示松开
value == 1 表示按下
触摸屏的获取
获取坐标
打开设备 --- 读取内容 --- 解析 --- 关闭设备
int touch_fd = open("/dev/input/event0",O_RDONLY);
if(touch_fd == -1)
perror("open touch fail");
return -1;
struct input_event ev;
int x=-1,y=-1;
while(1)
read(touch_fd,&ev,sizeof(ev));
if(ev.type == EV_ABS && ev.code == ABS_X)
x = ev.value;
if(ev.type == EV_ABS && ev.code == ABS_Y)
y = ev.value;
if(ev.type == EV_KEY && ev.code == BTN_TOUCH)
if(ev.value == 0)
printf("Release\\n");
break;
else if(ev.value == 1)
printf("Press\\n");
printf("x=%d y=%d\\n",x,y);
close(touch_fd);
#include <stdio.h>//printf
#include <linux/input.h>//struct input_event
#include <sys/types.h>//open
#include <sys/stat.h>//open
#include <fcntl.h>//open
#include <unistd.h>//read
#include <stdlib.h>
#include <sys/mman.h>
#include<linux/fb.h>
#include <math.h>
int * p = NULL ;
void draw_point(int x,int y,int color)
if(x>=0 && x<800 && y>=0 && y<480 )
*(p+800*y+x) = color ;
void show_bmp (char * pathname ,int x ,int y)
int fd = open(pathname,O_RDONLY);
if(fd == -1)
perror("open error\\n");
return ;
int fd1 = open("/dev/fb0",O_RDWR);
if(fd1 == -1)
perror("open error\\n");
return ;
printf("open success\\n");
p = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED ,fd1,0);
if(p == NULL )
perror("mmap error\\n");
return ;
int width,height;
short depth;
unsigned char buf[4] ;
//读取宽度
lseek(fd,0x12,SEEK_SET);
read(fd,buf,4);
width = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取高度
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];
//打印信息
printf("width = %d height = %d depth = %d \\n",width,height,depth);
int line_valid_bytes = abs(width) * depth / 8 ;
int laizi=0;
if( (line_valid_bytes % 4) !=0 )
laizi = 4 - line_valid_bytes%4;
int line_bytes = line_valid_bytes + laizi ;
int total_bytes = line_bytes * abs(height) ;
unsigned char * p1 = malloc(total_bytes);
lseek(fd,54,SEEK_SET);
read(fd,p1,total_bytes);
unsigned char a ,r ,g, b ;
int i = 0;
int x0=0,y0=0;
int color ;
for(y0=0;y0<abs(height);y0++)
for(x0=0;x0<abs(width);x0++)
b = p1[i++];
g = p1[i++];
r = p1[i++];
if(depth == 32)
a=p1[i++];
if(depth == 24)
a = 0;
color = a << 24 | r << 16 | g << 8 | b ;
draw_point(width>0?x+x0:abs(width)+x-1-x0,
height>0? y+height-1-y0 : y+y0,color);
i = i +laizi ;
free(p1);
close(fd1);
munmap(p,800*480*4);
close(fd);
int main()
int touch_fd = open("/dev/input/event0",O_RDONLY);
if(touch_fd == -1)
perror("open touch fail");
return -1;
struct input_event ev;
int x=-1,y=-1;
while(1)
while(1)
read(touch_fd,&ev,sizeof(ev));
if(ev.type == EV_ABS && ev.code == ABS_X)
x = ev.value;
if(ev.type == EV_ABS && ev.code == ABS_Y)
y = ev.value;
if(ev.type == EV_KEY && ev.code == BTN_TOUCH)
if(ev.value == 0)
printf("Release\\n");
break;
else if(ev.value == 1)
printf("Press\\n");
printf("x=%d y=%d\\n",x,y);
if (x>0&& y<400)
show_bmp("1.bmp", 0, 0);
if (x>400 && y<800)
show_bmp("2.bmp", 0, 0);
close(touch_fd);
return 0;
2048小游戏c语言代码
2048游戏规则:每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。
参考思路 :
第一步
给屏幕上背景色(红、蓝....)
第二步
中心画一个正方形400*400(这里也可以画大一点,每张图之间保留一点空隙,使游戏更美观)
第三步
找11张100*100的图片(2,4,8,16...2048)
第四步
初始化棋盘,游戏开始,在16个位置上随机出现2,4,8中的一张图片,共出现3张
(概率自己弄,如出现2的概率50%,4个概率25%,8个概率25%)
第五步
手指滑屏怎么实现图片的上下左右移动,同时相同的图片相加变成一张图片
如,两张图片2变更成一张图片4
同时,滑动后在没有图片的地方生成一张新的图片(同第四步,只是这里出现一张图)
第六步
判断游戏结束
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include<linux/fb.h>
#include <math.h>
#include <errno.h>
#include <time.h>
int lcd_fd, ts_fd;
int *lcd_ptr;
int game_over;
int get_finger_direction();
struct bmp_header //14
unsigned char type[2];
unsigned long size;
unsigned short reserverd1;
unsigned short reserverd2;
unsigned long offbit;
__attribute__((packed)); //字节对齐
struct bmp_info //40
unsigned int size;
unsigned int width;
unsigned int height;
unsigned short planes;
unsigned short bitcount;
unsigned int bitcompression;
unsigned int sizeimg;
unsigned int xpelspermeter;
unsigned int ypelspermeter;
unsigned int biclrused;
unsigned int important;
__attribute__((packed)); //字节对齐
//数组初始化,将所有的图片保存在一个数组中
const char *bmp_files[] =
"/pic/bmp/digit_2.bmp", "/pic/bmp/digit_4.bmp",
"/pic/bmp/digit_8.bmp", "/pic/bmp/digit_16.bmp",
"/pic/bmp/digit_32.bmp", "/pic/bmp/digit_64.bmp",
"/pic/bmp/digit_128.bmp", "/pic/bmp/digit_256.bmp",
"/pic/bmp/digit_512.bmp", "/pic/bmp/digit_1024.bmp",
"/pic/bmp/digit_2048.bmp", "/pic/bmp/digit_4096.bmp",
"/pic/bmp/digit_8192.bmp", "/pic/bmp/digit_16384.bmp",
"/pic/bmp/digit_32768.bmp", "/pic/bmp/digit_65536.bmp"
;
//棋盘矩阵的初始化
int array[4][4] = 0;
//根据要显示的数字来返回对应的文件名的下标
int get_bmp_files_index(int x)
if (x == 2)
return 0;
else if (x == 4)
return 1;
else if (x == 8)
return 2;
else if (x == 16)
return 3;
else if (x == 32)
return 4;
else if (x == 64)
return 5;
else if (x == 128)
return 6;
else if (x == 256)
return 7;
else if (x == 512)
return 8;
else if (x == 1024)
return 9;
else if (x == 2048)
return 10;
else if (x == 4096)
return 11;
else if (x == 8192)
return 12;
else if (x == 16384)
return 13;
else if (x == 32768)
return 14;
else if (x == 65536)
return 15;
return -1;
//求棋盘矩阵里面有多少个0
int rectangle_get_zero_num()
int i, j, count = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (array[i][j] == 0)
count++;
return count;
int rectangle_set_value(int z, int value)
int i, j, count = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (array[i][j] == 0)
count++;
if (count == z)
array[i][j] = value;
return 0;
//触摸屏滑屏算法实现
int get_xy_v2()
struct input_event ts;
int x1 = -1, y1 = -1;
int x2, y2;
int x_read = 0, y_read =1;
// x1, y1, x2,y2
//2, read coord
while (1)
read(ts_fd, &ts, sizeof(ts));
if (ts.type == EV_ABS && ts.code == ABS_X && x_read == 0)
if (x1 == -1)
x1 = ts.value;
x2 = ts.value;
x_read = 1;
y_read = 0;
if (ts.type == EV_ABS && ts.code == ABS_Y && y_read == 0)
if (y1 == -1)
y1 = ts.value;
y2 = ts.value;
x_read = 0;
y_read = 1;
if (x_read && y_read)
break;
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == KEY_RESERVED)
int num1 = x2-x1;
int num2 = y2-y1;
if (num1 > 0)
return 1;
else if (num1 < 0)
return 2;
if (num2 < 0)
return 3;
else if (num2 > 0)
return 4;
break;
/*
fin_left:手指左划后棋子移动及合并的方式
*/
void fin_left()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value, save_zero;
for(i = 0; i < 4; i++)
value = 0;
save_zero= 0;
for(j = 0; j < 4 ; j++)
if (array[i][j] == 0)
continue;
if (value == 0)
value = array[i][j];
else
if (value == array[i][j])
array[i][save_zero++] = value * 2;
value = 0;
else
array[i][save_zero++] = value;
value = array[i][j];
array[i][j] = 0;
if (value != 0)
array[i][save_zero] = value;
//draw_matrix();
/*
fin_right:手指上划后棋子移动及合并的方式
*/
void fin_right()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for (i = 0; i < 4; i++)
value = 0;
save_zero = 4 -1;
for (j = 4 - 1; j >= 0 ; j--)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[i][save_zero--] = 2 * value;
value = 0;
else
array[i][save_zero--] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[i][save_zero] = value;
/*
fin_up:手指上划后棋子移动及合并的方式
*/
void fin_up()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for(j = 0; j < 4; j++)
value = 0;
save_zero= 0;
for(i = 0; i < 4 ; i++)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[save_zero++][j] =2 * value;
value = 0;
else
array[save_zero++][j] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[save_zero][j] = value;
//draw_matrix();
/*
fin_down:手指上划后棋子移动及合并的方式
*/
void fin_down()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for(j = 0; j < 4; j++)
value = 0;
save_zero = 4 - 1;
for(i = 4 - 1; i >= 0 ; i--)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[save_zero--][j] = 2 * value;
value = 0;
else
array[save_zero--][j] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[save_zero][j] = value;
/*
change_matrix:根据手指滑动(direction),
变换棋盘矩阵
*/
int change_matrix()
int direction = get_finger_direction();
if (direction == 1)
fin_left();
else if (direction == 2)
fin_right();
else if (direction == 3)
fin_up();
else
fin_down();
/*
lcd_draw_point:在屏幕坐为(x, y)这个点,填充color
这个颜色值。
@x: x轴坐标
@y:y轴坐标
@color:要填充的辨色值
返回值:
无返回值。
*/
void lcd_draw_point(int x, int y, int color)
int *p = lcd_ptr;
if (x >= 0 && x < 800 && y>=0 && y < 480)
*(p +800*y + x) = color;
/*
lcd_draw_dect: 在屏幕上画一个矩形,并且用
color这种颜色填充该矩形。
@x0: 该矩形的左上角的那个点x轴坐标
@y0:该矩形的左上角的那个点y轴坐标
@w:该矩形的宽
@h:该矩形的高
@color:该矩形要填充的辨色值
返回值:
无返回值。
*/
void lcd_draw_dect(int x0, int y0, int w, int h, int color)
if (x0 < 0 || y0 < 0 || w < 0 || h <0)
return;
if ((x0 + w >800) || (y0+h) > 480)
return;
int x, y;
for (y = y0; y < y0 + h; y++)
for (x = x0; x < x0 + w; x++)
lcd_draw_point(x, y , color);
/*
draw_bmp_byname:把一张bmp图片显示在屏幕上特定的位置
@bmpfile:要显示的bmp图片的文件名
@x0: 在屏幕上显示的左上角顶点的x轴坐标
@y0: 在屏幕上显示的左上角顶点的y轴坐标
@w: 位图宽度
@h: 位图高度
返回值:
无返回值.
*/
void draw_bmp_byname(const char *bmpfile, int x0, int y0, int w, int h)
int fd;
int x, y;
fd = open(bmpfile, O_RDONLY);
if (fd == -1)
perror("open bmpfile error:");
return ;
char bmpdata[w*h*3];
lseek(fd, 54, SEEK_SET);
read(fd, bmpdata, w*h*3);
close(fd);
int i = 0;
for (y = 0; y < h; y++)
unsigned char r,g ,b;
int color;
for (x = 0; x < w; x++)
b = bmpdata[i++];
g = bmpdata[i++];
r = bmpdata[i++];
color = (r << 16) | (g << 8) | b;
lcd_draw_point(x0+ x, y0 + (h -1 - y) ,color);
/*
draw_matrix:把棋盘矩阵在屏幕上显示出来
*/
void draw_matrix()
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4;j++)
int x0, y0;
x0 = 185;//棋盘矩阵左上角那个点的x轴坐标
y0 = 25;//棋盘矩阵左上角那个点的y轴坐标
if (array[i][j] == 0)
lcd_draw_dect(x0+j*110, y0+i*110, 100, 100,
0xff8080);//如果此处元素的值为0,那么
//就显示
else
int f_index = get_bmp_files_index(array[i][j]);
draw_bmp_byname(bmp_files[f_index],
x0+j*110, y0+i*110,
100,100);
/*
init_matrix:初始化棋盘矩阵
在任意x个位置,填充x个数字(2,4,8)
*/
void init_matrix()
//规则x >= 1,x <= 3
int x = (random() % 3) + 1;
int i;
/*
step1:随机产生x个数字,并填充到棋盘矩阵中去
*/
for(i = 0; i < x; i++)
int pos = (random() % rectangle_get_zero_num()) + 1;
int s[] = 2, 4, 8, 2;
int s_i = (random() % 3);
rectangle_set_value(pos, s[s_i]);
/*
step 2: 绘制棋盘矩阵
*/
draw_matrix();
/*
rand1_matrix:移动之后随机产生一个数字填充到
任意一个0的位置上
*/
void rand_matrix()
int pos = (random() % rectangle_get_zero_num()) + 1;
int s[] = 2, 4, 8, 2;
int s_i = (random() % 4);
rectangle_set_value(pos, s[s_i]);
draw_matrix();
/*
get_finger_direction:获取手指在触摸屏上面的滑动方向
返回值:
MOVE_LEFT:手指向左移动
MOVE_RIGHT:手指向右移动
MOVE_UP:手指向上移动
MOVE_DOWN:手指向下移动
*/
int get_finger_direction()
int ret;
int fd = open("/dev/input/event0", O_RDWR);
if (fd == -1)
perror("open event failed:");
return -1;
struct input_event ev;
int x1 = -1; //在滑动过程中第一个点的x轴坐标
int x2; //在滑动过程中最后一个点的x轴坐标
int y1 = -1;//在滑动过程中第一个点的y轴坐标
int y2;//在滑动过程中最后一个点的y轴坐标
while (1)
ret = read(fd, &ev, sizeof(ev));
if(ret != sizeof(ev))
continue;
if (ev.type == EV_ABS && ev.code == ABS_X)//是x轴坐标
if (x1 == -1)//x1重来没有赋过值,那么肯定是第一个点
x1 = ev.value;
x2 = ev.value;
if (ev.type == EV_ABS && ev.code == ABS_Y)//是y轴坐标
if ( y1 == -1)//y1重来没有赋过值,那么肯定是第一个点
y1 = ev.value;
y2 = ev.value;
// if (ev.type == EV_ABS && ev.code == ABS_PRESSURE//手指弹起,再计算滑动方向
// && ev.value == 0)//触摸屏压力值为0, press up
if (ev.type == EV_KEY && ev.code == BTN_TOUCH)
if(ev.value==0)
int x_cz;//x轴的位移
int y_cz;//y轴的位移
int abs_x;
int abs_y;
x_cz = x2 - x1;
y_cz = y2 - y1;
abs_x = abs(x_cz);
abs_y = abs(y_cz);
if((x_cz > 30) && (abs_x > 2 * abs_y))
close(fd);
return 2;
else if((x_cz < -30) && (abs_x > 2 * abs_y))
close(fd);
return 1;
else if((y_cz > 30) && (abs_y > 2 * abs_x))
close(fd);
return 4;
else if((y_cz < -30) && (abs_y > 2 * abs_x))
close(fd);
return 3;
else
x1 = y1 = -1;
continue;
break;
close(fd);
/*
move_judge:判断是否还能移动
return value:
1 game over
0 continue
*/
int move_judge()
int i, j;
if(rectangle_get_zero_num() != 0)
return 0;
for(i = 0; i < 4; i++)
for(j = 0; j < 4 ; j++)
if (j != 4 -1)
if (array[i][j] == array[i][j+1])
return 0;
if (i != 4 - 1)
if (array[i][j] == array[i+1][j])
return 0;
return 1;
int main()
/*step 1: 打开屏幕*/
lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
perror("open fb0 failed:");
return -1;
/*step 2: mmap*/
lcd_ptr = mmap(
NULL, //第一个参数,为映射后的内存地址,
//为NULL,表示让操作系统自行分配
800*480*4, //第二个参数,为映射的长度。
PROT_WRITE, //第三个参数,为映射内存区域的权限
MAP_SHARED, //第四个参数,为映射标志,shared
lcd_fd, //第五个参数,为文件描述符,表示您要
//映射哪个文件
0 //第六个参数为偏移量,表示您要从文件的
//哪个位置开始映射
);
lcd_draw_dect(0, 0, 800, 480, 0x0080ff);//清屏
srandom( time(NULL) ); //设置随机数种子,种子一样,产生的
//随机数是一样的
init_matrix();
while (game_over == 0) //游戏没结束
//用来保存原来的矩阵值
int matrix_v1[4][4];
int i, j, flag = 0;
for (i = 0; i < 4; ++i)
for (j = 0; j < 4; ++j)
matrix_v1[i][j] = array[i][j];
/*
step 1: 变换矩阵
*/
change_matrix();
for (i = 0; i < 4; ++i)
for (j = 0; j < 4; ++j)
if (matrix_v1[i][j] != array[i][j])
flag = 1;
i = j = 4;
if (flag)
rand_matrix();
draw_matrix();
else
draw_matrix();
game_over = move_judge();
printf("Game Over~~");
munmap(lcd_ptr, 800*480*4);
close(lcd_fd);
电子相册+2048小游戏
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include<linux/fb.h>
#include <math.h>
#include <errno.h>
#include <time.h>
#include<string.h>
int lcd_fd, ts_fd;
int *lcd_ptr;
int game_over;
int get_finger_direction();
struct bmp_header //14
unsigned char type[2];
unsigned long size;
unsigned short reserverd1;
unsigned short reserverd2;
unsigned long offbit;
__attribute__((packed)); //字节对齐
struct bmp_info //40
unsigned int size;
unsigned int width;
unsigned int height;
unsigned short planes;
unsigned short bitcount;
unsigned int bitcompression;
unsigned int sizeimg;
unsigned int xpelspermeter;
unsigned int ypelspermeter;
unsigned int biclrused;
unsigned int important;
__attribute__((packed)); //字节对齐
int dev_init()
//1,lcd device init
lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
printf("open lcd device failed!\\n");
return -1;
//建立映射(走到镜子)
lcd_ptr = mmap(NULL, //内存映射的地址,默认填NULL,由系统来分配
800*480*4,//内存映射区的大小
PROT_READ | PROT_WRITE,//操作标志
MAP_SHARED,//共享标志
lcd_fd, //将要进行映射的文件的别名
0 //偏移量
);
if (lcd_ptr == MAP_FAILED)
printf("mmap failed!\\n");
return -2;
ts_fd = open("/dev/input/event0", O_RDONLY);
if (ts_fd == -1)
printf("open lcd device failed!\\n");
return -3;
return 0;
void dev_uninit()
munmap(lcd_ptr, 800*480*4);
close(lcd_fd);
close(ts_fd);
int show_bmp(int x, int y, const char* pathname)
//bmp file
int bmp_fd = open(pathname, O_RDWR);
if (bmp_fd == -1)
printf("open bmp file failed!\\n");
return -1;
struct bmp_header b_header;
struct bmp_info b_info;
read(bmp_fd, &b_header, 14);
read(bmp_fd, &b_info, 40);
int w, h;
w = b_info.width;
h = b_info.height;
//b) 读取图片颜色数据
char rgb_buf[w*h*3];
int tmp_buf[w*h];
int lcd_buf[800*480];
read(bmp_fd, rgb_buf, w*h*3);
// 24 --- > 32
int i, j;
int color;
for (i = 0; i < w*h; i++)
/*
color = rgb_buf[0]; //b
color = (rgb_buf[1] << 8); //g
color = (rgb_buf[2] << 16); //r
lcd_buf[0] = color;
color = rgb_buf[3]; //b
color = (rgb_buf[4] << 8); //g
color = (rgb_buf[5] << 16); //r
lcd_buf[1] = color;
*/
color = rgb_buf[3*i]; //b
color |= (rgb_buf[3*i+1] << 8); //g
color |= (rgb_buf[3*i+2] << 16); //r
tmp_buf[i] = color;
// up down
for (i = 0; i < h; i++)
for (j = 0; j < w; j++)
lcd_ptr[(i+y)*800+(j+x)] = tmp_buf[(h-1-i)*w+j];
//c) 将图片颜色数据写入到lcd屏幕
//write(lcd_fd, lcd_buf, 800*480*4);
close(bmp_fd);
return 0;
int get_xy(int *x, int *y)
struct input_event ts;
int x_read = 0, y_read =1;
// x1, y1, x2,y2
//2, read coord
while (1)
read(ts_fd, &ts, sizeof(ts));
if (ts.type == EV_ABS && ts.code == ABS_X && x_read == 0)
*x = ts.value;
x_read = 1;
y_read = 0;
if (ts.type == EV_ABS && ts.code == ABS_Y && y_read == 0)
*y = ts.value;
x_read = 0;
y_read = 1;
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == KEY_RESERVED)
printf("手指已经离开\\n");
break;
return 0;
int log_on()
int xing_x[6] = 175,255,325,395,475,545;
char number[7] = 0;
char vc[7] = 0;
//获取随机数种子
srandom(time(NULL));
show_bmp(0, 0, "/pic/bmp/vc_login.bmp");
int i;
bzero(number, 6);
for (i = 0; i < 6; i++)
number[i] = (random()%10)+48;
printf("%d ", number[i]);
printf("\\n");
number[7] = '\\0';
printf("number : %s\\n", number);
int x, y;
int j = 0;
while (1)
get_xy(&x, &y);
if (y > 160 && y <= 275 && j < 6)
//1 2 3
if (x > 170 && x < 385)
vc[j] = '1';
// /pic/bmp/
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("111\\n");
else if (x > 390 && x < 605)
vc[j] = '2';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("222\\n");
else if (x > 610 && x < 800)
vc[j] = '3';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("333\\n");
else if (y > 280 && y <= 395 && j < 6)
//4 5 6
if (x > 170 && x < 385)
vc[j] = '4';
// /pic/bmp/
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("444\\n");
else if (x > 390 && x < 605)
vc[j] = '5';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("555\\n");
else if (x > 610 && x < 800)
vc[j] = '6';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("666\\n");
else if (y > 400 && y <= 465 && j < 6)
//7 8 9
if (x > 170 && x < 385)
vc[j] = '7';
// /pic/bmp/
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("777\\n");
else if (x > 390 && x < 605)
vc[j] = '8';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("888\\n");
else if (x > 610 && x < 800)
vc[j] = '9';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("999\\n");
else if (y > 470 && y <= 615)
if (x > 170 && x < 385 && j > 0)
j--;
vc[j] = '0';
show_bmp(xing_x[j], 62, "/pic/bmp/white.bmp");
printf("delete!\\n");
else if (x > 390 && x < 605 && j < 6)
vc[j] = '0';
show_bmp(xing_x[j], 62, "/pic/bmp/star.bmp");
j++;
printf("000\\n");
else if (x > 610 && x < 800)
vc[7] = '\\0';
printf("%s\\n", vc);
if (strncmp(number, vc, 6) == 0)
show_bmp(200, 120, "/pic/bmp/correct.bmp");
sleep(1);
break;
else
show_bmp(200, 120, "/pic/bmp/error.bmp");
sleep(1);
j = 0;
bzero(vc, 6);
/* for (i = 0; i < 6; i++)
show_bmp(xing_x[i], 62, "/pic/bmp/white.bmp");
*/
show_bmp(0, 0, "/pic/bmp/vc_login.bmp");
continue;
int show_pic(void)
//1, device init
int rt = dev_init();
if (rt != 0)
printf("rt : %d\\n", rt);
return -1;
//2, oper
//gif
int i;
char buf[1024] = 0; //bzero
for (i = 0; i < 10; i++)
sprintf(buf, "/pic/gif/%d.bmp", i);
show_bmp(0, 0, buf);
usleep(100000);
//log on
log_on();
//main
//3, rmmod to device
dev_uninit();
return 0;
//数组初始化,将所有的图片保存在一个数组中
const char *bmp_files[] =
"/pic/bmp/digit_2.bmp", "/pic/bmp/digit_4.bmp",
"/pic/bmp/digit_8.bmp", "/pic/bmp/digit_16.bmp",
"/pic/bmp/digit_32.bmp", "/pic/bmp/digit_64.bmp",
"/pic/bmp/digit_128.bmp", "/pic/bmp/digit_256.bmp",
"/pic/bmp/digit_512.bmp", "/pic/bmp/digit_1024.bmp",
"/pic/bmp/digit_2048.bmp", "/pic/bmp/digit_4096.bmp",
"/pic/bmp/digit_8192.bmp", "/pic/bmp/digit_16384.bmp",
"/pic/bmp/digit_32768.bmp", "/pic/bmp/digit_65536.bmp"
;
//棋盘矩阵的初始化
int array[4][4] = 0;
//根据要显示的数字来返回对应的文件名的下标
int get_bmp_files_index(int x)
if (x == 2)
return 0;
else if (x == 4)
return 1;
else if (x == 8)
return 2;
else if (x == 16)
return 3;
else if (x == 32)
return 4;
else if (x == 64)
return 5;
else if (x == 128)
return 6;
else if (x == 256)
return 7;
else if (x == 512)
return 8;
else if (x == 1024)
return 9;
else if (x == 2048)
return 10;
else if (x == 4096)
return 11;
else if (x == 8192)
return 12;
else if (x == 16384)
return 13;
else if (x == 32768)
return 14;
else if (x == 65536)
return 15;
return -1;
//求棋盘矩阵里面有多少个0
int rectangle_get_zero_num()
int i, j, count = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (array[i][j] == 0)
count++;
return count;
int rectangle_set_value(int z, int value)
int i, j, count = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (array[i][j] == 0)
count++;
if (count == z)
array[i][j] = value;
return 0;
//触摸屏滑屏算法实现
int get_xy_v2()
struct input_event ts;
int x1 = -1, y1 = -1;
int x2, y2;
int x_read = 0, y_read =1;
// x1, y1, x2,y2
//2, read coord
while (1)
read(ts_fd, &ts, sizeof(ts));
if (ts.type == EV_ABS && ts.code == ABS_X && x_read == 0)
if (x1 == -1)
x1 = ts.value;
x2 = ts.value;
x_read = 1;
y_read = 0;
if (ts.type == EV_ABS && ts.code == ABS_Y && y_read == 0)
if (y1 == -1)
y1 = ts.value;
y2 = ts.value;
x_read = 0;
y_read = 1;
if (x_read && y_read)
break;
if (ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == KEY_RESERVED)
int num1 = x2-x1;
int num2 = y2-y1;
if (num1 > 0)
return 1;
else if (num1 < 0)
return 2;
if (num2 < 0)
return 3;
else if (num2 > 0)
return 4;
break;
/*
fin_left:手指左划后棋子移动及合并的方式
*/
void fin_left()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value, save_zero;
for(i = 0; i < 4; i++)
value = 0;
save_zero= 0;
for(j = 0; j < 4 ; j++)
if (array[i][j] == 0)
continue;
if (value == 0)
value = array[i][j];
else
if (value == array[i][j])
array[i][save_zero++] = value * 2;
value = 0;
else
array[i][save_zero++] = value;
value = array[i][j];
array[i][j] = 0;
if (value != 0)
array[i][save_zero] = value;
//draw_matrix();
/*
fin_right:手指上划后棋子移动及合并的方式
*/
void fin_right()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for (i = 0; i < 4; i++)
value = 0;
save_zero = 4 -1;
for (j = 4 - 1; j >= 0 ; j--)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[i][save_zero--] = 2 * value;
value = 0;
else
array[i][save_zero--] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[i][save_zero] = value;
/*
fin_up:手指上划后棋子移动及合并的方式
*/
void fin_up()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for(j = 0; j < 4; j++)
value = 0;
save_zero= 0;
for(i = 0; i < 4 ; i++)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[save_zero++][j] =2 * value;
value = 0;
else
array[save_zero++][j] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[save_zero][j] = value;
//draw_matrix();
/*
fin_down:手指上划后棋子移动及合并的方式
*/
void fin_down()
int i, j;//i为矩阵行下标,j为矩阵列下标
int value;
int save_zero;
for(j = 0; j < 4; j++)
value = 0;
save_zero = 4 - 1;
for(i = 4 - 1; i >= 0 ; i--)
if(array[i][j] == 0)
continue;
if(value == 0)
value = array[i][j];
else
if(value == array[i][j])
array[save_zero--][j] = 2 * value;
value = 0;
else
array[save_zero--][j] = value;
value = array[i][j];
array[i][j] = 0;
if(value != 0)
array[save_zero][j] = value;
/*
change_matrix:根据手指滑动(direction),
变换棋盘矩阵
*/
int change_matrix()
int direction = get_finger_direction();
if (direction == 1)
fin_left();
else if (direction == 2)
fin_right();
else if (direction == 3)
fin_up();
else
fin_down();
/*
lcd_draw_point:在屏幕坐为(x, y)这个点,填充color
这个颜色值。
@x: x轴坐标
@y:y轴坐标
@color:要填充的辨色值
返回值:
无返回值。
*/
void lcd_draw_point(int x, int y, int color)
int *p = lcd_ptr;
if (x >= 0 && x < 800 && y>=0 && y < 480)
*(p +800*y + x) = color;
/*
lcd_draw_dect: 在屏幕上画一个矩形,并且用
color这种颜色填充该矩形。
@x0: 该矩形的左上角的那个点x轴坐标
@y0:该矩形的左上角的那个点y轴坐标
@w:该矩形的宽
@h:该矩形的高
@color:该矩形要填充的辨色值
返回值:
无返回值。
*/
void lcd_draw_dect(int x0, int y0, int w, int h, int color)
if (x0 < 0 || y0 < 0 || w < 0 || h <0)
return;
if ((x0 + w >800) || (y0+h) > 480)
return;
int x, y;
for (y = y0; y < y0 + h; y++)
for (x = x0; x < x0 + w; x++)
lcd_draw_point(x, y , color);
/*
draw_bmp_byname:把一张bmp图片显示在屏幕上特定的位置
@bmpfile:要显示的bmp图片的文件名
@x0: 在屏幕上显示的左上角顶点的x轴坐标
@y0: 在屏幕上显示的左上角顶点的y轴坐标
@w: 位图宽度
@h: 位图高度
返回值:
无返回值.
*/
void draw_bmp_byname(const char *bmpfile, int x0, int y0, int w, int h)
int fd;
int x, y;
fd = open(bmpfile, O_RDONLY);
if (fd == -1)
perror("open bmpfile error:");
return ;
char bmpdata[w*h*3];
lseek(fd, 54, SEEK_SET);
read(fd, bmpdata, w*h*3);
close(fd);
int i = 0;
for (y = 0; y < h; y++)
unsigned char r,g ,b;
int color;
for (x = 0; x < w; x++)
b = bmpdata[i++];
g = bmpdata[i++];
r = bmpdata[i++];
color = (r << 16) | (g << 8) | b;
lcd_draw_point(x0+ x, y0 + (h -1 - y) ,color);
/*
draw_matrix:把棋盘矩阵在屏幕上显示出来
*/
void draw_matrix()
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4;j++)
int x0, y0;
x0 = 185;//棋盘矩阵左上角那个点的x轴坐标
y0 = 25;//棋盘矩阵左上角那个点的y轴坐标
if (array[i][j] == 0)
lcd_draw_dect(x0+j*110, y0+i*110, 100, 100,
0xff8080);//如果此处元素的值为0,那么
//就显示
else
int f_index = get_bmp_files_index(array[i][j]);
draw_bmp_byname(bmp_files[f_index],
x0+j*110, y0+i*110,
100,100);
/*
init_matrix:初始化棋盘矩阵
在任意x个位置,填充x个数字(2,4,8)
*/
void init_matrix()
//规则x >= 1,x <= 3
int x = (random() % 3) + 1;
int i;
/*
step1:随机产生x个数字,并填充到棋盘矩阵中去
*/
for(i = 0; i < x; i++)
int pos = (random() % rectangle_get_zero_num()) + 1;
int s[] = 2, 4, 8, 2;
int s_i = (random() % 3);
rectangle_set_value(pos, s[s_i]);
/*
step 2: 绘制棋盘矩阵
*/
draw_matrix();
/以上是关于粤嵌GEC6818,基于LVGL和mplayer的音视频播放器的主要内容,如果未能解决你的问题,请参考以下文章
粤嵌gec6818开发板LED屏幕上画图(数组与内存映射的采用)换图片 电子相册 实现识别触摸坐标的识别等项目
粤嵌gec6818LED屏幕上画图 太极图 图片显示 电子相册 2048小游戏 实现识别触摸坐标的识别 电子自助点餐设计等项目
GEC6818开发板JPG图像显示,科大讯飞离线语音识别包Linux_aitalk_exp1227_1398d7c6运行demo程序,开发板实现录音