嵌入式开发第20、21、22、23天(触摸屏电子相册)
来源:互联网 发布:拳皇咆哮 源码 编辑:程序博客网 时间:2024/05/17 11:35
项目框架
触摸屏电子相册
1、密码登录 (9键 6位密码登陆、36键 6位随机验证码)
2、电子相册功能(有自动浏览,手动浏览,上一张,下一张、划屏操作)
1、密码登录 (9键 6位密码登陆、36键 6位随机验证码)
2、电子相册功能(有自动浏览,手动浏览,上一张,下一张、划屏操作)
指定运用方法(用链表将当前目录下面的图片连接起来,链表采用双向循环,或者内核链表)
3、音乐播放功能(播放、暂停、上一首、下一首)
其他:全触摸操作,链表链接,不许用线程。
运用知识:linux C, 文件IO,数据结构,Bmp24图片解码,jpeg图片解码,在任意位置显示24位位图图片
项目感想
1)项目框架很重要,早早的想好项目框架,对写代码有明显的辅助作用。而且能够看到自己开发过程,每完成一个功能有激励的效果。
2)准备工作很重要,在写之前列好各种需要用到的函数原型,不需要在写的过程中还在想,这个函数怎么用。
3)每写一个函数的时候,一定要想好这个函数的功能是什么,不能写过超出这个函数功能之外的东西,因为函数是被方便多次调用的,而不是只用一次,只用一次的函数,没有存在的意义。
4)每一个功能,一个全局变量,定义名字的时候一定要有代表性,有含义,不要瞎定义,有时定义一个i ,搞得自己都不知道他是干嘛的了。
5)关键的地方一定要备注,很重要,有时灵光一闪想到的算法,过了一两天,我居然看不懂了。
6)写代码的时候,不能一次写出超过两个函数以上的功能,两个以上的时候,找BUG会非常繁琐,浪费时间,建议每写一个小功能要调试一次,只有把地基打牢,才能建起高楼,特别是在写到自己不太熟练的,一定要想好,调试好。
7)习惯写调试信息,没有一个正确的反馈根本不知道自己出错在哪。而且用完以后也不要删除,注释就好,可能后面还要用呢。
8)刚开始的时候写的时候,不要把初始的功能想的太复杂,越复杂的东西越难实现,只要结果能够达到初始所设计的目标就够了。想要更智能需要重新构思。我在刚开始写26键密码按钮的时候,耗了很多时间,看到别人把9键都已经做出来了,压力更大了,也没信心写了,后来改回简单的9键,做完整个项目再慢慢加上去,觉得特别的轻松。
9)有那么一刻觉得,自己的代码是完美的,绝对是系统出错了。经过无数次打脸后,得出一个结果,永远不要怪系统出错,就是自己的错误,电脑发展至今,就是经历了无数程序员的修改,完善,不可能自己的一时想法,就超越了这么多的前人。
10)永远不要对自己的代码感到满足。同时也要对自己的代码充满信心。
#include <stdio.h>#include <fcntl.h> #include <unistd.h>#include <sys/select.h>#include <stdlib.h>#include <netdb.h>#include <string.h>#include <sys/stat.h>#include <sys/mman.h>#include "tslib.h"#include <sys/types.h>#include <dirent.h>#include <errno.h>#include <strings.h>#include "list.h"#include <time.h>#define DEV_NAME "/dev/event0"#define USR_PW "./setting/password"int g_y=0;//字母弹框int g_x=1;//操作教程int g_lcd_fd;//触摸屏显示unsigned long *g_fd_men;//显示屏的 内存映射char num[6];//密码char numm[6];//验证码char bmp[][40];//图片char mmp3[][40];//音乐void picture_or_music(void); //声明选项//链表--------------OPEN----------------------//设计节点 双向链表typedef struct node{char bmpp[40];struct node *prev;struct node *next;}listnode,*double_list; //listnode = struct node ,double_list = struct node *//2、初始化空链表double_list init_list(void){double_list head = malloc(sizeof(listnode)); //开辟节点空间if(head == NULL){printf("malloc node failed!\n");return NULL;}head->prev = head->next = head;return head;}//3、插入节点void insert_node(double_list new,double_list p){if(new == NULL || p == NULL)return;new->prev = p; //第一步new->next = p->next; //第二步p->next = new;//第三步new->next->prev = new; //第四步}//3、显示链表操作void show(double_list head){if(head == NULL)return;double_list p = head->next;while(p!=head){printf("%s\n",p->bmpp);p = p->next;}}//链表--------------END--------------------//读文件路径 id=1 读图片 id=2 读音乐int dir(int id){DIR *dir;int i=0; struct dirent *tmp; struct dirent *tmp2; //打开目录 if(id==1) dir = opendir("/coolAlbum/picture"); if(id==2) dir = opendir("/coolAlbum/music"); if(dir == NULL) { perror("opendir!\n"); return -1; } //读目录 计算数量 while((tmp = readdir(dir))!=NULL ) {if(tmp->d_type==4)//跳过系统类型文件continue;if(id==1){if(strstr(tmp->d_name,"bmp")!=NULL) { i++; //计算图片数量 }} if(id==2){if(strstr(tmp->d_name,"mp3")!=NULL) { i++; //计算音乐 }} } //根据数量 分配空间bzero(bmp,i*40); //打开目录 if(id==1) dir = opendir("/coolAlbum/picture"); if(id==2) dir = opendir("/coolAlbum/music"); if(dir == NULL) { perror("opendir!\n"); return -1; } i=0; //读文件路径 while((tmp2 = readdir(dir))!=NULL ) {if(id==1){if(strstr(tmp2->d_name,"bmp")!=NULL){ sprintf(bmp[i++],"/coolAlbum/picture/%s",tmp2->d_name);}}if(id==2){if(strstr(tmp2->d_name,"mp3")!=NULL){ sprintf(mmp3[i++],"madplay /coolAlbum/music/%s &\n",tmp2->d_name);}} } return i;}//初始化显示屏int lcd_init(void){g_lcd_fd = open("/dev/fb0",O_RDWR);//打开设备g_fd_men = (unsigned long *)mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,g_lcd_fd,0);//建立内存映射if(g_fd_men == NULL){printf("mmap g_fd_men failed!\n");return -1;}return 0;}int lcd_uninit(void) //关闭显示屏{munmap(g_fd_men,800*480*4);}/*任意位置显示24位bmp图片unsigned long *g_fd_men:显存映射地址int x :图片起点xint y :图片起点y int w:图片的宽int h:图片的高const char *pathname:图片路径*/int show_shape(unsigned long *g_fd_men,int x,int y,int w,int h,const char *pathname){int bmp_fd,i,j;char bmp_buffer[w*h*3];int lcd_buffer[w*h];//打开图片bmp_fd = open(pathname,O_RDONLY);if(bmp_fd == -1){printf("open failed!\n");return -1;}//跳过54个字节头 54个是BMP 文件的信息lseek(bmp_fd,54,SEEK_SET);read(bmp_fd,bmp_buffer,sizeof(bmp_buffer));for(i=0;i<w*h;i++){lcd_buffer[i] = bmp_buffer[3*i] | bmp_buffer[3*i+1]<<8 | bmp_buffer[3*i+2]<<16; }for(i=0;i<h;i++)for(j=0;j<w;j++){*(g_fd_men+(y+i)*800+x+j) = lcd_buffer[(h-1-i)*w+j];}close(bmp_fd);return 0;}//划屏int ts_row(void){struct tsdev *ts;struct ts_sample samp;int ret;int sub=0;//打开触摸屏ts = ts_open(DEV_NAME,0);if(ts == NULL){printf("open ts failed!\n");}//配置触摸屏,配置插件ret = ts_config(ts);if(ret == -1){printf("ts_config failed!\n");ts_close(ts);}while(1){ts_read(ts,&samp,1);printf("samp.x = %d,samp.y = %d,samp.pressure = %d\n",samp.x,samp.y,samp.pressure);if(samp.y>400&&samp.x<100&&samp.x>0&&samp.y>0){return 0;}if(samp.y>0&&samp.y<240&&samp.x>700&&samp.x<800){return 1;}if(samp.y>240 && samp.y<480 && samp.x>700 && samp.x<800){return 2;}//划屏幕的起点sub=samp.x;ts_read(ts,&samp,1); //阻止在划屏时 触摸下一张ts_read(ts,&samp,1);if(samp.x && samp.pressure==0){if(samp.x && samp.pressure==0){printf("%d - %d = %d\n",samp.x,sub,samp.x-sub);sub =samp.x-sub ;if(sub>0)//左划{return 1;}if(sub<0)//右划{return 2;}}}}}//判断触摸的有效性struct ts_sample ts_touch(int i){struct tsdev *ts;struct ts_sample samp;int ret;int sub=0;//打开触摸屏ts = ts_open(DEV_NAME,0);if(ts == NULL){printf("open ts failed!\n");}//配置触摸屏,配置插件ret = ts_config(ts);if(ret == -1){printf("ts_config failed!\n");ts_close(ts);}if(i==1)//判断触摸的有效性{while(1){ts_read(ts,&samp,1);if(samp.pressure==200){ts_read(ts,&samp,1);if(samp.pressure==0){ts_read(ts,&samp,1);if(samp.pressure==0){printf("ok\n");//输出触摸区域return samp;}}}}}}//弹字母 9个数字键 代表36个选择 点一个数字键 显示对应的4种选择char tancuang(int i){int j,k=4;char AA[36]={"1ABC2DEF3GHI4JKL5MNO6PQR7STU8VWX9YZ0"};char tan[40];if(i==9)k=3;if(i==0){sprintf(tan,"./setting/keyboard2/%c.bmp",AA[35]);show_shape(g_fd_men,g_y*55+30,85,51,50,tan);g_y++;if(g_y==6)g_y=0;return AA[35];}--i;for(j=0;j<k;j++){sprintf(tan,"./setting/keyboard2/%c.bmp",AA[i*4+j]);show_shape(g_fd_men,j*133 +50,150,51,50,tan);}j=ts_pw(8);sprintf(tan,"./setting/keyboard2/%c.bmp",AA[i*4+j]);show_shape(g_fd_men,g_y*55+30,85,51,50,tan);g_y++;if(g_y==6)g_y=0;return AA[i*4+j];}int ts_pw(int function)//N多功能触摸 按键确认{struct ts_sample samp;int i=0,j=0,k=0;if(function ==1) //数字密码判断{while(i<6){samp=ts_touch(1);printf("okkokokokoko \nsamp.x = %d,samp.y = %d,samp.pressure = %d\n",samp.x,samp.y,samp.pressure);if(samp.x>20&&samp.x<620&&samp.y<460&&samp.y>230)//输入密码的有效位置if(samp.y<340){if(samp.x<150){printf("1\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/1.bmp");num[i]='1';i++;continue;}if(samp.x<270){printf("2\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/2.bmp");num[i]='2';i++;continue;}if(samp.x<380){printf("3\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/3.bmp");num[i]='3';i++;continue;}if(samp.x<500){printf("4\n");num[i]='4';show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/4.bmp");i++;continue;}else{printf("5\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/5.bmp");num[i]='5';i++;continue;}}else{if(samp.x<150){printf("6\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/6.bmp");num[i]='6';i++;continue;}if(samp.x<270){printf("7\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/7.bmp");num[i]='7';i++;continue;}if(samp.x<380){printf("8\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/8.bmp");num[i]='8';i++;continue;}if(samp.x<500){printf("9\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/9.bmp");num[i]='9';i++;continue;}else{printf("0\n");show_shape(g_fd_men, i*102 +20 ,40,100,100,"./setting/keyboard/0.bmp");num[i]='0';i++;}}}return 1;}if(function ==2) //登陆确认键{while(1){samp=ts_touch(1);printf("samp.x = %d,samp.y = %d,samp.pressure = %d\n",samp.x,samp.y,samp.pressure);if(samp.x>620&&samp.y>230)return 2;}}if(function ==3)//相册 与 音乐 与 返回 按键确认{while(1){samp=ts_touch(1);printf("samp.x = %d,samp.y = %d,samp.pressure = %d\n",samp.x,samp.y,samp.pressure);if(samp.x>111&&samp.y>130&&samp.x<340&&samp.y<300){return 3;}if(samp.x>470&&samp.y>130&&samp.x<700&&samp.y<300){return 4;}if(samp.y>350&&samp.x<150){return 0;}}}if(function ==4) //测试触摸反应结果{while(1){samp=ts_touch(1);return 6;}}if(function ==6)//音乐播放按键{while(1){samp=ts_touch(1);if(samp.y>350&&samp.x<150)return 0;if(samp.y>175&&samp.x>180&&samp.x<650&&samp.y<280){if(samp.x<300)return 1;if(samp.x<420)return 2;if(samp.x<540)return 3;elsereturn 4;}}}if(function ==7)//验证码按键{while(i<6){samp=ts_touch(1);if(samp.x>20&&samp.x<620&&samp.y<460&&samp.y>230)//输入密码的有效位置if(samp.y<340){if(samp.x<150){//弹窗numm[i]=tancuang(1);i++;continue;}if(samp.x<270){numm[i]=tancuang(2);i++;continue;}if(samp.x<380){numm[i]=tancuang(3);i++;continue;}if(samp.x<500){numm[i]=tancuang(4);i++;continue;}else{numm[i]=tancuang(5);i++;continue;}}else{if(samp.x<150){numm[i]=tancuang(6);i++;continue;}if(samp.x<270){numm[i]=tancuang(7);i++;continue;}if(samp.x<380){numm[i]=tancuang(8);i++;continue;}if(samp.x<500){numm[i]=tancuang(9);i++;continue;}else{numm[i]=tancuang(0);i++;}}}}if(function ==8)//相框右侧 按键{samp=ts_touch(1);if(samp.x>20&&samp.x<500&&samp.y<230&&samp.y>125)//输入密码的有效位置{if(samp.x<150){return 0;}if(samp.x<270){return 1;}if(samp.x<380){return 2;}if(samp.x<500){return 3;}}}}void verification(void)//验证码生成与输入确认{int i,j=0;char yz[6];char v_bmp[6][40];bzero(v_bmp,6*40);char input_pasd[6];//验证码式的警告show_shape(g_fd_men,0,0,800,480,"./setting/warning2.bmp");sleep(2);show_shape(g_fd_men,0,0,800,480,"./setting/password.bmp");srand((int)time(0));//设置时间种子//生成随机的验证码//在界面上生成对应的图片while(j<6){i = 1 + (int) (2.0 * rand() / (RAND_MAX + 1.0));if(i==1){i = 0 + (int) (9.0 * rand() / (RAND_MAX + 1.0));yz[j]='0'+i;}if(i==2){i = 0 + (int) (25.0 * rand() / (RAND_MAX + 1.0));yz[j]='A'+i;}sprintf(v_bmp[j],"./setting/keyboard2/%c.bmp",yz[j]);show_shape(g_fd_men, j*55+30, 30 ,51,50,v_bmp[j]);j++;}printf("%s\n",yz);i=0;ts_pw(7);stpcpy(input_pasd,numm); //接收触摸屏密码if( ts_pw(2)==2 && (strcmp(yz,input_pasd)==0))//点击go,判断密码正确{usr_password();}elseverification();}int usr_password(void)//开机密码输入{int fd;char ch;char usrpasd[7];char input_pasd[6];int i=0;//打开文件fd = open(USR_PW,O_RDONLY);if(fd == -1){printf("open ps file failed!\n");return -1;}read(fd,usrpasd,6);usrpasd[6]='\0';//若是不赋值零的话 他可能会以为字符没读完,而越界了printf("usrpd = %s\n",usrpasd);i=0;while(1){//输入密码页面show_shape(g_fd_men,0,0,800,480,"./setting/password.bmp");printf("please input passwd!\n");ts_pw(1);stpcpy(input_pasd,num); //接收触摸屏密码printf("%s\n%s\n",usrpasd,input_pasd);if( ts_pw(2)==2 && strcmp(usrpasd,input_pasd)==0 )//点击go,判断密码正确{sleep(1);//登陆成功printf("compare correct!\n");//进入 电子相册 和 MP3 选择页面picture_or_music();break;}i++;if(i==3){//第三次输入错误,死机 或者 开启验证码输入printf("you haven't no change input!\n");//进入验证码模式verification();}//输入错误警告show_shape(g_fd_men,0,0,800,480,"./setting/warning.bmp");sleep(1);}close(fd);return 0;}void picture_or_music(void);void picture(void)//电子相册 页面{int i,j;//初始化链表double_list head_list = init_list();double_list new;//读取路径导入到链表i=dir(1);if(i==-1){printf("picture read dir fail\n",i);}for(i-=1;i>=0;i--)//插入链表{new = init_list();stpcpy(new->bmpp,bmp[i]);printf("%s\n",new->bmpp);insert_node(new,head_list);}if(g_x==1)//相册介绍使用教程{show_shape(g_fd_men,0,0,800,480,"/coolAlbum/setting/picture.bmp");sleep(1);}double_list p =head_list->next;show_shape(g_fd_men,0,0,800,480,p->bmpp);while(1){j=ts_row();//判断滑动状态g_x=0;if(j==1){p = p->prev;if(p==head_list)//判断是不是头节点 因为头节点没有数据p=p->prev;show_shape(g_fd_men,0,0,800,480,p->bmpp);}if(j==2){p = p->next;if(p==head_list)p=p->next;show_shape(g_fd_men,0,0,800,480,p->bmpp);}if(j==0){picture_or_music();}}}void mp3(void)//音乐播放页面{int i,j,x,z=0;//初始化链表double_list head_list = init_list();double_list new;//读取路径导入到链表i=dir(2);if(i==-1){printf("picture read dir fail\n",i);}printf("i=%d\n",i);for(i-=1;i>=0;i--){new = init_list();stpcpy(new->bmpp,mmp3[i]);printf("------%s----\n",new->bmpp);insert_node(new,head_list);}show_shape(g_fd_men,0,0,800,480,"/coolAlbum/setting/music.bmp");double_list p =head_list;while(1){j=ts_pw(6);if(j==1){//上一首system("killall -KILL madplay\n");p = p->prev;if(p==head_list)p=p->prev;system(p->bmpp); }if(j==2){p = p->next;system("killall -STOP madplay&\n");//停止音乐z=1;}if(j==3){//system(p->bmpp); //启动音乐if(z==0)system("madplay /coolAlbum/music/sd.mp3&\n"); //启动音乐if(z==1)system("killall -CONT madplay&\n");//继续播放}if(j==4){//下一首system("killall -KILL madplay\n");p = p->next;if(p==head_list)p=p->next;printf(" %s\n ",p->bmpp);system(p->bmpp); }if(j==0){picture_or_music();}}}void picture_or_music(void)//触摸选择 电子相册 MP3 返回{int i;//加载登陆后的图片 带返回show_shape(g_fd_men, 0,0,800,480,"./setting/picture_or_mp3.bmp");i=ts_pw(3);//触摸选择区域 电子相册 MP3 返回if(3== i){picture();}if(4== i)//进入MP3{mp3();}if(0== i)//返回到输入页面{usr_password();}}int main(void){int i=10;lcd_init();//屏幕初始化show_shape(g_fd_men,0,0,800,480,"./setting/logo.bmp");//开启画面system("madplay /coolAlbum/music/sd.mp3&\n"); //开机音乐sleep(3);usr_password();//密码输入lcd_uninit();return 0;}
0 0
- 嵌入式开发第20、21、22、23天(触摸屏电子相册)
- 基于mini2440触摸屏版电子相册(裸机代码)
- 嵌入式linux--电子相册
- 嵌入式开发第49天(RTC)
- 基于S3C2451的嵌入式电子相册
- android开发电子相册
- 【视频】嵌入式Linux/Android驱动开发揭秘(1)触摸屏驱动开发
- 嵌入式开发第30天(线程池)
- 嵌入式开发第37天(shell编程:shell是什么?)
- 嵌入式开发第41天(什么是ARM?)
- 嵌入式开发第42天(ARM的体系结构)
- 嵌入式开发第44天(GPIO的使用)
- 嵌入式开发第47天(看门狗定时器的原理)
- 嵌入式开发第50天(s5pv210的LCD原理)
- 嵌入式开发第5天(数组)
- 嵌入式up-tech开发板触摸屏的配置
- 嵌入式多功能电子相册之上位机
- Android应用开发之电子相册
- 小白装openstack(三) 安装数据库等必要服务
- CSS3
- 访问附有_weak修饰符的变量
- 总结:对Java内存模型JMM的理解
- FFmpeg常用基本命令
- 嵌入式开发第20、21、22、23天(触摸屏电子相册)
- Android怎样调用@hide和internal API
- HUST 1644 (思维)
- 调整dock动画效果
- 高性能、高并发TCP服务器(多线程调用libevent)
- 七种网卡绑定模式详解
- [模板]扩展KMP模板
- 关于UICollectionView的使用
- 开源WebGIS实施方案(一):开篇