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

📄 touch.c

📁 当手指或笔触摸屏幕时
💻 C
字号:
/****************************************************************
 *  本实验为触摸屏实验											*
 *																*
 *  描述:就是把ads7846触摸屏控制器读出的A/D转换值映射成LCD坐标	*
 *																*
 *  在第三部分《进阶》中可同图形用户界面GUI组合作为输入设备		*  
 *																*
 *  参考:\datashhet\ads7846.pdf								*
 *																*
 ***************************************************************/
 
#include "44b.h"
#include "def.h" 

//#include "44blib.h"


//ads7846同CPU之间的时序:CPU送一个命令字节后ads7846回送两字节的数据
#define COMMAND_GET_X 0xD1      //CPU=>ads7846的读X方向命令       
#define COMMAND_GET_Y 0x91		//CPU=>ads7846的读Y方向命令

#define LCD_XSIZE    320		//LCD的X族方向的点数
#define LCD_YSIZE	 240		//LCD的Y族方向的点数


/********************************************************
 *                                                      *
 *   以下的常量是通过调用校准函数得出                   *
 *   通常每个触摸屏由于其本身材料及制造的不同           *
 *   这些值都有所差异                                   *
 *   在实验中第一步就是分别按下触摸屏的四个角           *
 *   分析得出这四个值                                   *
 *                                                      *
 ********************************************************/ 
#define XORDINAMAX   0x0E78     //X方向A/D最大值   
#define XORDINAMIN   0x180      //X方向A/D最小值
#define YORDINAMAX   0x0DB8     //Y方向A/D最大值
#define YORDINAMIN   0x260      //Y方向A/D最小值

#define beepon()  	{rPDATE =rPDATE |0xff;}
#define beepoff()  	{rPDATE =rPDATE &0x00;}


#define LCD_TOUCH_BUFFER_SIZE    128                

typedef struct tagSTRU_LCDTOUCH       // LCD坐标
{
	INT32U ulX;
	INT32U ulY;
}STRU_LCDTOUCH, *PSTRU_LCDTOUCH;

STRU_LCDTOUCH aStruLcdTouch[LCD_TOUCH_BUFFER_SIZE];  //存放转换好的 LCD 坐标缓存    
INT32 ulLcdTouchBufferIndex = -1;        //缓存区计数




/******************************************************************
 *  (0,0)        (320,0)          (小,大)        (大,大)         *
 *  -----------------               -----------------             *
 *  |               |               |               |             *
 *  |               |               |               |             *
 *  |     LCD       |               |    A/D值      |             *
 *  |    (x,y)      |               |    (X,Y)      |             *
 *  |               |               |               |             *
 *  |               |               |               |             *
 *  -----------------               -----------------             *
 * (0,240)     (320,240)          (小,小)        (大,小)          *
 *                                                                *
 *  上面说明了LCD上的坐标同ads7846的A/D转换值之间的换算关系       *
 *                                                                *
 *   由上推出下列公式:                                           *
 ******************************************************************/
#define ADC2X(adc)   (((adc-XORDINAMIN)*LCD_XSIZE/(XORDINAMAX-XORDINAMIN))%(LCD_XSIZE))
#define ADC2Y(adc)   (((YORDINAMAX-adc)*LCD_YSIZE/(YORDINAMAX-YORDINAMIN))%(LCD_YSIZE))

 
//CS 	PE5     
//CLK 	PF8=SIOCLK
//DIN	PF5=SIOTXD
//DOUT  PF7=SIORXD
//BUSY   PF6=SIORDY
//PenIrq  PG7=EXINT7

#define CS_L()  rPDATE &= 0xffdf          //ads7846的片选选中
#define CS_H()  rPDATE |= 0x0020          //拆除ads7846的片选
#define CLK_L() rPDATF &= 0xfeff		  //CLK 低	
#define CLK_H() rPDATF |= 0x0100		  //CLK 高
#define DIN_L() rPDATF &= 0xffdf		  //ads7846的命令输入腿 低
#define DIN_H() rPDATF |= 0x0020		  //ads7846的命令输入腿 高
#define DOUT()  (rPDATF & 0x80)?1:0 	  //读ads7846的数据输出腿
#define BUSY()  (rPDATF & 0x40)			  //判ads7846内A/D转换完成?	


void Ads7846_Delay(void);                //CLK 的时钟脉宽,太快时ads7846不能接收


//当有触摸时,Exint7上的电平变为LOW
INT8U GetDInt()                      
{
	return (rPDATG & 0x80)?1:0;
}


void mydelay(unsigned int i,unsigned int j)
{ 
	int m,n;
	for (m=0;m<=i;m++)
	{
	  for (n=0;n<j;n++);
	}
}  


//发送8bit的命令到ads7846(DIN 腿)
void Ads7846_SendCommand(INT8U ucCommand)
{
	INT8U i,data;

	data=ucCommand;
	
	for (i = 0; i < 8; i++)
	{
		if (data&0x80)
			DIN_H();        
		else 
		    DIN_L();
		
		data<<=1;            //下一 bit
		CLK_H();
		Ads7846_Delay();     
		CLK_L();             //H->L 下降沿ads7846读入1bit
		DIN_L();
		Ads7846_Delay();
	}
}


//ads7846返回12BIT的A/D转换值
INT32U Ads7846_Get(INT8U ucCommand)
{
	INT8U i;
	INT32U ulData = 0;


	CLK_L();            
	Ads7846_Delay();
	CS_L();						//片选为低: 选中Ads7846
	Ads7846_Delay();
	Ads7846_SendCommand(ucCommand);
	DIN_L();
	CLK_H();
	Ads7846_Delay();
	CLK_L();
	Ads7846_Delay();
	while (BUSY());           //Ads7846的转换时间   判ads7846内A/D转换完成
	for (i = 0; i < 12; i++)  //12 bit 的转换值
	{
		DIN_L();
		ulData <<= 1;		  
		ulData += DOUT();	  //读入一位  读ads7846的数据输出腿
		CLK_H();             
		Ads7846_Delay();
		CLK_L();           
		Ads7846_Delay();
	}
	for (i = 0; i < 3; i++)   //丢调16-12=4位
	{
		DIN_L();
		CLK_H();     
		Ads7846_Delay();
		CLK_L();
		Ads7846_Delay();
	}
	CS_H();						//片选为高
	return ulData;
	
}



//读取完整的A/D值(X,Y)并换算成对应的LCD坐标(x,y)
INT32U QueryAds7846(void)
{
	INT8U i;
	INT32U ulMaxX = 0;
	INT32U ulMinX = 0xffffffff;
	INT32U ulMaxY = 0;
	INT32U ulMinY = 0xffffffff;
	INT32U ulX =  0;
	INT32U ulY =  0;
	INT32U ulAverageY = 0;
	INT32U ulAverageX = 0;

	
	if (GetDInt() == 0)    //有触摸时
	{
		for (i = 0; i < 10; i++)		//取10次 Y 方向的A/D转换值
		{
			ulY = Ads7846_Get(COMMAND_GET_Y);
			if (ulY > ulMaxY)           //去除无理值
			{
				ulMaxY = ulY;
			}
			if (ulY < ulMinY)
			{
				ulMinY = ulY;
			}
			ulAverageY += ulY;
		}
		
		for (i = 0; i < 10; i++)		//取10次 X 方向的A/D转换值
		{
			ulX = Ads7846_Get(COMMAND_GET_X);
			if (ulX > ulMaxX)			//去除无理值
			{
				ulMaxX = ulX;
			}
			if (ulX < ulMinX)
			{
				ulMinX = ulX;
			}
			ulAverageX += ulX;
			
		}
		
		ulAverageX = (ulAverageX - ulMaxX - ulMinX) / 8;     //去除最大和最小值后取平均值
		ulAverageY = (ulAverageY - ulMaxY - ulMinY) / 8;

		if (ulAverageX < XORDINAMIN)  
		    {
		        ulAverageX = XORDINAMIN;
			}		  	
		if (ulAverageX > XORDINAMAX)
			{
		        ulAverageX = XORDINAMAX;
			}		  
		if (ulAverageY < YORDINAMIN)
	        {
	            ulAverageY = YORDINAMIN;
			}		 
		if (ulAverageY > YORDINAMAX)
		    {
		        ulAverageY = YORDINAMAX;
			}	
			
		ulLcdTouchBufferIndex++;
		if (ulLcdTouchBufferIndex == LCD_TOUCH_BUFFER_SIZE)
		{
			ulLcdTouchBufferIndex = 0;
		}
  		aStruLcdTouch[ulLcdTouchBufferIndex].ulX = ADC2X(ulAverageX);
		aStruLcdTouch[ulLcdTouchBufferIndex].ulY = ADC2Y(ulAverageY);
		return 0x1;                       //按下
	}
	else
	{
		return 0x0;           //无按下
	}
	//Ads7846_Init();
}


//CLK时钟的脉宽
void Ads7846_Delay()
{
	volatile INT8U i;
	
	for (i = 0; i < 40; i++);                 
}


//CS 	PE5     
//CLK 	PF8=SIOCLK
//DIN	PF5=SIOTXD
//DOUT  PF7=SIORXD
//BUSY   PF6=SIORDY
//PenIrq  PG7=EXINT7
void Ads7846_Portinit(void)
{
	
//--CS:GPE5
	rPCONE = (rPCONE & ~0xC00) + (0x1 << 10);


//-- SPI(SIO):
	rPCONF=(rPCONF&0x3ff)+(1<<19)+(0<<16)+(0<<13)+(1<<10);
	rPUPF =(rPUPF&~0x1E0) |0x160;//SIORxD 必须接上上拉电阻

//--EXTINT7
	rPCONG &=~0xC000;		//PORTG口的第7位工作为输入方式EINT7
    rPUPG&=0x7f;			//打开Extint7 内部上拉电阻	    




}

/****************************************************************
 *                                                             	*
 *   按触摸屏的四个角分析得出                                  	*
 *	 XORDINAMAX     //X方向A/D最大值 							*  
 *   XORDINAMIN     //X方向A/D最小值							*
 *   YORDINAMAX     //Y方向A/D最大值							*
 *   YORDINAMIN     //Y方向A/D最小值							*
 *   然后校准上面的定义,再重新编译								*
 ****************************************************************/
 
void  CheckTouch(void)
{
	INT8U i;
	INT32U ulMaxX = 0;
	INT32U ulMinX = 0xffffffff;
	INT32U ulMaxY = 0;
	INT32U ulMinY = 0xffffffff;
	INT32U ulX =  0;
	INT32U ulY =  0;
	INT32U ulAverageX = 0;
	INT32U ulAverageY = 0;


	while(GetDInt());
	{
		for (i = 0; i < 130; i++)		//取10次 Y 方向的A/D转换值
		{
			ulY = Ads7846_Get(COMMAND_GET_Y);
			if (ulY > ulMaxY)           //去除无理值
			{
				ulMaxY = ulY;
			}
			if (ulY < ulMinY)
			{
				ulMinY = ulY;
			}
			ulAverageY += ulY;
		}
		
		
		for (i = 0; i < 130; i++)		//取10次 X 方向的A/D转换值
		{
			ulX = Ads7846_Get(COMMAND_GET_X);
			if (ulX > ulMaxX)			//去除无理值
			{
				ulMaxX = ulX;
			}
			if (ulX < ulMinX)
			{
				ulMinX = ulX;
			}
			ulAverageX += ulX;
		}

		ulAverageX = (ulAverageX - ulMaxX - ulMinX) / 128;     //去除最大和最小值后取平均值

		ulAverageY = (ulAverageY - ulMaxY - ulMinY) / 128;
		
		for (i=0;i<10;i++);	//****在此设断点
		
	}                                   
}


void Main(void)
{
	
//_44blib_init();

	Ads7846_Portinit();
	
	//CheckTouch();              //校准时用(按左下角) X、Y 最小
	//CheckTouch();              //校准时用(按右上角) X、Y 最大
    
    while(1) 
		if(GetDInt() == 0)
		{
		    /*beepon();
		    mydelay(1000,100);
		    beepoff();*/
		    if(QueryAds7846())
		    {
		      /* beepon();
		       mydelay(1000,100);
		       beepoff();*/
		       if((aStruLcdTouch[ulLcdTouchBufferIndex].ulX>0xff)&&(aStruLcdTouch[ulLcdTouchBufferIndex].ulY>0xff))
		       {
		       beepon();
		       mydelay(1000,100);
		       beepoff();	
		       }	    
		    }
		}
    
	/*while(1) 
		if(QueryAds7846())
		{
			//Uart_Printf("\nPress at point: (%d,%d)",aStruLcdTouch[ulLcdTouchBufferIndex].ulX,aStruLcdTouch[ulLcdTouchBufferIndex].ulY);
		    beepon();
		    mydelay(1000,100);
		    beepoff();
		   // break; 
		} */
		 
	

}

⌨️ 快捷键说明

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