OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 27564|回复: 1

触摸屏不动

[复制链接]

3

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2010-12-21
在线时间
4 小时
发表于 2010-12-28 11:38:29 | 显示全部楼层 |阅读模式

我把版主的触摸屏程序稍微改动了一下,移植在别的板子上面,触摸屏就出现问题,大家帮我看看问题出在哪里?、红色部分是改动和定义的,其他没有动


(MOSI=PB15; MISO=PB14; SCK=PB13; NSS=PB12;)  PEN==PG7;
//与触摸屏芯片连接引脚   
#define PEN  PGin(7)     //PG7   INT
#define DOUT PBout(15)   //PC15  MOSO
#define TDIN PBin(14)   //PC14  MISO
#define TCLK PBout(13)   //PC13  SCLK
#define TCS  PBout(12)   //PC12  CS


#include "touch.h"
#include "lcd.h"
#include "led.h"
#include "delay.h"
#include "stdlib.h"
#include "math.h"
#include "24cxx.h" 
//ADS7843/7846/UH7843/7846/XPT2046/TSC2046 驱动函数

Pen_Holder Pen_Point;//定义笔实体
//SPI写数据
//向7843写入1byte数据  
void ADS_Write_Byte(u8 num)   

 u8 count=0;  
 for(count=0;count<8;count++) 
 {   
  if(num&0x80)TDIN=1; 
  else TDIN=0;  
  num<<=1;   
  TCLK=0;//上升沿有效     
  TCLK=1;     
 }       
}   
//SPI读数据
//从7846/7843/XPT2046/UH7843/UH7846读取adc值   
u16 ADS_Read_AD(u8 CMD)  
{  
 u8 count=0;   
 u16 Num=0;
 TCLK=0;//先拉低时钟  
 TCS=0; //选中ADS7843 
 ADS_Write_Byte(CMD);//发送命令字
 delay_us(6);//ADS7846的转换时间最长为6us
 TCLK=1;//给1个时钟,清除BUSY       
 TCLK=0;  
 for(count=0;count<16;count++) 
 {      
  Num<<=1;  
  TCLK=0;//下降沿有效          
  TCLK=1;
  if(DOUT)Num++;   
 }   
 Num>>=4;   //只有高12位有效.
 TCS=1;//释放ADS7843 
 return(Num);  
}
//读取一个坐标值
//连续读取READ_TIMES次数据,对这些数据升序排列,
//然后去掉最低和最高LOST_VAL个数,取平均值
#define READ_TIMES 15 //读取次数
#define LOST_VAL 5   //丢弃值
u16 ADS_Read_XY(u8 xy)
{
 u16 i, j;
 u16 buf[READ_TIMES];
 u16 sum=0;
 u16 temp;
 for(i=0;i<READ_TIMES;i++)
 {    
  buf=ADS_Read_AD(xy);    
 }       
 for(i=0;i<READ_TIMES-1; i++)//排序
 {
  for(j=i+1;j<READ_TIMES;j++)
  {
   if(buf>buf[j])//升序排列
   {
    temp=buf;
    buf=buf[j];
    buf[j]=temp;
   }
  }
 }  
 sum=0;
 for(i=LOST_VAL;i<READ_TIMES-LOST_VAL;i++)sum+=buf;
 temp=sum/(READ_TIMES-2*LOST_VAL);
 return temp;  
}
//带滤波的坐标读取
//最小值不能少于100.
u8 Read_ADS(u16 *x,u16 *y)
{
 u16 xtemp,ytemp;         
 xtemp=ADS_Read_XY(CMD_RDX);
 ytemp=ADS_Read_XY(CMD_RDY);                 
 if(xtemp<100||ytemp<100)return 0;//读数失败
 *x=xtemp;
 *y=ytemp;
 return 1;//读数成功

//2次读取ADS7846,连续读取2次有效的AD值,且这两次的偏差不能超过
//50,满足条件,则认为读数正确,否则读数错误.   
//该函数能大大提高准确度
#define ERR_RANGE 50 //误差范围
u8 Read_ADS2(u16 *x,u16 *y)
{
 u16 x1,y1;
  u16 x2,y2;
  u8 flag;   
    flag=Read_ADS(&x1,&y1);  
    if(flag==0)return(0);
    flag=Read_ADS(&x2,&y2);   
    if(flag==0)return(0);  
    if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE))//前后两次采样在+-50内
    &&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE)))
    {
        *x=(x1+x2)/2;
        *y=(y1+y2)/2;
        return 1;
    }else return 0;  
}
//读取一次坐标值 
//仅仅读取一次,知道PEN松开才返回!       
u8 Read_TP_Once(void)
{
 u8 t=0;    
 en_Int_Set(0);//关闭中断
 en_Point.Key_Sta=Key_Up;
 Read_ADS2(&en_Point.X,&en_Point.Y);
 while(PEN==0&&t<=250)
 {
  t++;
  delay_ms(10);
 };
 en_Int_Set(1);//开启中断  
 if(t>=250)return 0;//按下2.5s 认为无效
 else return 1; 
}

//////////////////////////////////////////////////
//与LCD部分有关的函数 
//画一个触摸点
//用来校准用的
void Drow_Touch_Point(u8 x,u16 y)
{
 LCD_DrawLine(x-12,y,x+13,y);//横线
 LCD_DrawLine(x,y-12,x,y+13);//竖线
 LCD_DrawPoint(x+1,y+1);
 LCD_DrawPoint(x-1,y+1);
 LCD_DrawPoint(x+1,y-1);
 LCD_DrawPoint(x-1,y-1);
 Draw_Circle(x,y,6);//画中心圈
}  
//画一个大点
//2*2的点     
void Draw_Big_Point(u8 x,u16 y)
{    
 LCD_DrawPoint(x,y);//中心点
 LCD_DrawPoint(x+1,y);
 LCD_DrawPoint(x,y+1);
 LCD_DrawPoint(x+1,y+1);      
}
//////////////////////////////////////////////////

//转换结果
//根据触摸屏的校准参数来决定转换后的结果,保存在X0,Y0中
void Convert_Pos(void)
{     
 if(Read_ADS2(&en_Point.X,&en_Point.Y))
 {
  en_Point.X0=Pen_Point.xfac*Pen_Point.X+Pen_Point.xoff;
  en_Point.Y0=Pen_Point.yfac*Pen_Point.Y+Pen_Point.yoff; 
 }
}   
//中断,检测到PEN脚的一个下降沿.
//置位Pen_Point.Key_Sta为按下状态
//中断线0线上的中断检测
void EXTI9_5_IRQChanneler(void)
{         
 en_Point.Key_Sta=Key_Down;//按键按下          
 EXTI->PR=1<<7;  //清除LINE1上的中断标志位
}
//-------------------------------------------------------
//PEN中断设置 
void Pen_Int_Set(u8 en)
{
 if(en)EXTI->IMR|=1<<7;   //开启line1上的中断    
 else EXTI->IMR&=~(1<<7); //关闭line1上的中断   
}  
//////////////////////////////////////////////////////////////////////////
//此部分涉及到使用外部EEPROM,如果没有外部EEPROM,屏蔽此部分即可
#ifdef ADJ_SAVE_ENABLE
//保存在EEPROM里面的地址区间基址,占用13个字节(RANGE:SAVE_ADDR_BASE~SAVE_ADDR_BASE+12)
#define SAVE_ADDR_BASE 40
//保存校准参数             
void Save_Adjdata(void)
{
 s32 temp;   
 //保存校正结果!             
 temp=Pen_Point.xfac*100000000;//保存x校正因素     
    AT24CXX_WriteLenByte(SAVE_ADDR_BASE,temp,4);  
 temp=Pen_Point.yfac*100000000;//保存y校正因素   
    AT24CXX_WriteLenByte(SAVE_ADDR_BASE+4,temp,4);
 //保存x偏移量
    AT24CXX_WriteLenByte(SAVE_ADDR_BASE+8,Pen_Point.xoff,2);     
 //保存y偏移量
 AT24CXX_WriteLenByte(SAVE_ADDR_BASE+10,Pen_Point.yoff,2); 
               
 temp=AT24CXX_ReadOneByte(SAVE_ADDR_BASE+12);
 temp&=0XF0;
 temp|=0X0A;//标记校准过了
 AT24CXX_WriteOneByte(SAVE_ADDR_BASE+12,temp);   
}
//得到保存在EEPROM里面的校准值
//返回值:1,成功获取数据
//        0,获取失败,要重新校准
u8 Get_Adjdata(void)
{      
 s32 tempfac;
 tempfac=AT24CXX_ReadOneByte(52);//第五十二字节的第四位用来标记是否校准过!   
 if((tempfac&0X0F)==0X0A)//触摸屏已经校准过了     
 {                
  tempfac=AT24CXX_ReadLenByte(40,4);    
  Pen_Point.xfac=(float)tempfac/100000000;//得到x校准参数
  tempfac=AT24CXX_ReadLenByte(44,4);            
  Pen_Point.yfac=(float)tempfac/100000000;//得到y校准参数
     //得到x偏移量
  tempfac=AT24CXX_ReadLenByte(48,2);        
  Pen_Point.xoff=tempfac;     
     //得到y偏移量
  tempfac=AT24CXX_ReadLenByte(50,2);       
  Pen_Point.yoff=tempfac;     
  return 1; 
 }
 return 0;
}
#endif  
//触摸屏校准代码
//得到四个校准参数
void Touch_Adjust(void)
{        
 u16 pos_temp[4][2];//坐标缓存值
 u8  cnt=0; 
 u16 d1,d2;
 u32 tem1,tem2;
 float fac;    
 cnt=0;    
 POINT_COLOR=BLUE;
 BACK_COLOR =WHITE;
 LCD_Clear(WHITE);//清屏  
 POINT_COLOR=RED;//红色
 LCD_Clear(WHITE);//清屏
 Drow_Touch_Point(20,20);//画点1
 Pen_Point.Key_Sta=Key_Up;//消除触发信号
 Pen_Point.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误 
 while(1)
 {
  if(Pen_Point.Key_Sta==Key_Down)//按键按下了
  {
   if(Read_TP_Once())//得到单次按键值
   {            
    pos_temp[cnt][0]=Pen_Point.X;
    pos_temp[cnt][1]=Pen_Point.Y;
    cnt++;
   }   
   switch(cnt)
   {     
    case 1:
     LCD_Clear(WHITE);//清屏
     Drow_Touch_Point(220,20);//画点2
     break;
    case 2:
     LCD_Clear(WHITE);//清屏
     Drow_Touch_Point(20,300);//画点3
     break;
    case 3:
     LCD_Clear(WHITE);//清屏
     Drow_Touch_Point(220,300);//画点4
     break;
    case 4:  //全部四个点已经得到
           //对边相等
     tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
     tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
     tem1*=tem1;
     tem2*=tem2;
     d1=sqrt(tem1+tem2);//得到1,2的距离
     
     tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
     tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
     tem1*=tem1;
     tem2*=tem2;
     d2=sqrt(tem1+tem2);//得到3,4的距离
     fac=(float)d1/d2;
     if(fac<0.95||fac>1.05||d1==0||d2==0)//不合格
     {
      cnt=0;
      LCD_Clear(WHITE);//清屏
      Drow_Touch_Point(20,20);
      continue;
     }
     tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
     tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
     tem1*=tem1;
     tem2*=tem2;
     d1=sqrt(tem1+tem2);//得到1,3的距离
     
     tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
     tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
     tem1*=tem1;
     tem2*=tem2;
     d2=sqrt(tem1+tem2);//得到2,4的距离
     fac=(float)d1/d2;
     if(fac<0.95||fac>1.05)//不合格
     {
      cnt=0;
      LCD_Clear(WHITE);//清屏
      Drow_Touch_Point(20,20);
      continue;
     }//正确了
          
     //对角线相等
     tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
     tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
     tem1*=tem1;
     tem2*=tem2;
     d1=sqrt(tem1+tem2);//得到1,4的距离
 
     tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
     tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
     tem1*=tem1;
     tem2*=tem2;
     d2=sqrt(tem1+tem2);//得到2,3的距离
     fac=(float)d1/d2;
     if(fac<0.95||fac>1.05)//不合格
     {
      cnt=0;
      LCD_Clear(WHITE);//清屏
      Drow_Touch_Point(20,20);
      continue;
     }//正确了
     //计算结果
     Pen_Point.xfac=(float)200/(pos_temp[1][0]-pos_temp[0][0]);//得到xfac  
     Pen_Point.xoff=(240-Pen_Point.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;//得到xoff
       
     Pen_Point.yfac=(float)280/(pos_temp[2][1]-pos_temp[0][1]);//得到yfac
     Pen_Point.yoff=(320-Pen_Point.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;//得到yoff 
     POINT_COLOR=BLUE;
     LCD_Clear(WHITE);//清屏
     LCD_ShowString(35,110,"Touch Screen Adjust OK!");//校正完成
     delay_ms(1000);
     LCD_Clear(WHITE);//清屏  
     return;//校正完成    
   }
  }
 }
}     
//外部中断初始化函数
void Touch_Init(void)
{           
 //注意,时钟使能之后,对GPIO的操作才有效
 //所以上拉之前,必须使能时钟.才能实现真正的上拉输出
RCC->APB2ENR|=1<<3;    //PB时钟使能(MOSI=PB15; MISO=PB14; SCK=PB13; NSS=PB12;) 
 RCC->APB2ENR|=1<<8;    //PG时钟使能(中断输出,PG7) 
 RCC->APB2ENR|=1<<0;    //开启辅助时钟
         
 GPIOB->CRH&=0X0000FFFF;//PB12~15
 GPIOB->CRH|=0X38330000;

 GPIOG->CRL&=0X0FFFFFFF;//PG7
 GPIOG->CRL|=0X80000000;//PG7 为PEN输入

 GPIOB->ODR|=0XF000;    //PB12~15  全部上拉
 GPIOG->ODR|=0X0080;    //PG7  全部上拉   
  Read_ADS(&Pen_Point.X,&Pen_Point.Y);//第一次读取初始化   
 MY_NVIC_Init(2,0,EXTI9_5_IRQChannel,2); //抢占2,子优先级0,组2
  
 RCC->APB2ENR|=0x01;      //使能io复用时钟    
    AFIO->EXTICR[1]|=0X6000; //EXTI7映射到PG7  
 EXTI->IMR|=1<<7;         //开启line7上的中断
 EXTI->EMR|=1<<7;         //不屏蔽line7上的事件
 EXTI->FTSR|=1<<7;        //line7上事件下降沿触发


#ifdef ADJ_SAVE_ENABLE  
 AT24CXX_Init();//初始化24CXX
  
 if(Get_Adjdata())return;//已经校准
 else      //未校准?
 {           
  LCD_Clear(WHITE);//清屏
     Touch_Adjust();  //屏幕校准
  Save_Adjdata(); 
 }   
 Get_Adjdata();
#else
 LCD_Clear(WHITE);//清屏
    Touch_Adjust();  //屏幕校准,带自动保存
        
#endif
// printf("Pen_Point.xfac:%f\n",Pen_Point.xfac);
// printf("Pen_Point.yfac:%f\n",Pen_Point.yfac);
// printf("Pen_Point.xoff:%d\n",Pen_Point.xoff);
// printf("Pen_Point.yoff:%d\n",Pen_Point.yoff);
}

//====================================

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2010-12-28 14:19:16 | 显示全部楼层
回复【楼主位】zzh0596:
-------------------------------
先看看有没有进中断?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 13:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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