所有的屏幕, 每对边缘都会有一个相对恒定的电压差值, 每一条边到另外一条边的电压变化也都是恒定的,
这也就是意味着, 我们可以将两个电压差值当作X, Y轴, 如果能够得到当前触摸的点上面的电压, 再知道两边的电压, 就能通过简单的数学公式得到近似于像素点坐标的位置.
(注 : 每一位都可以查询S3C2400中文手册里的说明, 在这里就不细说了)
所以有以下几个步骤:
1 : 我们要开启触摸屏中断, 在点击屏幕的时候能够让开发板知道我们是在点击屏幕, 在这其中触摸屏中断又分为按下中断和抬起中断两个步骤, 在采样当前按下屏幕点的电压值中当然也有不同的步骤.
#define vPRSCEN (1<<14)
#define vPRSCVL (49<<6)
#define vADCCON (vPRSCEN | vPRSCVL)
#define vADCDLY (40000) //该值可以根据 自己的需要来设定采样时间
#define ADCTS_PEN_DOWN_INT (0xD3)
ADCCON = vADCCON;
ADCDLY = vADCDLY;
INTMSK &= ~(1<<31);
INTSUBMSK &= ~(1<<10); //该位可以不同设置, 因为不需要用到ADC中断
INTSUBMSK &= ~(1<<9);
ADCTSC = ADCTS_PEN_DOWN_INT; //十分重要, 是按下中断, 如果不设置, 触摸中断就不会进入
以上是进入触摸IRQ中断的先决条件.
在IRQ中INTOFFSET的偏移量为31
用if语句判断进入按下触摸中断的处理, 再用ADCUPDN判断是按下还是抬起动作 : if(ADCUPDN & (1<<0)) (按下) if(ADCUPDN & (1<<1))(抬起)
2 : 下面就是需要我们来得到我们按下时候的X, Y不同轴上面的电压值, 首先要开始写ADC转换的函数
#define ADCTS_GET_X (0x69)
#define ADCTS_GET_Y (0x9A) /*这三个将要赋值给ADCTSC的定义就决定了你是要得到X轴上面的电压还是Y轴上的还是XY都要得到*/
#define ADCTS_AUTO_XY (0x0C)
#define vENABLE_START (1<<0)
#define ADC_START() (ADCCON |= vENABLE_START) //将转换开始开关打开
#define ACD_WAIT_START() while((ADCCON & vENABLE_START)) //等待转换开始
#define ADC_WAIT_EXCHANGE() while(!(ADCCON & 0x8000)) //等待转换结束
void ADC_Get_XY(int *x, int *y)
{
int i = 0;
for(i=0; i<5; i++) //循环的次数, 能够接近平均值
{
ADCTSC = ADCTS_AUTO_XY; //想要得到XY轴上的电压
ADC_START(); //打开转换开关
ACD_WAIT_START(); //等待转换开始
ADC_WAIT_EXCHANGE(); //等待转换结束
*x += GET_XDATA(); //取得转换的X轴上的电压值
*y += GET_YDATA(); //取得转换的Y轴上的电压值
ADCTSC = ADCTS_PEN_UP_INT; //打开抬起中断, 因为这个函数是按下的时候进入的, 如果想要获得抬起的响应, 就要把抬起中断打开
}
*x = *x/5;
*y = *y/5;
}
3 : 先决条件和方法都有了, 下面就应该在IRQ中断中开始得到电压值
这里有两种方法
第一种方法 :
int id = INTOFFSET;
static int x = 0, y = 0;
static char ax[13] = {0};
static char ay[13] = {0};
if(id == 31)
{
if(ADCUPDN & (1<<0)) //按下
{
ADC_Get_XY(&x, &y);
sprintf(ax, "%d", x);
sprintf(ay, "%d", y);
x = 0;
y = 0;
LCD_printstring_gb2312_16x16(0, 100, 0, 0, "触摸屏幕", 0x1111, 0xffFF);
}
if(ADCUPDN & (1<<1)) //抬起
{
LCD_str_16x16(ax, 50, 10, 0x11111, 0xffaa);
LCD_str_16x16(ay, 50, 50, 0x11111, 0xffaa);
LCD_printstring_gb2312_16x16(0, 150, 0, 0, "离开屏幕", 0x1111, 0xffaa);
ADCTSC = ADCTS_PEN_DOWN_INT; //必须要改成落下中断, 否则是第二次点击屏幕是没有反应的
}
SUBSRCPND |= (1<<9); //清除中断标志
}
这是一种方法, 如果你用了, 就会发现, XY轴的电压值根本不是在你想象中那样变化的, 只会在1~2差值之间浮动, 根本无法通过这样的电压值得到XY 轴坐标.
最根本的原因我也不懂, 我只知道因为采样的数据太少, 总共才采样了六次, 这样的采样方法肯定是不对的.
第二种方法 :
这一种方法就利用了定时器的方法, 如果你们做过了定时器, 并且5个定时器都一一试过去的话, 就会发现, 0 ~ 4的定时器频率是不一样的, 0定时器的频率最 低, 4定时器 的频率最高, 这样我们在按下屏幕的时候, 就能够打开不同的定时器, 控制采样数据的多少.
注意 : 定时器的频率不能过高, 否则采样还没结束就要输出采样值, 这样屏幕上就什么也没有.
假如说你频率很高, 那么你如果在下面的if(id == 12)里面, 加上一个delay函数, 也还是可以显示出正常的结果的.
int id = INTOFFSET;
static int x = 0, y = 0;
static char ax[13] = {0};
static char ay[13] = {0};
if(id == 12)
{
ADC_Get_XY(&x, &y);
sprintf(ax, "%d", x);
sprintf(ay, "%d", y);
x = 0;
y = 0;
}
if(id == 31)
{
if(ADCUPDN & (1<<0))
{
TIME_Init(TIME2, 1);
TIME_Start(TIME2);
LCD_printstring_gb2312_16x16(0, 100, 0, 0, "触摸屏幕", 0x1111, 0xffFF);
ADCUPDN &= ~(1<<0);
}
if(ADCUPDN & (1<<1))
{
TIME_Stop(TIME2);
LCD_str_16x16(ax, 50, 10, 0x11111, 0xffaa);
LCD_str_16x16(ay, 50, 50, 0x11111, 0xffaa);
LCD_printstring_gb2312_16x16(0, 150, 0, 0, "离开屏幕", 0x1111, 0xffaa);
ADCUPDN &= ~(1<<1); //这里也是必须的! 很重要, ADCUPDN 不会自己置为零, 第一次按下没有错,但是第二次的时候, 上面和下面的if都成立, 这样 //定时器会被立即关闭, 来不及采样, 是得不到XY轴电压值的
ADCTSC = ADCTS_PEN_DOWN_INT; //必须要改成落下中断, 否则是第二次点击屏幕是没有反应的
}
SUBSRCPND |= (1<<9);
}
以上的数据是在我的屏幕下面的表现比较优秀的一组, 每个人手上的屏幕数据都是不大一样的, 这需要依靠个人的测试来找到能够比较准确和较快的得出电压值的一组数据.