⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 touch2410.c

📁 达盛EL-ARM-830
💻 C
字号:
/*
;************************************************************************************************************
;*				        				北京精仪达盛科技有限公司
;*                                     	     研    发    部
;*
;*                                 	     http://www.techshine.com
;*
;*--------------------------------------------- 文件信息 ----------------------------------------------------                                      
;*
;* 文件名称 : Touch2410.c	
;* 文件功能 : 该文件为S3C2410硬件平台的触摸屏程序驱动程序
;* 补充说明 : 
;*-------------------------------------------- 最新版本信息 -------------------------------------------------
;* 修改作者 : ARM开发小组
;* 修改日期 : 2004/04/25
;* 版本声明 : V1.0.1
;*-------------------------------------------- 历史版本信息 -------------------------------------------------
;* 文件作者 : ARM开发小组
;* 创建日期 : 2004/04/20
;* 版本声明 : v1.0.0
;*-----------------------------------------------------------------------------------------------------------
;*-----------------------------------------------------------------------------------------------------------
;************************************************************************************************************
;*/

#include "..\inc\touch2410.h"
#include "2410addr.h"
#include "..\..\Startup2410\INC\2410lib.h"
#include "LCDdriver.h"

static int TOUCH_X = 0;
static int TOUCH_Y = 0;

#define isDebug 0  //如果此值是1,可以串口输出信息,此值是0,不输出信息

	const int ADCount = 20;
	int ArrayDat0[ADCount];
	
#define avaverage 0
#define optimize 1

#define method avaverage

	
/*
***********************************************************************************************************
*
*          						----***--   配置宏    --***-----
*
***********************************************************************************************************
*/
	
	#ifndef GUI_TOUCH_AD_LEFT      									// 由AD转换器返回的320X240屏的最左面的值
  		//#define GUI_TOUCH_AD_LEFT 		610   
  		#define GUI_TOUCH_AD_LEFT 		40   
	#endif

	#ifndef GUI_TOUCH_AD_RIGHT      								// 由AD转换器返回的320X240屏的最右面的值 
  		#define GUI_TOUCH_AD_RIGHT 		980    
	#endif

	#ifndef GUI_TOUCH_AD_TOP       									// 由AD转换器返回的320X240屏的最上面的值 
  		//#define GUI_TOUCH_AD_TOP 		710
  		#define GUI_TOUCH_AD_TOP 		102
	#endif

	#ifndef GUI_TOUCH_AD_BOTTOM     								// 由AD转换器返回的320X240屏的最下面的值 
  		//#define GUI_TOUCH_AD_BOTTOM  	360
  		#define GUI_TOUCH_AD_BOTTOM  	942
	#endif

	#ifndef GUI_TOUCH_XSIZE
  		#define GUI_TOUCH_XSIZE 		320
	#endif
	#ifndef GUI_TOUCH_YSIZE
  		#define GUI_TOUCH_YSIZE 		240
	#endif

/*
*************************************************************************************************************
- 函数名称: void Touch_Show(int x, int y)
- 函数功能:触摸屏触点显示函数
- 输入参数:x:横坐标,y:纵坐标
- 输出参数:无
*************************************************************************************************************
*/ 
void Touch_Show(int x, int y)
{
    Uart_Printf("量化后的结果:x = %d, y = %d\n\n",x,y);
    Fill_Circle (x, y, 1);
}

/*
*************************************************************************************************************
- 函数名称: void Touch_Init(void)
- 函数功能:初始化触摸屏控制器
- 输入参数:无
- 输出参数:无
*************************************************************************************************************
*/ 
void Touch_Init(void)				
{
    rADCDLY   = (0x5000);	                                   // ADC Start or Interval Delay
	rADCTSC   = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(0<<2)|(3);  //设置成为等待中断模式
	//rADCTSC   = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|(3);  //设置成为等待中断模式,disable int
	rADCCON	= (1<<14)|(49<<6)|(7<<3)|(0<<2)|(1<<1)|(0);	                  //设置ADC控制寄存器
}

/*
*************************************************************************************************************
- 函数名称:void TouchINT_Init(void)
- 函数功能:触摸屏中断初始化
- 输入参数:无
- 输出参数:无
*************************************************************************************************************
*/
void TouchINT_Init(void)													             //触摸屏硬件接口使能
{
    if ((rSRCPND & BIT_ADC)){                 //清除中断挂起位
    	rSRCPND |= BIT_ADC;
    } 
     
     if ((rINTPND & BIT_ADC)){
    	rINTPND |= BIT_ADC;
    }
 
    if ((rSUBSRCPND & BIT_SUB_TC)){
    	rSUBSRCPND |= BIT_SUB_TC;
    }
    
    if ((rSUBSRCPND & BIT_SUB_ADC)){
    	rSUBSRCPND |= BIT_SUB_ADC;
    }
    rINTMSK  &= ~(BIT_ADC);      //相关中断屏蔽位置0,使能中断
    rINTSUBMSK  &= ~(BIT_SUB_TC);
    pISR_ADC = (unsigned)Touch_ISR;             //设置中断向量
}

/*
*************************************************************************************************************
- 函数名称: void __irq Touch(void)
- 函数功能:触摸屏中断
- 输入参数:无
- 输出参数:无
*************************************************************************************************************
*/ 

void __irq  Touch_ISR(void){
	int AD_XY,yPhys,xPhys;
	
	//关中断
	rINTMSK |= (BIT_ADC);
	rINTSUBMSK |= (BIT_SUB_ADC | BIT_SUB_TC);	// 关闭子中断(ADC和TC) 
	
	//获取位置
	AD_XY  = GetTouch_XY_AD();
	yPhys = (AD_XY) & 0xffff;      //获取Y的AD值
    xPhys = (AD_XY >> 16) & 0xffff;//获取X的AD值
    TOUCH_X = AD2X(xPhys);
    TOUCH_Y = AD2Y(yPhys);
   	// 
   	Touch_Show(TOUCH_X,TOUCH_Y);
    //开中断,清空挂起位
    rSUBSRCPND |= BIT_SUB_TC;
    ClearPending(BIT_ADC);
    
    rINTMSK  &= ~(BIT_ADC);
    rINTSUBMSK &= ~(BIT_SUB_ADC);
    rINTSUBMSK &= ~(BIT_SUB_TC);
    
}
/*
*************************************************************************************************************
- 函数名称: void selectsort(int* r,int n)
- 函数功能:选择排序
- 输入参数:r[] is struct rec,n是要排序记录的个数
- 输出参数:无
*************************************************************************************************************
*/
void selectsort(int* r,int n){ //r[] is struct rec,选择排序
    int i,j,k;
    int w;//struct rec
    for(i = 0; i < n - 1; i ++){
        k = i;
        for (j = i + 1; j < n; j ++){
            if (r[j] < r[k])
                k = j;
        }
        if (k != i){
            w=r[i];//交换
            r[i]=r[k];
            r[k]=w;
        }
    }
    #if (isDebug == 1)
        Uart_Printf("Sort::");
        for (i = 0; i < n; i++)
            Uart_Printf("%d, ", r[i]);
        Uart_Printf("  end\n");
    #endif
}

/*
*************************************************************************************************************
- 函数名称: int GetDat0(int* p)
- 函数功能:将采集到的数据进行处理,去除不稳定的抖动值,得到准确的AD转换值
- 输入参数:采集到的数据的指针
- 输出参数:准确的AD转换值
*************************************************************************************************************
*/ 
int GetDat0(int* p){
    int Dat0;
    //const int ADCount = 10;
    int tmp[19];//ADCount - 1
    int i, k, diftag = 0;
    struct ARRAYCMP{
        int difsize;
        int continuecount;
    }ArrayCmp[19];//ADCount - 1
    #if (method == avaverage) //将采集的点数据平均处理
        Dat0 = 0;
        for(i = 0; i < ADCount; i ++){
            Dat0 += p[i];     //转换结果累加,最后取平均
        }
        Dat0 /= ADCount;

    #elif (method == optimize) //取最优点,即选取各点之间差别最小且连续个数最多的点,这是最稳定值
        selectsort(p, ADCount); //将采集到的数据排序(由小到大)
        for (i = 0; i < ADCount - 1; i ++){
            tmp[i] = p[i + 1] - p[i]; //tmp[]存储各点之间的差值
        }
        #if (isDebug == 1)
        Uart_Printf("tmp:\n    ");
        for (i = 0; i < ADCount - 1; i++){
            Uart_Printf("%d,",tmp[i]);
        }
        Uart_Printf("\n");
        #endif
        
        //fill table
        //ArrayCmp是一个表格,表格的第一列存储各点之间的差值,
        //第二列存储相同的点连续存放的个数
        /* 举例:
        tmp[] : 2,0,0,0,2,0,0,2,2
        ArrayCmp[]如下:
        下标	差值	连续个数
        0		2		0
        1		0		2
        2		0		-2
        3		0		-1
        4		2		0
        5		0		1
        6		0		-2
        7		2		1
        */
        ArrayCmp[0].difsize = tmp[0];
        ArrayCmp[0].continuecount = 0;
        k = 0;
        for(i = 1; i < ADCount - 1; i++){
            if ((tmp[i] == tmp[i - 1]) && (diftag == 0)){
                ArrayCmp[i].difsize = tmp[i];
                ArrayCmp[i].continuecount = -2;
                ArrayCmp[i - 1].continuecount = 1;
                diftag = 1;
                k = i - 1;
            }else if ((tmp[i] == tmp[i - 1]) && (diftag == 1)){
                ArrayCmp[i].difsize = tmp[i];
                ArrayCmp[i].continuecount = -1;
                ArrayCmp[k].continuecount += 1;
                diftag = 1;
            }else{ //(tmp[i] != tmp[i - 1])
                ArrayCmp[i].difsize = tmp[i];
                ArrayCmp[i].continuecount = 0;
                diftag = 0;
            }
        }

        #if (isDebug == 1)
        Uart_Printf("ArrayCmp:\n    ");
        for (i = 0; i < ADCount - 1; i++){
            Uart_Printf("%d,  %d,  %d\n",i, ArrayCmp[i].difsize, ArrayCmp[i].continuecount);
        }
        Uart_Printf("\n");
        #endif
        //scan table
        //扫描ArrayCmp[]中差值最小且连续个数最多的点的下标
        k = 0;
        for (i = 1; i < ADCount - 1; i++){
            if (ArrayCmp[i].difsize < ArrayCmp[k].difsize)
                k = i;
            else if (ArrayCmp[i].difsize == ArrayCmp[k].difsize){
                if (ArrayCmp[i].continuecount >= ArrayCmp[k].continuecount)
                    k = i;
            }
        }
        Dat0 = p[k];
        
        
    #endif
    
    return Dat0;
}

/*
***********************************************************************************************************
* 函数名称:  GetTouch_XY_AD(void)
*       					
* 函数功能:  写给触摸屏控制器控制字,把触摸屏控制器转换的AD值放到接收变量AD_XY中
*
* 输入参数:  无
*
* 返回值  :  AD_XY
***********************************************************************************************************
*/
unsigned int GetTouch_XY_AD(void)
{
    int Dat0, i;
    int* p;
                      //转换次数
	unsigned int x, y;              //存放转换结果
	unsigned int AD_XY = 0; //存放最终XY的转换结果

	p = ArrayDat0;                   //初始化累加变量
     		
	while ((rADCDAT0 & 0x8000) | (rADCDAT1 & 0x8000));//测试rADCDAT的bit15是否等于0(触笔按下状态)
 
	//X,Y分别转换模式
	rGPGUP = 0xffff;  //设置GPIO,禁止GPG上拉
	rADCTSC=(0<<8)|(0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|(1);       //设置转换X的位置
	//rADCTSC=(0<<8)|(1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|(1);       //设置转换X的位置
	for(i = 0; i < ADCount; i++){                                //开始转换X,共ADCount次
		rADCCON = (1<<14)|(49<<6)|(7<<3)|(0<<2)|(0<<1)|(1);              //设置控制寄存器
		while(rADCCON & 0x1);                     //测试转换开始位
		while(!(0x8000 & rADCCON));   // 测试ECFLG位,转换是否结束
		Delay(20);
		ArrayDat0[i] = (rADCDAT0) & 0x3ff;
		//Dat0 += (rADCDAT0) & 0x3ff;     //转换结果累加,最后取平均
		
	}
	Dat0 = GetDat0(p);

	
	if (Dat0 != 0)
	{    //如果X有效,继续转换Y
		x = Dat0;
		
		#if (isDebug == 1)
		for (i = 0; i < ADCount; i ++){
	        Uart_Printf("%d, ", ArrayDat0[i]);
	    }
	    Uart_Printf("\n");
	    #endif
		
		rADCTSC=(0<<8)|(1<<7)|(0<<6)|(0<<5)|(1<<4)|(1<<3)|(0<<2)|(2);     //设置转换Y的位置
		//rADCTSC=(0<<8)|(0<<7)|(1<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|(2);     //设置转换Y的位置
		Delay(100);
		for (i = 0; i < ADCount; i++){                             //开始转换Y,共ADCount次
			rADCCON = (1<<14)|(49<<6)|(5<<3)|(0<<2)|(0<<1)|(1);            //设置控制寄存器
			while(rADCCON & 0x1);                    //测试转换开始位
			while(!(0x8000 & rADCCON));  // 测试ECFLG位,转换是否结束
			Delay(20);
			//Dat0 += (rADCDAT1) & 0x3ff;    //转换结果累加,最后取平均
			ArrayDat0[i] = (rADCDAT1) & 0x3ff;
		}
		Dat0 = GetDat0(p);
		y = Dat0;
		
		#if (isDebug == 1)
		for (i = 0; i < ADCount; i ++){
		    Uart_Printf("%d, ",ArrayDat0[i]);
		}
		Uart_Printf("\n",ArrayDat0[i]);
		#endif
	}
	rGPGUP = 0x00;   //设置GPIO,使能GPG上拉
	
	
	Uart_Printf("采样结果::x: %d, y: %d\n",x, y);
	#if (isDebug == 1)
	Uart_Printf("采样结果::x: %d, y: %d\n",x, y);
	#endif
	
	AD_XY = (x << 16) | y;	//高16位存放X,低16位存放Y
		
	//恢复等待中断模式
	Touch_Init();
    Delay(1000);
    
    while (!((rADCDAT0 & 0x8000) & (rADCDAT1 & 0x8000)));       //测试rADCDAT的bit15是否等于1(触笔抬起状态)
     		
 	return AD_XY;	
}

/*
***********************************************************************************************************
* 函数名称:  AD2X(int adx)
* 函数功能:  把AD值转换成X坐标值
* 输入参数:  adx
* 返回值  :  X坐标值
***********************************************************************************************************
*/	
int AD2X(int adx) 									           					// 把AD值转换成坐标值 x
{
	return GUI_TOUCH_XSIZE * (GUI_TOUCH_AD_LEFT - adx) / (GUI_TOUCH_AD_LEFT - GUI_TOUCH_AD_RIGHT);
}
/*
***********************************************************************************************************
* 函数名称:  AD2Y(int ady)
* 函数功能:  把AD值转换成Y坐标值
* 输入参数:  ady
* 返回值  :  Y坐标值
***********************************************************************************************************
*/
int AD2Y(int ady) 																// 把AD值转换成坐标值 y
{
	return GUI_TOUCH_YSIZE * (GUI_TOUCH_AD_TOP - ady) / (GUI_TOUCH_AD_TOP - GUI_TOUCH_AD_BOTTOM);
}
/*
*************************************************************************************************************
*-													结束文件                                               -*
*************************************************************************************************************
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -