中科因仑“3+1”工程特种兵精英论坛
标题:
触摸校准 tsc2046 校准失败
[打印本页]
作者:
张衍波
时间:
2015-6-10 09:20
标题:
触摸校准 tsc2046 校准失败
到
搜索
搜索
热搜: 净化器雕刻机阿莫邮购
amoBBS 阿莫电子论坛?论坛首页?单片机?STM32/8?触摸校准 tsc2046 校准失败bottom↓
返回列表发新帖
查看: 1675|回复: 22
打印 上一主题 下一主题 触摸校准 tsc2046 校准失败 [复制链接]
闷鱼
电梯直达跳转到指定楼层 1楼
发表于 2013-9-17 22:59:36 | 只看该作者 回帖奖励
10
莫元
本帖最后由 闷鱼 于 2013-9-18 12:33 编辑
搞出来的数值不对 程序跑得很乱 希望大神指点下
单步调试 不按照规则来走 这个或许是 我调试的方法不对
但是 有时候能够读到一些比较准确的坐标 不过很难控制
看看吧 需要什么信息 我立即补上来
//触摸芯片引脚定义
#define CLR_TDIN() GPIO_ResetBits(GPIOA, GPIO_Pin_6) // 数据输入
#define SET_TDIN() GPIO_SetBits(GPIOA, GPIO_Pin_6)
#define CLR_TCLK() GPIO_ResetBits(GPIOA, GPIO_Pin_5) //时钟
#define SET_TCLK() GPIO_SetBits(GPIOA, GPIO_Pin_5)
#define CLR_TCS() GPIO_ResetBits(GPIOB, GPIO_Pin_7) //片选
#define SET_TCS() GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define TDOUT_IN() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) //数据输出
#define PEN_State() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) //笔中断
#define SAMP_CNT 10 //采用次数
#define SAMP_CNT_DIV2 8 //采用取值个数
#define ADJUST_DE 80 //校验的阀门值,越小越精准但越难校验成功
#define CMD_RDY_t 0X90
#define CMD_RDX_t 0XD0
// spi接收函数
u16 ADS_Read_AD(u8 CMD);
// spi发送函数
void ADS_Write_Byte(u8 num);
uint16_t Phy_X,Phy_Y; //触笔的物理坐标
uint16_t ADC_X,ADC_Y; //触笔的ADC值
float xoff,yoff,xfac,yfac; //触笔的校正值及换算比值
extern u8 fuck;
/*
× 往spi写数据
*/
/* void ADS_Write_Byte(u8 num)
{
u8 count=0;
for(count=0;count<8;count++)
{
if(num&0x80)
{
SET_TDIN();
}
else
CLR_TDIN();
num<<=1;
CLR_TCLK(); //时钟低有效
SET_TCLK();
}
} */
/*
× 接收spi数据
*/
/* uint16_t ADS_Read_AD(u8 CMD)
{
u8 count=0;
u16 Num=0;
CLR_TCLK(); //时钟低有效
//CLR_TDIN(); //
CLR_TCS(); //
ADS_Write_Byte(CMD); // 差分方式
delay_us(6); //ADS7846最少延迟6us busy信号线 低有效
delay_us(1);
SET_TCLK(); //时钟拉高
CLR_TCLK();
for(count=0;count<16;count++) // 还可以改进
{
Num<<=1;
CLR_TCLK(); //
SET_TCLK();
if(TDOUT_IN())
Num++;
}
Num>>=4; //无效的4位
SET_TCS(); //不使用2046
return(Num); //返回读到的数值
} */
/* ************************************ 屏幕校准 ****************************************** */
//////////////////////////////////////屏幕校准//////////////////////////////////////////
//////////////////////////////////////屏幕校准//////////////////////////////////////////
//////////////////////////////////////屏幕校准//////////////////////////////////////////
/* **************************************屏幕校准****************************************** */
/******************************************************************************************
*函数名:Touch_GetPhyXY()
* 参数:void
* 返回值:uint8_t 返回1表示成功,返回0表示失败
* 功能:读取XY物理位置
*********************************************************************************************/
uint8_t Touch_GetPhyXY(void)
{
u8 i, j, k, min;
u16 temp;
u16 tempXY[2][SAMP_CNT], XY[2];// 采样
for(i=0; i<SAMP_CNT; i++)
{
tempXY[0][i] = ADS_Read_AD(CMD_RDX_t);
//LCD_ShowNum(70,150,ADC_X,5); //输出X坐标
tempXY[1][i] = ADS_Read_AD(CMD_RDY_t);
//LCD_ShowNum(150,150,ADC_Y,5);
}
// 滤波
for(k=0; k<2; k++)
{
// 降序排列
for(i=0; i<SAMP_CNT-1; i++)
{
min=i;
for (j=i+1; j<SAMP_CNT; j++)
{
if (tempXY[k][min] > tempXY[k][j])
min=j;
}
temp = tempXY[k][i];
tempXY[k][i] = tempXY[k][min];
tempXY[k][min] = temp;
}
// 设定阈值
if((tempXY[k][SAMP_CNT_DIV2]-tempXY[k][SAMP_CNT_DIV2-1]) > 5)
return 0;
// 求中间值的均值
XY[k] = (tempXY[k][SAMP_CNT_DIV2]+tempXY[k][SAMP_CNT_DIV2-1])>>1;
}
if(XY[0]==0 || XY[1]==2047)return 0;
ADC_X=XY[0];
ADC_Y=XY[1];
// 矫正坐标
Phy_X = (uint16_t)(ADC_X*xfac+xoff);
Phy_Y = (uint16_t)(ADC_Y*yfac+yoff);
return 1;
}
/******************************************************************************************
*函数名:ADS_Write_Byte(u8 num)
* 参数:u8 num
* 返回值:无
* 功能:向7843写入1byte数据
*********************************************************************************************/
void ADS_Write_Byte(u8 num)
{
u8 count=0;
for(count=0;count<8;count++)
{
if(num&0x80)SET_TDIN();
else CLR_TDIN();
num<<=1;
CLR_TCLK();//上升沿有效
SET_TCLK();
}
}
/******************************************************************************************
*函数名:ADS_Read_AD(u8 CMD)
* 参数:u8 CMD
* 返回值:无
* 功能:从7846/7843/XPT2046/UH7843/UH7846读取adc值
*********************************************************************************************/
uint16_t ADS_Read_AD(u8 CMD)
{
u8 count=0;
u16 Num=0;
CLR_TCLK(); //先拉低时钟
//CLR_TDIN(); //拉低数据线
CLR_TCS(); //选中ADS7843
ADS_Write_Byte(CMD);//发送命令字
delay_us(6); //ADS7846的转换时间最长为6us
//CLR_TCLK();
delay_us(1);
SET_TCLK(); //给1个时钟,清除BUSY
CLR_TCLK();
for(count=0;count<16;count++)
{
Num<<=1;
CLR_TCLK(); //下降沿有效
SET_TCLK();
if(TDOUT_IN())Num++;
}
Num>>=4; //只有高12位有效.
SET_TCS(); //释放ADS7843
return(Num);
}
/******************************************************************************************
*函数名:AdjustTouchPanel()
* 参数:void
* 返回值:void
* 功能:触摸屏校准函数
*********************************************************************************************/
void AdjustTouchPanel(void)
{
uint16_t touchXY[5][2];
uint8_t cnt=0;
uint16_t temp1,temp2,temp3;
LCD_Clear(WHITE); //清屏
LCD_SetColors(BLUE,WHITE); //设置前景色和背景色
TP_Drow_Touch_Point(20,20,BLUE); //绘制第一个准星
LCD_ShowString(40,50,"Touch Sight");
while(1)
{
// if(PEN_State()==RESET)
if( fuck == 1) // 如果外部中断响应 fuck 为 1 则说明有按键 执行读取物理坐标的操作
{
f(Touch_GetPhyXY()) //获取物理坐标成功
{
touchXY[cnt][0]=ADC_X; //存储
touchXY[cnt][1]=ADC_Y; //
LCD_ShowString(40,50," ");
//printf("%4d
",ADC_X);//touchXY[%d][0]=
//printf("%d",cnt,); touchXY[%d][1]=
while(PEN_State()== RESET); //等待触笔松开
delay_ms(50); //消抖
cnt++; //跳转到下个点
fuck = 0;
EXTI->IMR |= 0x00000040; //开启Line6
}
label: switch(cnt)
{
case 0:
TP_Drow_Touch_Point(120,160,WHITE); //清除第5个准星位置 TP_Drow_Touch_Point
TP_Drow_Touch_Point(20,20,RED); //绘制第一个准星
break;
case 1:
LCD_ShowNum(0,30,touchXY[cnt-1][0],4, 16); //输出X坐标 LCD_ShowNum
LCD_ShowNum(70,30,touchXY[cnt-1][1],4, 16);
TP_Drow_Touch_Point(20,20,WHITE); //清除第1个准星位置
TP_Drow_Touch_Point(20,300,BLUE); //绘制第二z
break;
case 2:
LCD_ShowNum(0,300,touchXY[cnt-1][0],4, 16); //输出X坐标
LCD_ShowNum(70,300,touchXY[cnt-1][1],4, 16);
TP_Drow_Touch_Point(20,300,WHITE); //清除第2个准星位置
TP_Drow_Touch_Point(220,300,GREEN); //绘制第三个准星
break;
case 3:
LCD_ShowNum(120,300,touchXY[cnt-1][0],4, 16); //输出X坐标
LCD_ShowNum(170,300,touchXY[cnt-1][1],4, 16);
TP_Drow_Touch_Point(220,300,WHITE); //清除第3个准星位置
TP_Drow_Touch_Point(220,20,BLACK); //绘制第四个准星
break;
case 4:
LCD_ShowNum(120,30,touchXY[cnt-1][0],4, 16); //输出X坐标
LCD_ShowNum(160,30,touchXY[cnt-1][1],4, 16);
TP_Drow_Touch_Point(220,300,WHITE); //清除第4个准星位置
TP_Drow_Touch_Point(120,160,BLUE); //绘制第五个准星
break;
case 5:
LCD_ShowNum(90,180,touchXY[cnt-1][0],4, 16); //输出X坐标
LCD_ShowNum(150,180,touchXY[cnt-1][1],4, 16);
temp1=abs(touchXY[3][0]-touchXY[0][0]); //获取上方两点的X的ADC值的差
temp2=abs(touchXY[2][0]-touchXY[1][0]); //获得下方两点的X的ADC值的差
if(abs(temp1-temp2)>ADJUST_DE) //对比偏差是否大于阀值,若大于则不符合
{
cnt=0; //归零
goto label; //跳转重新开始
}
temp3 = temp1 + temp2; //将上下X的ADC的值的差值相加
xfac=200.0/(temp3>>1);//右移n位除以2的n次方 //获取x的比值
temp3=temp3>>2; //将上下X的ADC的值的差值相加除以4和中心点的X的ADC值对比
if(abs(touchXY[4][0]-touchXY[0][0]-temp3)>ADJUST_DE) //对比偏差是否大于阀值,若大于则不符合
{
cnt=0; //归零
goto label; //跳转重新开始
}
temp1=abs(touchXY[1][1]-touchXY[0][1]); //获取左边两点的Y的ADC值的差
temp2=abs(touchXY[2][1]-touchXY[3][1]); //获取右边两点的Y的ADC值的差
if(abs(temp1-temp2)>ADJUST_DE) //对比偏差是否大于阀值,若大于则不符合
{
cnt=0; //归零
goto label; //跳转重新开始
}
temp3=temp1+temp2; //将左右Y的ADC差相加
yfac = 280.0/(temp3>>1); //获取y的比值
temp3=temp3>>2; //将左右Y的ADC差的和除以4和中心点的Y的ADC值对比
if(abs(touchXY[4][1]-touchXY[0][1]-temp3)>ADJUST_DE) //对比偏差是否大于阀值,若大于则不符合
{
cnt=0; //归零
goto label; //跳转重新开始
}
xoff=(240-xfac*(touchXY[0][0]+touchXY[3][0]))/2; //获取到X的修正值
yoff=(320-yfac*(touchXY[0][1]+touchXY[1][1]))/2; //获取到Y的修正值
LCD_ShowString(40,180," Finish");//校验完成
delay_ms(500); //延时
return ; //返回
}
}
}
}
/******************************************************************************************
*函数名:LCD_DrawPoint()
* 参数:uint16_t x,uint16_t y xy坐标
* 返回值:void
* 功能:绘制触摸笔笔尖的点
*********************************************************************************************/
void LCD_DrawTouchPoint(uint16_t x,uint16_t y)
{
LCD_DrawPoint(x,y); //绘制中心点
/*在四周分别绘制点*/
LCD_DrawPoint(x-1,y);
LCD_DrawPoint(x,y-1);
LCD_DrawPoint(x-1,y-1);
LCD_DrawPoint(x+1,y-1);
LCD_DrawPoint(x,y+1);
LCD_DrawPoint(x-1,y+1);
LCD_DrawPoint(x+1,y+1);
LCD_DrawPoint(x+1,y);
}转载
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4