到  
         
搜索 
搜索         
热搜: 净化器雕刻机阿莫邮购 
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); 
}转载 
 
 |