stm32触摸屏识别
- 我用的型号
- 准备
- 开始
- 分析例程
- 开始修改
- 结语
我用的型号
我用的是正点的开发板精英板,F103ZET6,电阻屏
准备
正点有一个例程,是触摸屏,注意是触摸屏不是手写识别,我们把它下载下来,烧进去发现是手写的轨迹,就是校准(电容屏忽略)以后手按到哪就显示哪里的线条。
利用这个程序的函数,我们更改,最后目标是规定几个区域,按下去以后可以识别出来,也就是把触摸屏当做软按键来用,老式手机不是都像这样嘛哈哈
开始
分析例程
代码很长,反正能免费下载,我就不复制来了,只捡要说的来说。
在main最下面有一段:
if(tp_dev.touchtype&0X80)
ctp_test(); //电容屏测试
else rtp_test(); //电阻屏测试
这里的测试就是跟踪手写轨迹,啥用都没有,这个函数进去以后就是一直循环,不会自己跳出来的,所以先把它注释,后面可以删掉。
为什么现在不删,因为需要到这个函数定义里面去看看。
右击,go to definition
//电阻触摸屏测试函数
void rtp_test(void)
{
u8 key;
u8 i=0;
while(1)
{
key=KEY_Scan(0);
tp_dev.scan(0);
if(tp_dev.sta&TP_PRES_DOWN) //触摸屏被按下
{
if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
{
if(tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)Load_Drow_Dialog();//清除
else TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED); //画图
}
}else delay_ms(10); //没有按键按下的时候
if(key==KEY0_PRES) //KEY0按下,则执行校准程序
{
LCD_Clear(WHITE);//清屏
TP_Adjust(); //屏幕校准
Load_Drow_Dialog();
}
i++;
if(i%20==0)LED0=!LED0;
}
}
注释很清楚了,先扫描按键,然后扫描屏幕,接下来一个大大的if,如果按下怎样怎样,不按下怎样怎样。
我们先看如果屏幕如果按下了要干什么。
if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
{
if(tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)
Load_Drow_Dialog();//清除
else
TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED); //画图
}
tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height这个条件只是为了更加严谨,它范围就是整个屏幕。
tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)意思是如果按下了右上方24*16这一小块的地方,就清楚整个屏幕。
如果没有按下去,TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED); 注释是画图,而且是红色线条画图。
这个好像就是我们需要的函数了。
再来看看如果屏幕没有按下去会怎样:delay_ms(10);延迟10毫秒。
下面还有几句
if(key==KEY0_PRES) //KEY0按下,则执行校准程序
{
LCD_Clear(WHITE);//清屏
TP_Adjust(); //屏幕校准
Load_Drow_Dialog();
}
这个函数很好,能够很方便的随时调用屏幕校准。其中 TP_Adjust(); 这个子函数可以看看,里面用到了电阻屏校准的原理,在touch.c里面,很长很长,没时间的话这一段完全不需要看,反正调用以后能校准就OK,需要自己改动的可能性极小。
开始修改
既然例程已经看好了,那就自己改动呗。
我需要的是,在屏幕里面显示八行信息,点其中一个就能返回特定的值,即使是1~8也行,反正只要有返回就代表人机交互成功了。
这是显示八行信息的程序,用到了lcd.c(废话当然用到,这个不用到的话显示屏都显示不出来还触摸什么)
Show_Str(20,70,200,16,"选择需要查看的监测点序号:",16,0);
Show_Str(20,100,200,16,"测试点1",16,0);
Show_Str(20,130,200,16,"测试点2",16,0);
Show_Str(20,160,200,16,"测试点3",16,0);
Show_Str(20,190,200,16,"测试点4",16,0);
Show_Str(20,220,200,16,"测试点5",16,0);
Show_Str(20,250,200,16,"测试点6",16,0);
Show_Str(20,280,200,16,"测试点7",16,0);
Show_Str(20,310,200,16,"测试点8",16,0);
然后扫描以下屏幕哪里被触摸了:
tp_dev.scan(0);
再根据每行的像素位置来编触摸的有效位置,触摸到了以后给一个u8的返回值:
u8 chosedot(void)
{
if(tp_dev.sta&TP_PRES_DOWN)
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>100&&tp_dev.y[0]<120)
{
return 1;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>130&&tp_dev.y[0]<150)
{
return 2;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>160&&tp_dev.y[0]<180)
{
return 3;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>190&&tp_dev.y[0]<210)
{
return 4;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>220&&tp_dev.y[0]<240)
{
return 5;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>250&&tp_dev.y[0]<270)
{
return 6;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>280&&tp_dev.y[0]<300)
{
return 7;
}
else
{
if(tp_dev.x[0]>20&&tp_dev.x[0]<100&&tp_dev.y[0]>310&&tp_dev.y[0]<330)
{
return 8;
}
else
return 0;
}
}
}
}
}
}
}
}
}
烧进去看看,好像有问题,屏幕闪烁,程序是不是缺了什么?
缺了延迟,在按下屏幕前一次一次的循环,那加延迟行不行了?也不行,有了延迟扫描频率就降下来了。
我的解决方法是在哪个返回u8的子函数前面加了一直监测触摸信息的循环:
while(!(tp_dev.sta&TP_PRES_DOWN))
tp_dev.scan(0);
如果没有屏幕按下去的信息,那就一直检测被,什么时候有了什么时候去判断。
这个while和后面最大的if也可以合二为一。
结语
测试以后效果很好,电阻屏其实也有它的优点,价格方面就不说了,它的精确度很高啊,虽然定义的每个区域范围并不大,但是误触的概率还是很小的(根据程序,如果误触到没有定义的地方,返回值为0)。
因为时间问题,例程里面还有检测是否校准,如果没有校准还能自动调用校准函数的代码,我直接把它舍弃了,如果需要校准直接按按钮也行,手动强制调出来。 我也是今天上午才把这个带进去调试出来,如果文章有地方写错了欢迎指正。