查看: 1075|回复: 0
打印 上一主题 下一主题

触摸校准 tsc2046 校准失败

[复制链接]
跳转到指定楼层
沙发
发表于 2015-6-10 09:20:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
到 
       
搜索
搜索       
热搜: 净化器雕刻机阿莫邮购
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);
}转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表