Skip to content

触摸屏

电阻触摸屏只能一次一个点, 电容屏可以有多个

  • 电阻屏: 有两层均匀的电阻叫做ITO层, 有间隔点隔开, 受到压力的时候会接触, 在接触点链接, 使得电阻变化, 一般会引出四根线, X+, X-, Y+, Y-, 分别检测电阻, x和y分开时间供电, 一侧供电, 另一侧检测电压, 使用ADC进行检测, 也可以使用专门的芯片进行检测

触摸校准: 由于硬件的信息不同, 需要校准, 有四线吗五线, 七线, 八线

image-20240104183720715

  • 电容屏: 直接可以得出触点的坐标, 也是用ITO层, X轴Y轴不导电, 之间产生电容, 平时对X轴产生一个波动信号, 当手放上的时候, 会对电路分流, 使得Y达到电压阈值的时间变大, 轮流通电, 同时检测, 可以得到实际的位置

会在交叉的位置形成电容, 电容的位置就是他的坐标

  1. 表面电容型, 利用电场感应触摸, 只能识别一次

image-20230713181001349

  1. 投射式, 利用触摸屏电极发射出静电场线, 有两种电容

自我电容: 扫描电极与地构成的电容

交互电容: 玻璃表面横向纵向的ITO电极交叉处形成的电容

image-20240104180825757

image-20240104184036221

  • 红外线式
  • 表面声波

实现

image-20240104184224558

image-20230713181852133

一边链接电阻屏, 另一边链接stm32, PENDIRQ, 有信号之后产生信号, AUX电压辅助通道不使用,PENIRQ 变低并作为处理器的中断信号

image-20240104184658876

控制原理

4线触摸屏控制器, 使用SPi接口, 内部有一个12位分辨率的ADC, 125KHz, 是一个逐步逼近性的AD转换器

实际上是一个十二位的ADC, 最大为4096, 通过比例获得位置, 使用内部电压源, 通过发送命令获得数据

image-20230713182801896

7: 准备开始检测

6-4:

image-20230713191549154

3: 检测的模式

2: 设置为0, 1的时候使用AUX引脚

1-0: 节省电源, 设置为00的时候会在获取数据的时候再去产生电场

设置为0x90, 获取X通道数字, 0xD0获取Y的数字

image-20230713192050741

使用软件SPI

image-20231026185527854

image-20240104184904794

首先发送一个命令, 之后会获得对应的数据, 在实际接受的时候使用16位进行接收

image-20231026185602822

image-20231026185823730

首选的是差分工作模式, 这时候找到对应的A2-A0的表

image-20231026185835391

选择00, 在两次测量之间会进行自动断电

image-20231026221557923

实际使用的是001和101

image-20240104185503851

c
#define	            XPT2046_CHANNEL_X 	              0x90 	          //通道Y+的选择控制字
#define	            XPT2046_CHANNEL_Y 	              0xd0	          //通道X+的选择控制字

在读取X轴坐标的时候打开Y驱动, 把X轴的驱动关闭0x90=>10010000

读取Y轴坐标的时候打开X轴的驱动, 0xd0 =>11010000

image-20231026222352678

c
//发送命令
void XPT2046_SendCMD(uint8_t cmd)	
{
	uint8_t i;
	
	/*设置引脚的初始状态*/
	XPT2046_CS_ENABLE();//片选引脚设置为低电平
	XPT2046_CLK_LOW();//时钟为低电平
	XPT2046_MOSI_0();
	
	/*片选选中*/
	XPT2046_DelayUS(10);
	XPT2046_CS_DISABLE();
	
	/*产生8个时钟,发送数据*/
	for(i=0;i<8;i++)
	{
		if( (cmd & (0x80>>i)) == 0 )
		{
			XPT2046_MOSI_0();
		}
		else
		{
			XPT2046_MOSI_1();		
		}		
		
		XPT2046_CLK_HIGH();		
		XPT2046_DelayUS(5);
			
		XPT2046_CLK_LOW();
		XPT2046_DelayUS(5);	
	}	
	
//	/*片选取消*/
//	XPT2046_CS_ENABLE();
	
}

在上升沿的时候采样, 高数据位先行

c
//读取数据
uint16_t XPT2046_ReceiveData(void)	
{
	uint8_t i;
	
	uint16_t receive_temp=0;
	
//	/*设置引脚的初始状态*/
//	XPT2046_CS_ENABLE();
//	XPT2046_CLK_LOW();
//	XPT2046_MOSI_0();
//	
//	/*片选选中*/
//	XPT2046_DelayUS(10);
//	XPT2046_CS_DISABLE();
	
		XPT2046_CLK_HIGH();		
		XPT2046_DelayUS(5);
		XPT2046_CLK_LOW();
		XPT2046_DelayUS(5);	
	
	/*产生12个时钟,读取数据*/
	for(i=0;i < 12;i++)
	{		
		receive_temp = receive_temp << 1;

		XPT2046_CLK_HIGH();		
		XPT2046_DelayUS(5);
		
		
		if( XPT2046_MISO() == Bit_SET)
		{
			receive_temp |= 0x01;
		}
		else
		{
			receive_temp |= 0x00;		
		}				
			
		XPT2046_CLK_LOW();
		XPT2046_DelayUS(5);	

	}	
	
	/*片选取消*/
	XPT2046_CS_ENABLE();
	
	return receive_temp;
	
}

高电平的时候数据是稳定的

在发送命令到接收时序直接片选不能中断, 且两个中间有一个时钟间隔, 可以使用一直片选

使用状态机检测

检测输出按下释放两种状态

检测

image-20230713201105922

c
//触摸检测状态机
uint8_t touch_detect(void)
{
	static Touch_State touch_state = XPT2046_STATE_RELEASE; 
	static uint8_t i;
	uint8_t result;
	
	switch(touch_state)
	{
		case XPT2046_STATE_RELEASE:
				//之前没有按下,现在检测为低电平
				if(XPT2046_PENIRQ_Read() == XPT2046_PENIRQ_ActiveLevel)
				{
				
					touch_state = XPT2046_STATE_WAITING;
					result = TOUCH_NOT_PRESSED;
				}
				else
				{							
					touch_state = XPT2046_STATE_RELEASE;
					result = TOUCH_NOT_PRESSED;
				}						
		break;
		
		case XPT2046_STATE_WAITING:
			//在等待状态,再次检测
			if(XPT2046_PENIRQ_Read() == XPT2046_PENIRQ_ActiveLevel)
				{
					i++;
					
					if(i>10)
					{
						//进行延时后检测为按下
						touch_state = XPT2046_STATE_PRESSED;
						result = TOUCH_PRESSED;
					}		
					else
					{	//等待没有结束
						touch_state = XPT2046_STATE_WAITING;
						result = TOUCH_NOT_PRESSED;							
					}										
						
				}
				else
				{					
						i = 0;
						touch_state = XPT2046_STATE_RELEASE;
						result = TOUCH_NOT_PRESSED;
				}				
		
			break;
		
		case XPT2046_STATE_PRESSED:			
						if(XPT2046_PENIRQ_Read() == XPT2046_PENIRQ_ActiveLevel)
						{
								touch_state = XPT2046_STATE_PRESSED;
								result = TOUCH_PRESSED;
						}
						else
						{							
								touch_state = XPT2046_STATE_RELEASE;
								result = TOUCH_NOT_PRESSED;
						}	
			
			break;
	
	}
	
	return result;
}