资讯详情

【手拉手 带你准备电赛】原来你是这样的触摸屏(电阻触摸屏)

在我们的生活中,触摸屏可以说无处不在。我们可以在各种触摸面板上看到触摸屏,一些产品的价值也因为触摸屏而飙升。接下来,小蛋糕会带你对触摸屏有更深入的了解。

触摸屏可分为电阻触摸屏和电容触摸屏。在这里,我们介绍电阻触摸屏(为什么使用电阻触摸屏更好或更广泛?no no no 事实上,电容式触摸屏现在被广泛使用。电容式触摸屏是我们主流手机使用的屏幕。那我为什么要用电阻触摸屏,因为它便宜(手动无奈表情)。

言归正传,我来介绍一下电阻屏的优缺点,如下表所示:

电阻触摸屏的优点 电阻触摸屏的缺点
精度高,价格低,抗干扰能力强,稳定性好 易划伤,透光性差,不支持多点触摸

在我们眼里,触摸屏一直是一种科技感慢的高科技设备,but看完小蛋糕下触摸屏原理的介绍,你会觉得触摸屏,just so so。

首先,我们需要了解触摸屏的组成结构。电阻触摸屏的主要部分是一个与显示器表面非常匹配的电阻膜屏,是一种多层复合膜,以玻璃或硬塑料板为基层,表面涂有透明氧化物膜导电层,外表面硬化处理,塑料层光滑,内表面涂有涂层,两层导电层之间有许多小的透明隔离点。当手指触摸屏幕时,两层导电层在接触点接触,电阻在X和Y在两个方向上产生相应的信号,然后发送到触摸屏控制器。该接触被控制器检测到并计算(X,Y)变量,然后根据获得的位置模拟鼠标运行,以上是电阻触摸屏的基本原理。怎么样,是不是老简单!

在这篇文章中,小蛋糕了解触摸屏的工作过程。

我们以STM32F103系列的MINI开发板、2.以8电阻触摸屏为例,解释我们的相关硬件和程序代码。在这里,我们暂时不考虑触摸屏信号AD转换,关于AD将在以后的文章中解释小蛋糕的转换。

本实验首先需要初始化LCD,根据LCD的ID判断是否是电阻触摸屏,如果没有,我们需要继续遵循电容触摸屏的设计算法程序,是的,我们继续判断后进入相关测试板是一种逻辑强的通用方法,由于数据庞大,本片代码只详细说明电阻屏幕的相关代码。获得ID判断为电阻触摸屏后,需要判断触摸屏是否校准(触摸屏可以记住校准)。如果不需要校准,校准后(或之前校准过)进入电阻屏测试测序(测试界面右上角会有清空操作区域)。RST,单击此处将完全清除,恢复白板状态)

了解实验内容后,我们开始了编写代码的旅程,are you ready?

因为我们需要使用它LCD显示相关信息,这里的小蛋糕带你手拉手LCD初始化及相关应用。

由于LDC有太多的初始化代码,这里只解释关键代码

//结构声明 GPIO_InitTypeDef GPIO_InitStructure; //使能相关IO口的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);  //开启SWD,使能JTAG GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);  //使用的IO口(具体IO可以查看开发手册进行初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC   GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //  PORTBí?íìê?íìê?3? GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB GPIO_SetBits(GPIOB,GPIO_Pin_All);

完成LCD初始化后,我们需要LCD相关信息显示在上面,所以我们需要编写相关函数,即LCD_ShowString()函数。

//x,y代表打印信息的起始地址 //width和heigth代表信息显示区间的长度和高度 //size代表字符的大小 //*p指向我们想要输出信息地址的指针 void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p) {           u8 x0=x;    ///根据输入的起始地址更新显示区域  width =x;  height =y;     while((*p<='~')&&(*p>=' )//判断需要显示的字符是否有效     {                if(x>=width){x=x0;y =size;}判断输入的信息是否超过显示长度,超过显示长度的,换行显示         if(y>=height)break; ///调用提供的函数显示信息(真实显示信息的部分)         LCD_ShowChar(x,y,*p,size,0);         x =size/2;         p  ;     }   }

LCD工作结束后,我们开始了触摸屏的相关操作

首先,我们检查电阻屏控制器结构的定义

typedef struct {     u8 (*init)(void);        u8 (*scan)(u8);                 //扫描触摸屏     void (*adjust)(void);    u16 x[CT_MAX_TOUCH];     u16 y[CT_MAX_TOUCH];           u8  sta;     float xfac;       float yfac;  short xoff;  short yoff;     u8 touchtype; }_m_tp_dev;

然后我们需要初始化触摸屏。电阻触摸屏初始化代码如下:

    //首先,我们仍然需要使相关的时钟     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC  | RCC_APB2Periph_AFIO, ENABLE);  /*********************************************************************************/     //对触摸屏IO口进行初始化  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_0|GPIO_Pin_13;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(GPIOC, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;   GPIO_Init(GPIOC, &GPIO_InitStructure);  /************************************************************************************/         ////读第一次初始化xy的坐标   TP_Read_XY(&tp_dev.x[0],&tp_dev.y[0]);          //初始化   AT24CXX_Init();         //判断是否校准   if(TP_Get_Adjdata())return 0;         //如果校准不成功,再次校准   else       {                   LCD_Clear(WHITE);    P_Adjust(); 
			TP_Save_Adjdata();	 
		}			
		TP_Get_Adjdata();	

        扫描触摸屏,获得触摸地址的代码如下:

//tp用来区分屏幕坐标或者是物理坐标
u8 TP_Scan(u8 tp)
{			   
	if(PEN==0)
	{
		if(tp)TP_Read_XY2(&tp_dev.x[0],&tp_dev.y[0]);//tp为真,读取物理坐标
		else if(TP_Read_XY2(&tp_dev.x[0],&tp_dev.y[0]))//tp为假,读取屏幕坐标
		{
            //对读取的结果进行转化,转化为可使用的屏幕坐标
	 		tp_dev.x[0]=tp_dev.xfac*tp_dev.x[0]+tp_dev.xoff;
			tp_dev.y[0]=tp_dev.yfac*tp_dev.y[0]+tp_dev.yoff;  
	 	} 
		if((tp_dev.sta&TP_PRES_DOWN)==0)//按键或者触摸屏没有被按下
		{		 
			tp_dev.sta=TP_PRES_DOWN|TP_CATH_PRES;
			tp_dev.x[4]=tp_dev.x[0];
			tp_dev.y[4]=tp_dev.y[0];  	   			 
		}			   
	}else
	{
		if(tp_dev.sta&TP_PRES_DOWN)
		{
			tp_dev.sta&=~(1<<7);	
		}else
		{
			tp_dev.x[4]=0;
			tp_dev.y[4]=0;
			tp_dev.x[0]=0xffff;
			tp_dev.y[0]=0xffff;
		}	    
	}
	return tp_dev.sta&TP_PRES_DOWN;//返回当前触摸屏或者按键的状态
}	  

        触摸屏校准部分的核心代码如下所示:其中xfac yfac xoff yoff用来保存计算坐标偏差时的一些数据。


	tp_dev.sta = 0;//消除触发信号 
	tp_dev.xfac = 0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误	 
	while(1)//如果连续10秒钟没有按下,则自动退出
	{
READJ:
		tp_dev.scan(1);//扫描物理坐标
		if((tp_dev.sta&0xc0)==TP_CATH_PRES)//按键按下了一次
		{	
			outtime = 0;		
			tp_dev.sta &= ~(1<<6);	//标记按键已经被处理过了. 
			pos_temp[cnt][0] = tp_dev.x[0];
			pos_temp[cnt][1] = tp_dev.y[0];
			cnt++;	  
			switch(cnt)
			{			   
				case 1:						 
					TP_Drow_Touch_Point(20,20,WHITE);				//清除点1 
					TP_Drow_Touch_Point(lcddev.width-20,20,RED);	//画点2
					break;
				case 2:
 					TP_Drow_Touch_Point(lcddev.width-20,20,WHITE);	//清除点2
					TP_Drow_Touch_Point(20,lcddev.height-20,RED);	//画点3
					break;
				case 3:
 					TP_Drow_Touch_Point(20,lcddev.height-20,WHITE);			//清除点3
 					TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,RED);	//画点4
					break;                                                                                                                                                                                                                                                          
				case 4:	 //全部四个点已经得到
					for(cnt = 0;cnt < 3;cnt++)//计算三组点的距离是否在允许范围内?
					{ 
						tem1 = abs(pos_temp[TP_ADJDIS_TBL[cnt][0]][0]-pos_temp[TP_ADJDIS_TBL[cnt][1]][0]);//x1-x2/x1-x3/x2-x3
						tem2 = abs(pos_temp[TP_ADJDIS_TBL[cnt][0]][1]-pos_temp[TP_ADJDIS_TBL[cnt][1]][1]);//y1-y2/y1-y3/y2-y3
						tem1 *= tem1;
						tem2 *= tem2;
						d1 = sqrt(tem1+tem2);//得到两点之间的距离 
						tem1 = abs(pos_temp[TP_ADJDIS_TBL[cnt][2]][0]-pos_temp[TP_ADJDIS_TBL[cnt][3]][0]);//x3-x4/x2-x4/x1-x4
						tem2 = abs(pos_temp[TP_ADJDIS_TBL[cnt][2]][1]-pos_temp[TP_ADJDIS_TBL[cnt][3]][1]);//y3-y4/y2-y4/y1-y4
						tem1 *= tem1;
						tem2 *= tem2;
						d2 = sqrt(tem1+tem2);//得到两点之间的距离
						fac = (float)d1/d2;
						if(fac<0.95||fac>1.05||d1==0||d2==0)//不合格
						{
							cnt = 0;
							TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE);	//清除点4
							TP_Drow_Touch_Point(20,20,RED);									//画点1
							TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据   
							goto READJ;	//不合格,重新校准
						}
					}  
					//正确了
					//计算结果
					tp_dev.xfac = (float)(lcddev.width-40)/(pos_temp[1][0]-pos_temp[0][0]);//得到xfac		 
					tp_dev.xoff = (lcddev.width-tp_dev.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;//得到xoff
 					tp_dev.yfac = (float)(lcddev.height-40)/(pos_temp[2][1]-pos_temp[0][1]);//得到yfac
					tp_dev.yoff = (lcddev.height-tp_dev.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;//得到yoff  
					if(abs(tp_dev.xfac)>2||abs(tp_dev.yfac)>2)//触屏和预设的相反了.
					{
						cnt = 0;
 				    	TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE);	//清除点4
   	 					TP_Drow_Touch_Point(20,20,RED);								//画点1
						LCD_ShowString(40,26,lcddev.width,lcddev.height,16,"TP Need readjust!");
						tp_dev.touchtype = !tp_dev.touchtype;//修改触屏类型.
						if(tp_dev.touchtype)//X,Y方向与屏幕相反
						{
							CMD_RDX = 0X90;
							CMD_RDY = 0XD0;	 
						}else				   //X,Y方向与屏幕相同
						{
							CMD_RDX = 0XD0;
							CMD_RDY = 0X90;	 
						}			    
						continue;
					}		
					POINT_COLOR=BLUE;
					LCD_Clear(WHITE);//清屏
					LCD_ShowString(35,110,lcddev.width,lcddev.height,16,"Touch Screen Adjust OK!");//校正完成
					delay_ms(1000);
					TP_Save_Adjdata();  
 					LCD_Clear(WHITE);//清屏   
					return;//校正完成				 
			}
		}
		delay_ms(10);
		outtime++;
		if(outtime>1000)
		{
			TP_Get_Adjdata();
			break;
	 	} 
 	}
}	  

        完成上述操作后,我们就可以完成最神奇的一步——在触摸的点画图。这一步的核心代码如下图所示。

        所谓将触摸点显示出来其实就是,触摸屏控制器获得触摸点位置之后,利用画图函数,以触摸点为中心,给该中心极小范围内的像素点上色的过程。怎么样,是不是简单的出乎意料?

void rtp_test(void)
{
	u8 key;
	u8 i=0;	  
	while(1)
	{
	 	key=KEY_Scan(0);
		tp_dev.scan(0); 		 
		if(tp_dev.sta&TP_PRES_DOWN)			//触摸屏被按下
		{	
		 	if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
			{	
				if(tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)Load_Drow_Dialog();//触摸点在有效范围外,不显示
				else TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED);//触摸点在范围内,使用画图的方式将触摸点表示出来				   
			}
		}else delay_ms(10);		    
		if(key==KEY0_PRES)	//按键被按下,进行强制校准
		{
			LCD_Clear(WHITE);
		    TP_Adjust();  
			TP_Save_Adjdata();	 
			Load_Drow_Dialog();
		}
		i++;
		if(i%20==0)LED0=!LED0;//使用LED灯闪烁表示程序运行
	}
}

        all right ,关于电阻式触摸屏就到这里,你学废了吗?我们下篇文章见!!!拜拜!!!

标签: 电阻电容触摸显示器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台