嵌入式开发第20、21、22、23天(触摸屏电子相册)

项目框架

触摸屏电子相册
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 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "tslib.h"
#include 
#include 
#include 
#include 
#include "list.h"
#include 

#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  		:图片起点x
				int 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;i400&&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;j20&&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;
				else
					return 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();

			}
			else
				verification();

	
	
}

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;	
}


你可能感兴趣的:(日记,触摸屏电子相册,项目开发感想)