📄 tsp.c
字号:
/**------------------------------------------------------------------------------------------------------
** Modified by: Huangshaobin
** Modified date: 2005.6.1
** Version: 1.1
** Descriptions: 触摸屏校准程序。读取触摸屏左上角和右下角两个指定点的A/D值,保存
** 到E2PROM中(起始地址为0xF0),以后使用触摸屏就不需要再校准。
********************************************************************************************************/
#include "config.h"
//定义E2PROM地址
#define CAT1025 0xA0
// 蜂鸣器控制口定义(P0.7)
#define BEEPCON (1<<7)
// 定义用于保存触摸屏(0,0)和两个校准点的坐标的电压值
uint16 g_vx_min, g_vy_min;
uint16 g_vinx0, g_viny0;
uint16 g_vinx1, g_viny1;
uint32 t0_time;
static BITMAP s_tsp[3];
extern const unsigned int cur1_no;
extern const unsigned char cur1_data[];
extern const unsigned int cur2_no;
extern const unsigned char cur2_data[];
extern const unsigned int save_no;
extern const unsigned char save_data[];
/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时(dly毫秒,与程序运行速度有关)
* 入口参数:dly 延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
for(; dly>0; dly--)
for(i=0; i<800; i++);
}
/****************************************************************************
* 名称:Beep()
* 功能:控制蜂鸣器响一声。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void Beep(void)
{ IO0CLR = BEEPCON;
DelayNS(300);
IO0SET = BEEPCON;
DelayNS(150);
}
/****************************************************************************
* 名称:GetLCD_XY()
* 功能:读取触摸屏上触摸点的坐标。
* 程序会一直等待,直到有触摸输入。
* 入口参数:vx 用于保存触摸点x坐标(LCD)的变量指针
* vy 用于保存触摸点y坐标(LCD)的变量指针
* 出口参数:无
* 说明:先通测量y轴的触摸输入,判断是否有触摸动作。如果有,则进行6次数据
* 采集,并进行去极值平均滤波处理。最后还要判断触摸输入是否合法,只有
* 当触摸输入合法时才返回。
****************************************************************************/
void GetLCD_XY(uint16 *vx, uint16 *vy)
{ uint16 vx_dat, vy_dat;
uint16 vx_dat1, vy_dat1;
while(1)
{ // 判断是否有触摸动作(通过ADS7843的PENIRQ引脚进行判断)
while(1)
{ vy_dat = ADS7843_WriteRead(AIN_Y);
if(vy_dat != 0) break;
DelayNS(1);
} // end of while(1)...
// 进行数据采集
vx_dat = ADS7843_WriteRead(AIN_X);
vy_dat = ADS7843_WriteRead(AIN_Y);
vx_dat1 = ADS7843_WriteRead(AIN_X);
vy_dat1 = ADS7843_WriteRead(AIN_Y);
if((vy_dat<3) || (vy_dat1<3)) continue;
if(vx_dat>vx_dat1)
{ if((vx_dat-vx_dat1) > 13) continue;
}
else
{ if((vx_dat1-vx_dat) > 13) continue;
}
if(vy_dat>vy_dat1)
{ if((vy_dat-vy_dat1) > 18) continue;
}
else
{ if((vy_dat1-vy_dat) > 18) continue;
}
*vx = (vx_dat+vx_dat1) >> 1;
*vy = (vy_dat+vy_dat1) >> 1;
return;
}
}
#define VX_MIN_RANG ((0x0FFF) * 1/5)
#define VY_MIN_RANG ((0x0FFF) * 1/5)
#define VX_MAX_RANG ((0x0FFF) * 4/5)
#define VY_MAX_RANG ((0x0FFF) * 4/5)
/****************************************************************************
* 名称:ChkTouch()
* 功能:触摸屏幕校准程序。会设置g_vx_min、g_vy_min和g_vinx0、g_viny0、
* g_vinx1、g_viny1的值。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void ChkTouch(void)
{ // 在坐标(0,0)上显示校准图标(十字光标),图标格式为20x20,校准点为(10,10)
//GUI_LoadPic(0, 0, (uint8 *)CUR1_DATA, 20, 20);
FillBoxWithBitmap(0,0,&s_tsp[0]);
// 读取触摸输入点坐标值,并判断值是否在合法的范围内
while(1)
{ // 读取触摸输入
GetLCD_XY(&g_vx_min, &g_vy_min);
DelayNS(50); // 延时50mS,防抖
GetLCD_XY(&g_vinx0, &g_viny0);
// 判断触摸输入是否有效
if((g_vy_min<3) || (g_viny0<3)) continue;
if(g_vinx0>g_vx_min)
{ if((g_vinx0-g_vx_min) > 18) continue;
}
else
{ if((g_vx_min-g_vinx0) > 18) continue;
}
if(g_viny0>g_vy_min)
{ if((g_viny0-g_vy_min) > 13) continue;
}
else
{ if((g_vy_min-g_viny0) > 13) continue;
}
// 取得两次触摸输入的平均值
g_vinx0 = (g_vinx0+g_vx_min) >> 1;
g_viny0 = (g_viny0+g_vy_min) >> 1;
// 判断触摸输入是否有效
if((g_vinx0<VX_MIN_RANG) &&
(g_viny0<VY_MIN_RANG))
{ GUI_RectangleFill(0, 0, 0+20, 0+20, WHITE);
Beep();
break;
}
}
// 在坐标(299,219)上显示校准图标(十字光标),图标格式为20x20,校准点为(309,229)
//GUI_LoadPic(219, 299, (uint8 *)CUR1_DATA, 20, 20);
FillBoxWithBitmap(219,299,&s_tsp[0]);
// 读取触摸输入点坐标值,并判断值是否在合法的范围内
while(1)
{ // 读取触摸输入
GetLCD_XY(&g_vx_min, &g_vy_min);
DelayNS(50); // 延时50mS,防抖
GetLCD_XY(&g_vinx1, &g_viny1);
// 判断触摸输入是否有效
if((g_vy_min<3) || (g_viny1<3)) continue;
if(g_vinx1>g_vx_min)
{ if((g_vinx1-g_vx_min) > 18) continue;
}
else
{ if((g_vx_min-g_vinx1) > 18) continue;
}
if(g_viny1>g_vy_min)
{ if((g_viny1-g_vy_min) > 13) continue;
}
else
{ if((g_vy_min-g_viny1) > 13) continue;
}
// 取得两次触摸输入的平均值
g_vinx1 = (g_vinx1+g_vx_min) >> 1;
g_viny1 = (g_viny1+g_vy_min) >> 1;
// 判断触摸输入是否有效
if((g_vinx1>VX_MAX_RANG) &&
(g_viny1>VY_MAX_RANG))
{ GUI_RectangleFill(219, 299, 219+20, 299+20, BLACK);
Beep();
break;
}
}
// 对数据进行转换,以便于得到(0,0)点的电压值
g_vx_min = g_vinx0 - (g_vinx1 - g_vinx0) * 10 /(229 - 10);
g_vy_min = g_viny0 - (g_viny1 - g_viny0) * 10 /(309 - 10);
}
/****************************************************************************
* 名称:DispCommButton()
* 功能:在屏幕上显示“保存”、“重新校准”按钮。
* 图片大小为70*70,显示位置为(250,0)--(319,69)
* 入口参数:无
* 出口参数:无
****************************************************************************/
void DispCommButton(void)
{
FillBoxWithBitmap( 0,320-70, &s_tsp[2]);
}
/****************************************************************************
* 名称:SaveChkData()
* 功能:将触摸屏校准的数据保存到E2PROM中,保存地址为0xE0--0xFF。
* 入口参数:无
* 出口参数:无
* 说明:0xE0、0xE1保存触摸屏是否校准标志,为0x5A、0xA5时表示校准过;
*
* 0xE2、0xE3保存(0,0)点坐标的电压转换值g_vx_min;
* 0xE4、0xE5保存(0,0)点坐标的电压转换值g_vy_min;
* 0xE6、0xE7保存第1个校验点的电压转换值g_vinx0;
* 0xE8、0xE9保存第1个校验点的电压转换值g_viny0;
* 0xEA、0xEB保存第2个校验点的电压转换值g_vinx1;
* 0xEC、0xED保存第2个校验点的电压转换值g_viny1;
*
* 0xF0、0xF1保存第1、2校验点之间的x轴点数wide;
* 0xF2、0xF4保存第1、2校验点之间的y轴点数high;
*
* 其它单元保留。
****************************************************************************/
void SaveChkData(void)
{ uint8 dat_buf1[20];
//uint8 dat_buf2[20];
// int i;
// 设置数据
dat_buf1[0] = 0x5A; // 校准标志
dat_buf1[1] = 0xA5;
dat_buf1[2] = g_vx_min >> 8;
dat_buf1[3] = g_vx_min & 0x00FF;
dat_buf1[4] = g_vy_min >> 8;
dat_buf1[5] = g_vy_min & 0x00FF;
dat_buf1[6] = g_vinx0 >> 8;
dat_buf1[7] = g_vinx0 & 0x00FF;
dat_buf1[8] = g_viny0 >> 8;
dat_buf1[9] = g_viny0 & 0x00FF;
dat_buf1[10] = g_vinx1 >> 8;
dat_buf1[11] = g_vinx1 & 0x00FF;
dat_buf1[12] = g_viny1 >> 8;
dat_buf1[13] = g_viny1 & 0x00FF;
dat_buf1[14] = 0x01; // 值为309 - 10,即0x012B
dat_buf1[15] = 0x2B;
dat_buf1[16] = 0x00; // 值为229 - 10,即0x00DB
dat_buf1[17] = 0xDB;
// 写入数据
I2cWrite(CAT1025, dat_buf1, 14);
DelayNS(10); // 10mS写周期
I2cWrite(CAT1025, &dat_buf1[14], 4);
DelayNS(10); // 10mS写周期
/* 读出校验,若出错,则控制蜂鸣器响5声
I2cRead(CAT1025,dat_buf2, 0xE0, 1,14);
I2cRead(CAT1025,&dat_buf2[14], 0xF0, 1, 4);
for(i=0; i<18; i++)
{ if(dat_buf2[i] != dat_buf1[i])
{ Beep();
Beep();
Beep();
Beep();
Beep();
break;
}
}**/
}
/****************************************************************************
* 名称:TestDelayNS()
* 功能:测试DelayNS函数的延时时间。通过观察t0_time的值计算出实际延时时间。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void TestDelayNS(void)
{ int i;
T1PR = 0; // 设置定时器0分频为1分频,计数频率为Fpclk
for(i=0; i<10; i++)
{ T1TC = 0;
T1TCR = 0x01; // 启动定计器
DelayNS(1); // 调用软件延时
T1TCR = 0x00; // 停止定时器
t0_time = T1TC; // 读取定时计数值
}
}
/****************************************************************************
* 名称:tsp_check()
* 功能:触摸屏校准,并将校准参数保存到E2PROM中。
****************************************************************************/
int tsp_check(void)
{ int x_1, y_1;
uint16 x1_bak, y1_bak;
uint16 vx1, vy1;
// 测试软件延时函数延时时间
TestDelayNS();
// 初始化控制I/O
PINSEL0 = PINSEL0 & 0xFFFF3FFF;
IO0DIR = BEEPCON;
IO0SET = BEEPCON;
IO2DIR = ADS7843_CS|ADS7843_DIN|ADS7843_DCLK;
LoadBitmapFromMem(&s_tsp[0], cur1_data, cur1_no);
LoadBitmapFromMem(&s_tsp[1], cur2_data, cur2_no);
LoadBitmapFromMem(&s_tsp[2], save_data, save_no);
while(1)
{
GUI_ClearSCR(); // 清屏
// 进入触摸屏幕校准程序,会设置g_vx_min、g_vy_min和g_vinx0、g_viny0、
// g_vinx1、g_viny1的值。
ChkTouch();
// 显示操作按钮
DispCommButton();
// 显示原始光标
//GUI_LoadPic_EN(0, 0, (uint8 *)CUR_DATA, 32, 32);
FillBoxWithBitmap(0, 0, &s_tsp[1]);
x1_bak = y1_bak = 0;
// 读取触摸屏输入,在相应位置上显示光标
while(1)
{ // 读取新的触摸点
GetLCD_XY(&vx1, &vy1);
// 转换坐标值
x_1 = (vx1 - g_vx_min) * (229 - 10) / (g_vinx1 - g_vinx0);
y_1 = (vy1 - g_vy_min) * (309 - 10) / (g_viny1 - g_viny0);
if(x_1<0) x_1 = 0;
if(y_1<0) y_1 = 0;
if(x_1>239) x_1 = 239;
if(y_1>319) y_1 = 319;
// 判断是按钮命令
if( (y_1>257) && (y_1<315) &&
(x_1>4) && (x_1<27) ) // 参数保存
{ //SaveChkData();
Beep();
Beep();
}
if( (y_1>257) && (y_1<315) &&
(x_1>40) && (x_1<63) ) // 重新校准
{ Beep();
break;
}
// 不允许移动光标到屏幕上的按钮区(否则会破坏显示)
// 保护矩形区域为(320-70-35,0) -- (319, 70+5)
if((y_1>215) && (x_1<75)) continue;
// 删除上一次的光标显示
GUI_RectangleFill(x1_bak, y1_bak, x1_bak+32, y1_bak+32, BLACK);
// 显示光标
//GUI_LoadPic(x1, y1, (uint8 *)CUR_DATA, 32, 32);
FillBoxWithBitmap(x_1, y_1, &s_tsp[1]);
x1_bak = x_1;
y1_bak = y_1;
} // end of while(1)...
} // end of while(1)...
return(0);
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -