⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 touch.c

📁 基于stm32的MP3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "touch.h"
//触摸屏初始化
//使用外部8M晶振,PLL到72M频率		    
//正点原子@SCUT
//2008/12/14 
//V1.0  
	   		  
//SPI开始  
void start_spi()   
{ 	  
	TCLK_SET(0);   
	TCS_SET(1); 	 
	TDIN_SET(1);  
	TCLK_SET(1);  
	TCS_SET(0);   
}
//SPI写数据
//向7846写入1byte数据   
void WriteByteADS(u8 num)    
{  
	u8 count=0;  
	TCLK_SET(0);   
	for(count=0;count<8;count++)  
	{ 	  
		if(num&0x80)TDIN_SET(1);  
		else TDIN_SET(0);   
		num<<=1;    
		TCLK_SET(0);//上升沿有效  	 
		TCLK_SET(1);      
	} 			    
} 
//SPI读数据 
//从7846读取adc值	   
u16 ReadWordADS(void)	  
{ 	 
	u8 count=0; 	  
	u16 Num=0; 	 
	for(count=0;count<12;count++)  
	{ 				  
		Num<<=1; 	 
		TCLK_SET(1);//下降沿有效 	   
		TCLK_SET(0);    
		if(DOUT)Num++; 		 
	} 		  
	return(Num);   
}
 
//读取一次X,Y值
//读到的X,Y坐标值必须都大于100
//成功返回1,不成功返回0
//读数限制在100~3800之间.			   
u8 read_once(void)
{
	start_spi();//启动SPI  	 
	WriteByteADS(CMD_RDX); 
	//ADS7846的转换时间最长为6us
	TCLK_SET(1);delay_us(3);   	    
	TCLK_SET(0);delay_us(3);  
	Pen_Point.X=4096-ReadWordADS();//读X坐标,并转换 
	WriteByteADS(CMD_RDY); 
	//ADS7846的转换时间最长为6us
	TCLK_SET(1);delay_us(3);   	    
	TCLK_SET(0);delay_us(3);   
	Pen_Point.Y=4096-ReadWordADS();//读Y轴坐标   
	TCS_SET(1);   
	//限制触摸屏读数范围,个人根据实际情况定
	if(Pen_Point.X<3950&&Pen_Point.X>200&&Pen_Point.Y<3950&&Pen_Point.Y>200)return 1;//读数成功
	else return 0;							 //读数失败
}
//读取ADS7846	  
//连续读取10次数据,对十次数据排序,然后对
//中间三次取平均值,得到最终的X,Y值  	   
u8 Read_Ads7846(void)
{
	u8 t,t1,count=0;
	u16 databuffer[2][10];//数据组
	u16 temp=0;	 
	do					  //循环读数10次
	{		    		   
		if(read_once())//读数成功
		{	  
			databuffer[0][count]=Pen_Point.X;
			databuffer[1][count]=Pen_Point.Y;
			count++;  
		}
	}while(NPEN&&count<10);   
	if(count==10)//一定要读到10次数据,否则丢弃
	{  
	    do//将数据X升序排列
		{	
			t1=0;		  
			for(t=0;t<count-1;t++)
			{
				if(databuffer[0][t]>databuffer[0][t+1])//升序排列
				{
					temp=databuffer[0][t+1];
					databuffer[0][t+1]=databuffer[0][t];
					databuffer[0][t]=temp;
					t1=1; 
				}  
			}
		}while(t1); 	  
		do//将数据Y升序排列
		{	
			t1=0;		 
			for(t=0;t<count-1;t++)
			{
				if(databuffer[1][t]>databuffer[1][t+1])//升序排列
				{
					temp=databuffer[1][t+1];
					databuffer[1][t+1]=databuffer[1][t];
					databuffer[1][t]=temp;
					t1=1;	 
				}  
			}
		}while(t1);		   
		 	 		  
		Pen_Point.X=(databuffer[0][3]+databuffer[0][4]+databuffer[0][5])/3;
		Pen_Point.Y=(databuffer[1][3]+databuffer[1][4]+databuffer[1][5])/3;	  
																		  
		//TFT_ShowString(100,140,"X read:");TFT_ShowNum(142,140,Pen_Point.X);	   //
		//TFT_ShowString(100,152,"Y read:");TFT_ShowNum(142,152,Pen_Point.Y);
		return 1;									   
	}
	return 0;//读数失败
}	   
//中断,检测到PEN脚的一个下降沿.
//置位Pen_Point.Key_Sta为按下状态
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{ 							     
	Pen_Point.Key_Sta=Key_Down;//按键按下   
	EXTI->PR=1<<0;  //清除LINE0上的中断标志位 
} 	  
//按键处理程序
//type:按键响应类型
//0,单点,定点,不扩展.一定要按键松开才返回
//1,单点,滑动,不扩展.滚动条操作/连加操作
//2,扩展按键支持:
//即:MOVE_LEFT,MOVE_RIGHT,MOVE_UP,MOVE_DOWN使能
u8 Touch_Key_Pro(u8 type)
{
	u16 tempx,tempy;//暂时保存X,Y坐标 	 	 
	u8 ml=0,mr=0,mu=0,md=0;//四个方向上移动次数  
	u8 first=1;	  		 	    					   		 
	//按键还是按下的
	//手动按触摸屏的时候,至少需要15ms才能退出这个循环	   	
	do
	{	    
		Pen_Point.Key_Sta=Key_Up;//按键状态变为松开    
		if(Read_Ads7846())//成功读数
		{	 
			if(first)
			{
				Pen_Point.X0=Pen_Point.X;Pen_Point.Y0=Pen_Point.Y;//得到初始按下的坐标
				tempx=Pen_Point.X;tempy=Pen_Point.Y;  
				//printf("X0:%d Y0:%d\n",Pen_Point.X,Pen_Point.Y);
				first=0;  //标记清空
			}else if(type==2) //扩展按键														  
			{	  
				if(tempx>Pen_Point.X)ml++;
				else mr++;	   	
				if(tempy>Pen_Point.Y)mu++;
				else md++;
				//设定一个门限值,不能让一次移动大于这个值,如果一次大于这个值
				//认为触摸屏误动作了.400的时候,反映比较慢
				if(abs(tempx-Pen_Point.X)>700||abs(tempy-Pen_Point.Y)>700)//有抖动
				{
					ml=mr=mu=md=0;//全部清掉
					tempx=Pen_Point.X=Pen_Point.X0;//坐标复位
					tempy=Pen_Point.Y=Pen_Point.Y0;
					break;//退出数据采集,结果为点采集
				}   
				tempx=Pen_Point.X;tempy=Pen_Point.Y;//转移临时坐标 
			}else if(type==1)break; 
			//printf("X:%d Y:%d\n",Pen_Point.X,Pen_Point.Y); 
		}
		delay_ms(10);//10ms消抖 						   		     								 	
	}while(NPEN||Pen_Point.Key_Sta==Key_Down);//PEN=0或者按键状态为按下状态;
	delay_ms(50);
	Pen_Point.Key_Sta=Key_Up;//按键状态变为松开	 
 	//单次/不扩展 键值处理  
	if(abs(tempx-Pen_Point.X0)<=200&&abs(tempy-Pen_Point.Y0)<=200||type<2)//单次按键/不扩展按键功能
	{	 
		if(Pen_Point.xfac!=0)//已经校准过了
		{
			Pen_Point.X0=Pen_Point.xfac*Pen_Point.X0+Pen_Point.xoff;
			Pen_Point.Y0=Pen_Point.yfac*Pen_Point.Y0+Pen_Point.yoff;
		}
		Pen_Point.X=Pen_Point.X0;Pen_Point.Y=Pen_Point.Y0;
		return CLICK_POINT;//没有移动  
	}	 
	//扩展键值处理
	if(abs(tempx-Pen_Point.X0)<=500&&abs(tempy-Pen_Point.Y0)<=500)return 0;//滑动距离最少要大于500
	else if(Pen_Point.xfac!=0)//已经校准过了
	{
		Pen_Point.X0=Pen_Point.xfac*Pen_Point.X0+Pen_Point.xoff;
		Pen_Point.Y0=Pen_Point.yfac*Pen_Point.Y0+Pen_Point.yoff;

		tempx=Pen_Point.xfac*tempx+Pen_Point.xoff;
		tempy=Pen_Point.yfac*tempy+Pen_Point.yoff;
	}
		
	if(abs(ml-mr)>abs(mu-md))//数量 满足
	{
		if(abs(tempx-Pen_Point.X0)>abs(tempy-Pen_Point.Y0))//质量满足
		{
			if(tempx>Pen_Point.X0)return MOVE_RIGHT;
			else return MOVE_LEFT; 
		}else						//质量不满足
		{
			if(tempy>Pen_Point.Y0)return MOVE_DOWN;
			else return MOVE_UP;
		}
	}else
	{
		if(abs(tempy-Pen_Point.Y0)>abs(tempx-Pen_Point.X0))//质量满足
		{	    
			if(tempy>Pen_Point.Y0)return MOVE_DOWN;
			else return MOVE_UP;			 
		}else						//质量不满足
		{	  
			if(tempx>Pen_Point.X0)return MOVE_RIGHT;
			else return MOVE_LEFT;
		}
	}   	  
}
 
//判断触点是不是在指定区域之内
//(x1,y1):起始坐标
//(x2,y2):结束坐标
//返回值 :1,在该区域内.0,不在该区域内.
u8 Is_In_Area(u8 x1,u16 y1,u8 x2,u16 y2)
{
	if(Pen_Point.X<=x2&&Pen_Point.X>=x1&&Pen_Point.Y<=y2&&Pen_Point.Y>=y1)return 1;
	else return 0;
}  
//把触摸屏得到的数据转换为数字(按钮值)
//M_Type:按钮模式;
//0,系统菜单	
//1,文件浏览模式 	
//2,时间模式下,按键的获取,连按支持! 
//3,音乐播放模式下
//4,功能选择模式下
//5,收音机模式下
//6,闹钟中断程序按键			  
//返回值:对应的按键值(1~n)
//返回0,则表示此次按键无效  
u8 Touch_To_Num(u8 M_Type)
{
	u8 xtemp;
	u16 t,ytemp;
	switch(M_Type)
	{
		case 0://系统菜单下
			xtemp=Touch_Key_Pro(1);//不使用扩展按钮
			if(!(xtemp&CLICK_POINT))return 0;//不是点触直接退出
			ytemp=10;
			for(t=0;t<9;t++)
			{
				xtemp=80*(t%3)+10;
				if(t>5)ytemp=216;
				else if(t>2)ytemp=113;
				if(Is_In_Area(xtemp,ytemp,xtemp+59,ytemp+90))return t+1;//返回按键值 
			}
			break;
		case 1://1,文件浏览模式
			xtemp=Touch_Key_Pro(2);//支持扩展	 
			if(xtemp&CLICK_POINT)  //点触摸	 得到1~8的值
			{
				for(t=0;t<8;t++)
				{	  
					if(Is_In_Area(0,42+t*32,239,42+(t+1)*32))return t+1;
				}
				if(Is_In_Area(0,300,40,319))return 9;//选择按钮被按下
				if(Is_In_Area(200,300,239,319))return 10;//返回按钮被按下
				return 0;//按键无效
			}
			if(xtemp)return xtemp&0xf0;//滑动触摸了!! 
			break; 
		case 2://2,时间模式下,按键的获取,连按支持!
			xtemp=Touch_Key_Pro(1);//不扩展
			if(xtemp&CLICK_POINT)  //点触摸	 得到1~8的值
			{
				if(Is_In_Area(4,142,28,166))return 1;	    
				else if(Is_In_Area(60,142,84,166))return 2;
				else if(Is_In_Area(96,142,120,166))return 3;
				else if(Is_In_Area(136,142,160,166))return 4;
				else if(Is_In_Area(172,142,196,166))return 5;
				else if(Is_In_Area(212,142,236,166))return 6;

				else if(Is_In_Area(4,206,28,230))return 7;	    
				else if(Is_In_Area(60,206,84,230))return 8;
				else if(Is_In_Area(96,206,120,230))return 9;
				else if(Is_In_Area(136,206,160,230))return 10;
				else if(Is_In_Area(172,206,196,230))return 11;
				else if(Is_In_Area(212,206,236,230))return 12;
															   
				else if(Is_In_Area(0,300,40,319))return 13;//选择按钮被按下
				else if(Is_In_Area(200,300,239,319))return 14;//返回按钮被按下
				return 0;//按键无效
			}
			break;
		case 3://MP3界面下面的按钮值
			xtemp=Touch_Key_Pro(1);//不扩展
			if(xtemp&CLICK_POINT)  //点触摸	 得到1~8的值
			{
				if(Is_In_Area(214,72,240,96))return 1;//循环模式更改	    
				else if(Is_In_Area(87,103,153,119))return 2; //supper bass
				else if(Is_In_Area(8,223,56,247))return 3;   //音效存/取
				else if(Is_In_Area(64,223,112,247))return 4; //音量
				else if(Is_In_Area(120,223,168,247))return 5;//其他
				else if(Is_In_Area(178,224,204,276))return 6;//回车	 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -