Appearance
触摸屏
电阻触摸屏只能一次一个点, 电容屏可以有多个
- 电阻屏: 有两层均匀的电阻叫做ITO层, 有间隔点隔开, 受到压力的时候会接触, 在接触点链接, 使得电阻变化, 一般会引出四根线, X+, X-, Y+, Y-, 分别检测电阻, x和y分开时间供电, 一侧供电, 另一侧检测电压, 使用ADC进行检测, 也可以使用专门的芯片进行检测
触摸校准: 由于硬件的信息不同, 需要校准, 有四线吗五线, 七线, 八线
- 电容屏: 直接可以得出触点的坐标, 也是用ITO层, X轴Y轴不导电, 之间产生电容, 平时对X轴产生一个波动信号, 当手放上的时候, 会对电路分流, 使得Y达到电压阈值的时间变大, 轮流通电, 同时检测, 可以得到实际的位置
会在交叉的位置形成电容, 电容的位置就是他的坐标
- 表面电容型, 利用电场感应触摸, 只能识别一次
- 投射式, 利用触摸屏电极发射出静电场线, 有两种电容
自我电容: 扫描电极与地构成的电容
交互电容: 玻璃表面横向纵向的ITO电极交叉处形成的电容
- 红外线式
- 表面声波
实现
一边链接电阻屏, 另一边链接stm32, PENDIRQ, 有信号之后产生信号, AUX电压辅助通道不使用,PENIRQ 变低并作为处理器的中断信号
控制原理
4线触摸屏控制器, 使用SPi接口, 内部有一个12位分辨率的ADC, 125KHz, 是一个逐步逼近性的AD转换器
实际上是一个十二位的ADC, 最大为4096, 通过比例获得位置, 使用内部电压源, 通过发送命令获得数据
7: 准备开始检测
6-4:
3: 检测的模式
2: 设置为0, 1的时候使用AUX引脚
1-0: 节省电源, 设置为00的时候会在获取数据的时候再去产生电场
设置为0x90, 获取X通道数字, 0xD0获取Y的数字
使用软件SPI
首先发送一个命令, 之后会获得对应的数据, 在实际接受的时候使用16位进行接收
首选的是差分工作模式, 这时候找到对应的A2-A0的表
选择00, 在两次测量之间会进行自动断电
实际使用的是001和101
c#define XPT2046_CHANNEL_X 0x90 //通道Y+的选择控制字 #define XPT2046_CHANNEL_Y 0xd0 //通道X+的选择控制字
在读取X轴坐标的时候打开Y驱动, 把X轴的驱动关闭0x90=>10010000
读取Y轴坐标的时候打开X轴的驱动, 0xd0 =>11010000
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;
}
高电平的时候数据是稳定的
在发送命令到接收时序直接片选不能中断, 且两个中间有一个时钟间隔, 可以使用一直片选
使用状态机检测
检测输出按下释放两种状态
检测
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;
}