📄 touchstreen.c
字号:
/*
* @file touchstreen.c
* @author dayong
* @version V1.0
* @date 05/24/2012
*/
#include "stm32f10x.h"
#include "fsmc_sram.h"
#include "grlib/grlib.h"
#include "grlib/widget.h"
#include "touchstreen.h"
#include "Calibrate.h"//偏移量矫正算法
#include "lcdhal.h"
#include "usart.h"
//extern TOUCH_CorrectionTypeDef g_TouchCorrectionStruct; //触摸屏矫正量 结构体
#define Up 1
#define Down 0
extern unsigned char g_ucPenUpDownState;
extern PointTypeDef g_strDpy_Point;
extern TOUCH_CorrectionTypeDef g_strTouchCorrectionStruct;
static long (*g_pfnTSHandler)(unsigned long ulMessage, long lX, long lY);
/****************************************************************************
* 名 称:void XTP2046_Init(void)
* 功 能:TFT 触摸屏控制初始化
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:无
****************************************************************************/
void XTP2046_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 时钟使能 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
/* SPI1 SCK(PA5)、MISO(PA6)、MOSI(PA7) 设置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //口线速度50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用模式
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //触摸检测引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* SPI1 触摸芯片的片选控制设置 PB7 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //口线速度50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出模式
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 由于SPI1总线上挂接了4个外设,所以在使用触摸屏时,需要禁止其余3个SPI1 外设, 才能正常工作 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SPI1 SST25VF016B片选
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //SPI1 VS1003片选
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SPI1 网络模块片选
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_4); //SPI CS1
GPIO_SetBits(GPIOB, GPIO_Pin_12); //SPI CS4
GPIO_SetBits(GPIOA, GPIO_Pin_4); //SPI NSS
/* SPI1总线 配置 */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟极性 空闲状态时,SCK保持低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟相位 数据采样从第一个时钟边沿开始
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件产生NSS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //波特率控制 SYSCLK/64
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据高位在前
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC多项式寄存器初始值为7
SPI_Init(SPI1, &SPI_InitStructure);
/* SPI1 使能 */
SPI_Cmd(SPI1,ENABLE);
}
/****************************************************************************
* 名 称:unsigned char SPI_WriteByte(unsigned char data)
* 功 能:SPI1 写函数
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:
****************************************************************************/
unsigned char SPI_WriteByte(unsigned char ucData)
{
unsigned char ucDat = 0;
//等待发送缓冲区空
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
// 发送一个字节
SPI_I2S_SendData(SPI1,ucData);
//等待是否接收到一个字节
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);
// 获得该字节
ucDat = SPI_I2S_ReceiveData(SPI1);
// 返回收到的字节
return ucDat;
}
/****************************************************************************
* 名 称:unsigned char XTP2046ReadX(void)
* 功 能:触摸屏X轴数据读出
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:
****************************************************************************/
unsigned int XTP2046Read_X(void)
{
unsigned int uiX=0;
TP_CS(); //选择XPT2046
Delay(20); //延时
SPI_WriteByte(0x90); //设置X轴读取标志
Delay(20); //延时
uiX=SPI_WriteByte(0x00); //连续读取16位的数据
uiX<<=8;
uiX+=SPI_WriteByte(0x00);
Delay(20); //禁止XPT2046
TP_DCS();
uiX = uiX>>3; //移位换算成12位的有效数据0-4095
//uiX = uiX>>5; //移位换算成10位有效数据
return (uiX);
}
/****************************************************************************
* 名 称:unsigned char XTP2046Read_Y(void)
* 功 能:触摸屏Y轴数据读出
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:
****************************************************************************/
unsigned int XTP2046Read_Y(void)
{
unsigned int uiY =0;
TP_CS(); //选择XPT2046
Delay(20); //延时
SPI_WriteByte(0xD0); //设置Y轴读取标志
Delay(20); //延时
uiY=SPI_WriteByte(0x00); //连续读取16位的数据
uiY<<=8;
uiY+=SPI_WriteByte(0x00);
Delay(20); //禁止XPT2046
TP_DCS();
uiY = uiY>>3; //移位换算成12位的有效数据0-4095
//uiY = uiY>>5; //移位换算成10位有效数据
return (uiY);
}
/****************************************************************************
* 名 称:void Get_Coordinat(POINT *psPOINT)
* 功 能:读取触摸坐标,
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:
****************************************************************************/
//unsigned char Get_Coordinat(POINT *psPOINT)
void Get_Coordinat(PointTypeDef *psPOINT)
{
unsigned int uiX,uiY;
unsigned char ucT,ucT1,ucCount = 0;
unsigned int uiDatabuffer[2][30]; //触摸坐标过采样缓冲区
unsigned int uiTemp=0;
do{
uiX =XTP2046Read_X();
uiY =XTP2046Read_Y(); //循环读数30次
if(uiX>100&&uiX<4000&&uiY>100&&uiY<4000) //如果是在触摸显示有效区范围的值,标示此读数有效
{
uiDatabuffer[0][ucCount]=uiX;
uiDatabuffer[1][ucCount]=uiY;
ucCount++;
}
}while(ucCount<30);
if(ucCount==30) //每次度数一定要读到30次数据,否则丢弃
{
do //将数据X升序排列
{
ucT1=0;
for(ucT=0;ucT<ucCount-1;ucT++)
{
if(uiDatabuffer[0][ucT]>uiDatabuffer[0][ucT+1])//升序排列
{
uiTemp=uiDatabuffer[0][ucT+1];
uiDatabuffer[0][ucT+1]=uiDatabuffer[0][ucT];
uiDatabuffer[0][ucT]=uiTemp;
ucT1=1;
}
}
}while(ucT1);
do //将数据Y升序排列
{
ucT1=0;
for(ucT=0;ucT<ucCount-1;ucT++)
{
if(uiDatabuffer[1][ucT]>uiDatabuffer[1][ucT+1])//升序排列
{
uiTemp=uiDatabuffer[1][ucT+1];
uiDatabuffer[1][ucT+1]=uiDatabuffer[1][ucT];
uiDatabuffer[1][ucT]=uiTemp;
ucT1=1;
}
}
}while(ucT1);
/* 从排序过的数组里中间抽取连续的10组数据,进行取平均值,获得较高的精度 */
for(ucCount=10;ucCount<20; ucCount++)
{
uiX=uiX+uiDatabuffer[0][ucCount];
uiY=uiY+uiDatabuffer[1][ucCount];
}
//USART_OUT(USART1,"0103");
if(uiX%10 > 5)
{
psPOINT->uiX = uiX/10 +1;
// USART_OUT(USART1,"0104");
}
else
{
psPOINT->uiX = uiX/10;
// USART_OUT(USART1,"0105");
}
if(uiY%10 > 5)
{
psPOINT->uiY = (uiY/10 + 1);
// USART_OUT(USART1,"0106");
}
else
{
psPOINT->uiY = (uiY/10);
// USART_OUT(USART1,"0107");
}
// USART_OUT(USART1,"0108");
//return 1;
}
//USART_OUT(USART1,"0109");
USART_OUT(USART1,"x=%d ",psPOINT->uiX);
USART_OUT(USART1,"y=%d ",psPOINT->uiY);
}
/*
#define VALUE 5
unsigned char Get_Coordinat(POINT *psScreen)
{
//POINT *Screen;
int m0,m1,m2;
unsigned char count = 0;
unsigned int databuffer[2][9]={{0},{0}};//
unsigned int temp[3];
while(1)
{
do
{
databuffer[1][count] = XTP2046Read_X(); // V H coordinat swap
databuffer[0][count] = XTP2046Read_Y(); //
count ++;
}while(count<9);
if(count == 9)
{
temp[0]=(databuffer[0][0]+databuffer[0][1]+databuffer[0][2])/3;
temp[1]=(databuffer[0][3]+databuffer[0][4]+databuffer[0][5])/3;
temp[2]=(databuffer[0][6]+databuffer[0][7]+databuffer[0][8])/3;
m0 = temp[0] - temp[1];
m1 = temp[1] - temp[2];
m2 = temp[2] - temp[0];
m0 = m0 > 0 ? m0 : (0-m0);
m1 = m1 > 0 ? m1 : (0-m1);
m2 = m2 > 0 ? m2 : (0-m2);
if(m0 > VALUE && m1 > VALUE && m2 > VALUE)
{
return 0;
}
if(m0 < m1)
{
if(m2 < m0)
psScreen->x = (temp[0] + temp[2])/2;
else
psScreen->x = (temp[0] + temp[1])/2;
}
else
{
if(m2 < m1)
psScreen->x = (temp[0] + temp[2])/2;
else
psScreen->x = (temp[1] + temp[2])/2;
}
temp[0]=(databuffer[1][0]+databuffer[1][1]+databuffer[1][2])/3;
temp[1]=(databuffer[1][3]+databuffer[1][4]+databuffer[1][5])/3;
temp[2]=(databuffer[1][6]+databuffer[1][7]+databuffer[1][8])/3;
m0 = temp[0] - temp[1];
m1 = temp[1] - temp[2];
m2 = temp[2] - temp[0];
m0 = m0 > 0 ? m0 : (0-m0);
m1 = m1 > 0 ? m1 : (0-m1);
m2 = m2 > 0 ? m2 : (0-m2);
if(m0 > VALUE && m1 > VALUE && m2 > VALUE)
{
return 0;
}
if(m0 < m1)
{
if(m2 < m0)
psScreen->y = (temp[0] + temp[2])/2;
else
psScreen->y = (temp[0] + temp[1])/2;
return 1;
}
else
{
if(m2 < m1)
psScreen->y = (temp[0] + temp[2])/2;
else
psScreen->y = (temp[1] + temp[2])/2;
return 1;
}
break;
}
}
return 0;
}
*/
/****************************************************************************
* 名 称:void Get_TouchCorrection(TOUCH_CorrectionTypeDef *TouchCorrectionStruct)
* 功 能:获取触摸屏校正量,
* 入口参数:无
* 出口参数:无
* 说 明:
* 调用方法:
****************************************************************************/
void Get_TouchCorrection(TOUCH_CorrectionTypeDef *TouchCorrectionStruct)
{
PointTypeDef strPoint1; //第一个校正点
PointTypeDef strPoint2; //第二个校正点
unsigned char ucI;
for(ucI=0; ucI<10; ucI++)
{ //在竖屏模式下,左上角显示第一个校正点点击区域
PixelDraw (0,0,0+ucI,0xffff);
PixelDraw (0,0+ucI,0,0xffff);
}
USART_OUT(USART1,"push the first Point");
while (1) //等待点击第一个触摸校正点
{
if(PEN==0) //点击第一个校正点 等待触摸检测电平变低
{
Delay(34000); //延时340ms 消除抖动
if(PEN==0)
{ //检测触摸中断线是否可靠点击
while(PEN==0) //点击未松开,持续读取触摸坐标
{
Delay(1);
Get_Coordinat(&strPoint1);//读取触摸坐标
//获得第一个校正点的X,Y
TouchCorrectionStruct->uiXs=strPoint1.uiX;
TouchCorrectionStruct->uiYs=strPoint1.uiY;
Delay(34000); //延时340ms 消除抖动
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -