📄 touch.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 + -