近视眼怎么恢复

首页 » 常识 » 诊断 » 正点原子战舰V3第三十二章触摸屏实验
TUhjnbcbe - 2023/7/28 21:27:00
白癜风有什么治疗方法 http://pf.39.net/bdfyy/dbfzl/180614/6329464.html

本章,我们将介绍如何使用STM32F1来驱动触摸屏,ALIENTEK战舰STM32F本身并没有触摸屏控制器,但是它支持触摸屏,可以通过外接带触摸屏的LCD模块(比如ALIENTEKTFTLCD模块),来实现触摸屏控制。在本章中,我们将向大家介绍STM32控制ALIENTKETFTLCD模块(包括电阻触摸与电容触摸),实现触摸屏驱动,最终实现一个手写板的功能。本章分为如下几个部分:

32.1电阻与电容触摸屏简介

32.2硬件设计

32.3软件设计

32.4下载验证

32.1触摸屏简介

目前最常用的触摸屏有两种:电阻式触摸屏与电容式触摸屏。下面,我们来分别介绍。

32.1.1电阻式触摸屏

在Iphone面世之前,几乎清一色的都是使用电阻式触摸屏,电阻式触摸屏利用压力感应进

行触点检测控制,需要直接应力接触,通过检测电阻来定位触摸位置。

ALIENTEK2.4/2.8/3.5寸TFTLCD模块自带的触摸屏都属于电阻式触摸屏,下面简单介绍

下电阻式触摸屏的原理。

电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏,这是一种多层的复合

薄膜,它以一层玻璃或硬塑料平板作为基层,表面涂有一层透明氧化金属(透明的导电电阻)

导电层,上面再盖有一层外表面硬化处理、光滑防擦的塑料层、它的内表面也涂有一层涂层、

在他们之间有许多细小的(小于1/英寸)的透明隔离点把两层导电层隔开绝缘。当手指

触摸屏幕时,两层导电层在触摸点位置就有了接触,电阻发生变化,在X和Y两个方向上产生

信号,然后送触摸屏控制器。控制器侦测到这一接触并计算出(X,Y)的位置,再根据获得的

位置模拟鼠标的方式运作。这就是电阻技术触摸屏的最基本的原理。

电阻触摸屏的优点:精度高、价格便宜、抗干扰能力强、稳定性好。

电阻触摸屏的缺点:容易被划伤、透光性不太好、不支持多点触摸。

从以上介绍可知,触摸屏都需要一个AD转换器,一般来说是需要一个控制器的。

ALIENTEKTFTLCD模块选择的是四线电阻式触摸屏,这种触摸屏的控制芯片有很多,包括:

ADS、ADS、TSC、XPT和AK等。这几款芯片的驱动基本上是一样的,

也就是你只要写出了ADS的驱动,这个驱动对其他几个芯片也是有效的。而且封装也有一

样的,完全PINTOPIN兼容。所以在替换起来,很方便。

ALIENTEKTFTLCD模块自带的触摸屏控制芯片为XPT。XPT是一款4导线制触

摸屏控制器,内含12位分辨率KHz转换速率逐步逼近型A/D转换器。XPT支持从1.5V

到5.25V的低电压I/O接口。XPT能通过执行两次A/D转换查出被按的屏幕位置,除此

之外,还可以测量加在触摸屏上的压力。内部自带2.5V参考电压可以作为辅助输入、温度测量

和电池监测模式之用,电池监测的电压范围可以从0V到6V。XPT片内集成有一个温度传

感器。在2.7V的典型工作状态下,关闭参考电压,功耗可小于0.75mW。XPT采用微小

的封装形式:TSSOP-16,QFN-16(0.75mm厚度)和VFBGA-48。工作温度范围为-40℃~+85℃。

该芯片完全是兼容ADS和ADS的,关于这个芯片的详细使用,可以参考这两个

芯片的datasheet。

电阻式触摸屏就介绍到这里。

32.1.2电容式触摸屏

现在几乎所有智能手机,包括平板电脑都是采用电容屏作为触摸屏,电容屏是利用人体感

应进行触点检测控制,不需要直接接触或只需要轻微接触,通过检测感应电流来定位触摸坐标。

ALIENTEK4.3/7寸TFTLCD模块自带的触摸屏采用的是电容式触摸屏,下面简单介绍下

电容式触摸屏的原理。

电容式触摸屏主要分为两种:

1、表面电容式电容触摸屏。

表面电容式触摸屏技术是利用ITO(铟锡氧化物,是一种透明的导电材料)导电膜,通过电

场感应方式感测屏幕表面的触摸行为进行。但是表面电容式触摸屏有一些局限性,它只能识别

一个手指或者一次触摸。

2、投射式电容触摸屏。

投射电容式触摸屏是传感器利用触摸屏电极发射出静电场线。一般用于投射电容传感技术

的电容类型有两种:自我电容和交互电容。

自我电容又称绝对电容,是最广为采用的一种方法,自我电容通常是指扫描电极与地构成

的电容。在玻璃表面有用ITO制成的横向与纵向的扫描电极,这些电极和地之间就构成一个电

容的两极。当用手或触摸笔触摸的时候就会并联一个电容到电路中去,从而使在该条扫描线上

的总体的电容量有所改变。在扫描的时候,控制IC依次扫描纵向和横向电极,并根据扫描前后

的电容变化来确定触摸点坐标位置。笔记本电脑触摸输入板就是采用的这种方式,笔记本电脑

的输入板采用X*Y的传感电极阵列形成一个传感格子,当手指靠近触摸输入板时,在手指和传

感电极之间产生一个小量电荷。采用特定的运算法则处理来自行、列传感器的信号来确定手指

的位置。

交互电容又叫做跨越电容,它是在玻璃表面的横向和纵向的ITO电极的交叉处形成电容。

交互电容的扫描方式就是扫描每个交叉处的电容变化,来判定触摸点的位置。当触摸的时候就

会影响到相邻电极的耦合,从而改变交叉处的电容量,交互电容的扫面方法可以侦测到每个交

叉点的电容值和触摸后电容变化,因而它需要的扫描时间与自我电容的扫描方式相比要长一些,

需要扫描检测X*Y根电极。目前智能手机/平板电脑等的触摸屏,都是采用交互电容技术。

ALIENTEK所选择的电容触摸屏,也是采用的是投射式电容屏(交互电容类型),所以后

面仅以投射式电容屏作为介绍。

透射式电容触摸屏采用纵横两列电极组成感应矩阵,来感应触摸。以两个交叉的电极矩阵,

即:X轴电极和Y轴电极,来检测每一格感应单元的电容变化,如图32.1.2.1所示:

图32.1.2.1投射式电容屏电极矩阵示意

示意图中的电极,实际是透明的,这里是为了方便大家理解。图中,X、Y轴的透明电极

电容屏的精度、分辨率与X、Y轴的通道数有关,通道数越多,精度越高。以上就是电容触摸

屏的基本原理,接下来看看电容触摸屏的优缺点:

电容触摸屏的优点:手感好、无需校准、支持多点触摸、透光性好。

电容触摸屏的缺点:成本高、精度不高、抗干扰能力差。

这里特别提醒大家电容触摸屏对工作环境的要求是比较高的,在潮湿、多尘、高低温环境

下面,都是不适合使用电容屏的。

电容触摸屏一般都需要一个驱动IC来检测电容触摸,且一般是通过IIC接口输出触摸数据

的。ALIENTEK7’TFTLCD模块的电容触摸屏,采用的是15*10的驱动结构(10个感应通道,

15个驱动通道),采用的是GT/FT做为驱动IC。ALIENTEK4.3’TFTLCD模块有两种

成触摸屏:1,使用OTTA作为驱动IC,采用13*8的驱动结构(8个感应通道,13个驱动

通道);2,使用GT作为驱动IC,采用17*10的驱动结构(10个感应通道,17个驱动通

道)。

这两个模块都只支持最多5点触摸,本例程支持ALIENTEK的4.3寸屏模块和新版的7寸

屏模块(采用SSD+FT方案),电容触摸驱动IC,这里只介绍OTTA和GT,

GT/FT的驱动方法同这两款IC是类似的,大家可以参考着学习即可。

OTTA是台湾旭曜科技生产的一颗电容触摸屏驱动IC,最多支持个通道。支持

SPI/IIC接口,在ALIENTEK4.3’TFTLCD电容触摸屏上,OTTA只用了个通道,采

用IIC接口。IIC接口模式下,该驱动IC与STM32F1的连接仅需要4根线:SDA、SCL、RST

和INT,SDA和SCL是IIC通信用的,RST是复位脚(低电平有效),INT是中断输出信号,

关于IIC我们就不详细介绍了,请参考第二十九章。

OTTA的器件地址为0X59(不含最低位,换算成读写命令则是读:0XB3,写:0XB2),

接下来,介绍一下OTTA的几个重要的寄存器。

1,手势ID寄存器

手势ID寄存器(00H)用于告诉MCU,哪些点有效,哪些点无效,从而读取对应的数据,

该寄存器各位描述如表32.1.2.1所示:

表32.1.2.1手势ID寄存器

OTTA支持最多5点触摸,所以表中只有5个位用来表示对应点坐标是否有效,其余

位为保留位(读为0),通过读取该寄存器,我们可以知道哪些点有数据,哪些点无数据,如果

读到的全是0,则说明没有任何触摸。

2,传感器控制寄存器(ODH)

传感器控制寄存器(ODH),该寄存器也是8位,仅最高位有效,其他位都是保留,当最

高位为1的时候,打开传感器(开始检测),当最高位设置为0的时候,关闭传感器(停止检测)。

3,坐标数据寄存器(共20个)

坐标数据寄存器总共有20个,每个坐标占用4个寄存器,坐标寄存器与坐标的对应关系如

表32.1.2.2所示:

表32.1.2.2坐标寄存器与坐标对应表

从表中可以看出,每个坐标的值,可以通过4个寄存器读出,比如读取坐标1(X1,Y1),

我们则可以读取01H~04H,就可以知道当前坐标1的具体数值了,这里我们也可以只发送寄存

器01,然后连续读取4个字节,也可以正常读取坐标1,寄存器地址会自动增加,从而提高读

取速度。

OTTA相关寄存器的介绍就介绍到这里,更详细的资料,请参考:OTTAIIC协议

指导.pdf这个文档。OTTA只需要经过简单的初始化就可以正常使用了,初始化流程:复

位→延时ms→释放复位→设置传感器控制寄存器的最高位位1,开启传感器检查。就可以

正常使用了。

另外,OTTA有两个地方需要特别注意一下:

1,OTTA的寄存器是8位的,但是发送的时候要发送16位(高八位有效),才可

以正常使用。

2,OTTA的输出坐标,默认是以:X坐标最大值是,Y坐标最大值是

的分辨率输出的,也就是输出范围为:X:0~,Y:0~;MCU在读取到坐

标后,必须根据LCD分辨率做一个换算,才能得到真实的LCD坐标。

下面我们简单介绍下GT,该芯片是深圳汇顶科技研发的一颗电容触摸屏驱动IC,支

持Hz触点扫描频率,支持5点触摸,支持18*10个检测通道,适合小于4.5寸的电容触摸

屏使用。

和OTTA一样,GT与MCU连接也是通过4根线:SDA、SCL、RST和INT。不

过,GT的IIC地址,可以是0X14或者0X5D,当复位结束后的5ms内,如果INT是高电

平,则使用0X14作为地址,否则使用0X5D作为地址,具体的设置过程,请看:GT数据

手册.pdf这个文档。本章我们使用0X14作为器件地址(不含最低位,换算成读写命令则是读:

0X29,写:0X28),接下来,介绍一下GT的几个重要的寄存器。

1,控制命令寄存器(0X)

该寄存器可以写入不同值,实现不同的控制,我们一般使用0和2这两个值,写入2,即

可软复位GT,在硬复位之后,一般要往该寄存器写2,实行软复位。然后,写入0,即可

正常读取坐标数据(并且会结束软复位)。

2,配置寄存器组(0X~0X8)

这里共个寄存器,用于配置GT的各个参数,这些配置一般由厂家提供给我们(一

个数组),所以我们只需要将厂家给我们的配置,写入到这些寄存器里面,即可完成GT的

配置。由于GT可以保存配置信息(可写入内部FLASH,从而不需要每次上电都更新配置),

我们有几点注意的地方提醒大家:1,0X寄存器用于指示配置文件版本号,程序写入的版

本号,必须大于等于GT本地保存的版本号,才可以更新配置。2,0X80FF寄存器用于存

储校验和,使得0X~0X80FF之间所有数据之和为0。3,0X8用于控制是否将配置保存

在本地,写0,则不保存配置,写1则保存配置。

3,产品ID寄存器(0X~0X)

这里总共由4个寄存器组成,用于保存产品ID,对于GT,这4个寄存器读出来就是:

9,1,4,7四个字符(ASCII码格式)。因此,我们可以通过这4个寄存器的值,来判断驱动

IC的型号,从而判断是OTTA还是GT,以便执行不同的初始化。

4,状态寄存器(0XE)

该寄存器各位描述如表32.1.2.3所示:

表32.1.2.3状态寄存器各位描述

这里,我们仅关心最高位和最低4位,最高位用于表示buffer状态,如果有数据(坐标/

按键),buffer就会是1,最低4位用于表示有效触点的个数,范围是:0~5,0,表示没有触摸,

5表示有5点触摸。这和前面OTTA的表示方法稍微有点区别,OTTA是每个位表示

一个触点,这里是有多少有效触点值就是多少。最后,该寄存器在每次读取后,如果bit7有效,

则必须写0,清除这个位,否则不会输出下一次数据!!这个要特别注意!!!

5,坐标数据寄存器(共30个)

这里共分成5组(5个点),每组6个寄存器存储数据,以触点1的坐标数据寄存器组为例,

如表32.1.2.4所示:

表32.1.2.4触点1坐标寄存器组描述

我们一般只用到触点的x,y坐标,所以只需要读取0X~0X的数据,组合即可得

到触点坐标。其他4组分别是:0X、0X、0X和0X等开头的16个寄存器组

成,分别针对触点2~4的坐标。同样GT也支持寄存器地址自增,我们只需要发送寄存器

组的首地址,然后连续读取即可,GT会自动地址自增,从而提高读取速度。

GT相关寄存器的介绍就介绍到这里,更详细的资料,请参考:GT编程指南.pdf

这个文档。

GT只需要经过简单的初始化就可以正常使用了,初始化流程:硬复位→延时10ms→

结束硬复位→设置IIC地址→延时ms→软复位→更新配置(需要时)→结束软复位。此时

GT即可正常使用了。

然后,我们不停的查询0XE寄存器,判断是否有有效触点,如果有,则读取坐标数据

寄存器,得到触点坐标,特别注意,如果0XE读到的值最高位为1,就必须对该位写0,否

则无法读到下一次坐标数据。

电容式触摸屏部分,就介绍到这里。

32.2硬件设计

本章实验功能简介:开机的时候先初始化LCD,读取LCDID,随后,根据LCDID判断

是电阻触摸屏还是电容触摸屏,如果是电阻触摸屏,则先读取24C02的数据判断触摸屏是否已

经校准过,如果没有校准,则执行校准程序,校准过后再进入电阻触摸屏测试程序,如果已经

校准了,就直接进入电阻触摸屏测试程序。

如果是4.3寸电容触摸屏,则先读取芯片ID,判断是不是GT,如果是则执行GT

的初始化代码,如果不是,则执行OTTA的初始化代码;如果是7寸电容触摸屏(仅支持

新款7寸屏,使用SSD+FT方案),则执行FT的初始化代码,在初始化电容触

摸屏完成后,进入电容触摸屏测试程序(电容触摸屏无需校准!!)。

电阻触摸屏测试程序和电容触摸屏测试程序基本一样,只是电容触摸屏支持最多5点同时

触摸,电阻触摸屏只支持一点触摸,其他一模一样。测试界面的右上角会有一个清空的操作区

域(RST),点击这个地方就会将输入全部清除,恢复白板状态。使用电阻触摸屏的时候,可

以通过按KEY0来实现强制触摸屏校准,只要按下KEY0就会进入强制校准程序。

所要用到的硬件资源如下:

1)指示灯DS0

2)KEY0按键

3)TFTLCD模块(带电阻/电容式触摸屏)

4)24C02

所有这些资源与STM32F1的连接图,在前面都已经介绍了,这里我们只针对TFTLCD模

块与STM32F1的连接端口再说明一下,TFTLCD模块的触摸屏(电阻触摸屏)总共有5跟线

与STM32F1连接,连接电路图如图32.2.1所示:

图32.2.1触摸屏与STM32F1的连接图

从图中可以看出,T_MOSI、T_MISO、T_SCK、T_CS和T_PEN分别连接在STM32F1的:PF9、

PB2、PB1、PF11和PF10上。

如果是电容式触摸屏,我们的接口和电阻式触摸屏一样(上图右侧接口),只是没有用到

五根线了,而是四根线,分别是:T_PEN(CT_INT)、T_CS(CT_RST)、T_CLK(CT_SCL)和

T_MOSI(CT_SDA)。其中:CT_INT、CT_RST、CT_SCL和CT_SDA分别是OTTA/GT/FT

的:中断输出信号、复位信号,IIC的SCL和SDA信号。这里,我们用查询的方式读取

OTTA/GT/FT的数据,对于OTTA/FT没有用到中断信号(CT_INT),所以

同STM32F1的连接,最少只需要3根线即可,不过GT还需要用到CT_INT做IIC地址设定,所以需要4根线连接。

32.3软件设计

打开本章实验工程目录可以看到,我们在HARDWARE文件夹下新建了一个TOUCH文件

夹,然后新建了touch.c、touch.h、ctiic.c、ctiic.h、otta.c、otta.h、gt.c、gt.h、

ft.c和ft.h等十个文件用来存放触摸屏相关的代码。同时引入这些源文件到工程

HARDWARE分组之下,并将TOUCH文件夹加入头文件包含路径。其中,touch.c和touch.h

是电阻触摸屏部分的代码,顺带兼电容触摸屏的管理控制,其他则是电容触摸屏部分的代码。

打开touch.c文件,里面主要是与触摸屏相关的代码(主要是电阻触摸屏的代码),这里我

们也不全部贴出来了,仅介绍几个重要的函数。

首先我们要介绍的是TP_Read_XY2这个函数,该函数专门用于从电阻式触摸屏控制IC读取

坐标的值(0~),TP_Read_XY2的代码如下:

//连续2次读取触摸屏IC,且这两次的偏差不能超过

//ERR_RANGE,满足条件,则认为读数正确,否则读数错误.

//该函数能大大提高准确度

//x,y:读取到的坐标值

//返回值:0,失败;1,成功。

#defineERR_RANGE50//误差范围

u8TP_Read_XY2(u16*x,u16*y)

u16x1,y1;

u16x2,y2;

u8flag;

flag=TP_Read_XY(x1,y1);

if(flag==0)return(0);

flag=TP_Read_XY(x2,y2);

if(flag==0)return(0);

//前后两次采样在+-50内

if(((x2=x1x1x2+ERR_RANGE)

(x1=x2x2x1+ERR_RANGE))

((y2=y1y1y2+ERR_RANGE)

(y1=y2y2y1+ERR_RANGE)))

*x=(x1+x2)/2;

*y=(y1+y2)/2;

return1;

}elsereturn0;

该函数采用了一个非常好的办法来读取屏幕坐标值,就是连续读两次,两次读取的值之差

不能超过一个特定的值(ERR_RANGE),通过这种方式,我们可以大大提高触摸屏的准确度。另

外该函数调用的TP_Read_XY函数,用于单次读取坐标值。TP_Read_XY也采用了一些软件滤波

算法,具体见光盘的源码。接下来,我们介绍另外一个函数TP_Adjust,该函数源码如下:

//触摸屏校准代码

//得到四个校准参数

voidTP_Adjust(void)

u16pos_temp[4][2];//坐标缓存值

u8cnt=0;u32tem1,tem2;

u16d1,d2;u16outtime=0;

doublefac;

POINT_COLOR=BLUE;

BACK_COLOR=WHITE;

LCD_Clear(WHITE);//清屏

POINT_COLOR=RED;//红色

LCD_Clear(WHITE);//清屏

POINT_COLOR=BLACK;

LCD_ShowString(40,40,,,16,(u8*)TP_REMIND_MSG_TBL);//显示提示信息

TP_Drow_Touch_Point(20,20,RED);//画点1

tp_dev.sta=0;//消除触发信号

tp_dev.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误

while(1)//如果连续10秒钟没有按下,则自动退出

tp_dev.scan(1);//扫描物理坐标

if((tp_dev.sta0xc0)==TP_CATH_PRES)//按键按下了一次(此时按键松开了.)

outtime=0;

tp_dev.sta=~(16);//标记按键已经被处理过了.

pos_temp[cnt][0]=tp_dev.x;

pos_temp[cnt][1]=tp_dev.y;

cnt++;

switch(cnt)

case1:

TP_Drow_Touch_Point(20,20,WHITE);//清除点1

TP_Drow_Touch_Point(lcddev.width-20,20,RED);//画点2

break;

case2:

TP_Drow_Touch_Point(lcddev.width-20,20,WHITE);//清除点2

TP_Drow_Touch_Point(20,lcddev.height-20,RED);//画点3

break;

case3:

TP_Drow_Touch_Point(20,lcddev.height-20,WHITE);//清除点3

TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,RED);

//画点4

break;

case4://全部四个点已经得到

//对边相等

tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2

tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2

tem1*=tem1;

tem2*=tem2;

d1=sqrt(tem1+tem2);//得到1,2的距离

tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4

tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4

tem1*=tem1;

tem2*=tem2;

d2=sqrt(tem1+tem2);//得到3,4的距离

fac=(float)d1/d2;

if(fac0.95

fac1.05

d1==0

d2==0)//不合格

cnt=0;

TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE);

//清除点4

TP_Drow_Touch_Point(20,20,RED);//画点1

TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1]

[0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3]

[0],pos_temp[3][1],fac*);//显示数据

continue;

tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3

tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3

tem1*=tem1;

tem2*=tem2;

d1=sqrt(tem1+tem2);//得到1,3的距离

tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4

tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4

tem1*=tem1;

tem2*=tem2;

d2=sqrt(tem1+tem2);//得到2,4的距离

fac=(float)d1/d2;

if(fac0.95

fac1.05)//不合格

cnt=0;

TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,

WHITE);//清除点4

TP_Drow_Touch_Point(20,20,RED);//画点1

TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1]

[0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3]

[0],pos_temp[3][1],fac*);//显示数据

continue;

}//正确了

//对角线相等

tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3

tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3

tem1*=tem1;

tem2*=tem2;

d1=sqrt(tem1+tem2);//得到1,4的距离

tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4

tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4

tem1*=tem1;

tem2*=tem2;

d2=sqrt(tem1+tem2);//得到2,3的距离

fac=(float)d1/d2;

if(fac0.95

fac1.05)//不合格

cnt=0;

TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,

WHITE);//清除点4

TP_Drow_Touch_Point(20,20,RED);//画点1

TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1]

[0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3]

[0],pos_temp[3][1],fac*);//显示数据

continue;

}//正确了

//计算结果

tp_dev.xfac=(float)(lcddev.width-40)/(pos_temp[1][0]-pos_temp[0][0]);

//得到xfac

tp_dev.xoff=(lcddev.width-tp_dev.xfac*(pos_temp[1][0]+pos_temp[0]

[0]))/2;//得到xoff

tp_dev.yfac=(float)(lcddev.height-40)/(pos_temp[2][1]-pos_temp[0][1]

);//得到yfac

tp_dev.yoff=(lcddev.height-tp_dev.yfac*(pos_temp[2][1]+pos_temp[0]

[1]))/2;//得到yoff

if(abs(tp_dev.xfac)2

abs(tp_dev.yfac)2)//触屏和预设的相反了.

cnt=0;

TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,WHITE

);//清除点4

TP_Drow_Touch_Point(20,20,RED);//画点1

LCD_ShowString(40,26,lcddev.width,lcddev.height,16,TPNeed

readjust!);

tp_dev.touchtype=!tp_dev.touchtype;//修改触屏类型.

if(tp_dev.touchtype)//X,Y方向与屏幕相反

{CMD_RDX=0X90;CMD_RDY=0XD0;}

else{CMD_RDX=0XD0;CMD_RDY=0X90;}

//X,Y方向与屏幕相同

continue;

POINT_COLOR=BLUE;

LCD_Clear(WHITE);//清屏

LCD_ShowString(35,,lcddev.width,lcddev.height,16,TouchScreen

AdjustOK!);//校正完成

delay_ms();

TP_Save_Adjdata();

LCD_Clear(WHITE);//清屏

return;//校正完成

delay_ms(10);outtime++;

if(outtime){TP_Get_Adjdata();break;}

TP_Adjust是此部分最核心的代码,在这里,给大家介绍一下我们这里所使用的触摸屏校

正原理:我们传统的鼠标是一种相对定位系统,只和前一次鼠标的位置坐标有关。而触摸屏则

是一种绝对坐标系统,要选哪就直接点哪,与相对定位系统有着本质的区别。绝对坐标系统的

特点是每一次定位坐标与上一次定位坐标没有关系,每次触摸的数据通过校准转为屏幕上的坐

标,不管在什么情况下,触摸屏这套坐标在同一点的输出数据是稳定的。不过由于技术原理的

原因,并不能保证同一点触摸每一次采样数据相同,不能保证绝对坐标定位,点不准,这就是

触摸屏最怕出现的问题:漂移。对于性能质量好的触摸屏来说,漂移的情况出现并不是很严重。

所以很多应用触摸屏的系统启动后,进入应用程序前,先要执行校准程序。通常应用程序中使

用的LCD坐标是以像素为单位的。比如说:左上角的坐标是一组非0的数值,比如(20,20),

而右下角的坐标为(,)。这些点的坐标都是以像素为单位的,而从触摸屏中读出的是点

的物理坐标,其坐标轴的方向、XY值的比例因子、偏移量都与LCD坐标不同,所以,需要在

程序中把物理坐标首先转换为像素坐标,然后再赋给POS结构,达到坐标转换的目的。

校正思路:在了解了校正原理之后,我们可以得出下面的一个从物理坐标到像素坐标的转

换关系式:

LCDx=xfac*Px+xoff;

LCDy=yfac*Py+yoff;

其中(LCDx,LCDy)是在LCD上的像素坐标,(Px,Py)是从触摸屏读到的物理坐标。xfac,

yfac分别是X轴方向和Y轴方向的比例因子,而xoff和yoff则是这两个方向的偏移量。

这样我们只要事先在屏幕上面显示4个点(这四个点的坐标是已知的),分别按这四个点就

可以从触摸屏读到4个物理坐标,这样就可以通过待定系数法求出xfac、yfac、xoff、yoff这四

个参数。我们保存好这四个参数,在以后的使用中,我们把所有得到的物理坐标都按照这个关

系式来计算,得到的就是准确的屏幕坐标。达到了触摸屏校准的目的。

TP_Adjust就是根据上面的原理设计的校准函数,注意该函数里面多次使用了

lcddev.width和lcddev.height,用于坐标设置,主要是为了兼容不同尺寸的LCD(比如*、

*和*的屏都可以兼容)。

接下来看看触摸屏初始化函数:TP_Init,该函数根据LCD的ID(即lcddev.id)判别是电

阻屏还是电容屏,执行不同的初始化,该函数代码如下:

//触摸屏初始化

//返回值:0,没有进行校准

//1,进行过校准

u8TP_Init(void)

if(lcddev.id==0X)//4.3寸电容触摸屏

if(GT_Init()==0)//是GT

tp_dev.scan=GT_Scan;//扫描函数指向GT触摸屏扫描

}else

OTTA_Init();

tp_dev.scan=OTTA_Scan;//扫描函数指向OTTA触摸屏扫描

tp_dev.touchtype

=0X80;//电容屏

tp_dev.touchtype

=lcddev.dir0X01;//横屏还是竖屏

return0;

}elseif(lcddev.id==0X)//7寸电容触摸屏

FT_Init();

tp_dev.scan=FT_Scan;//扫描函数指向GT触摸屏扫描

tp_dev.touchtype

=0X80;//电容屏

tp_dev.touchtype

=lcddev.dir0X01;//横屏还是竖屏

return0;

}else

GPIO_InitTypeDefGPIO_Initure;

__HAL_RCC_GPIOB_CLK_ENABLE();//开启GPIOB时钟

__HAL_RCC_GPIOF_CLK_ENABLE();//开启GPIOF时钟

//PB1

GPIO_Initure.Pin=GPIO_PIN_1;//PB1

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出

GPIO_Initure.Pull=GPIO_PULLUP;//上拉

GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速

HAL_GPIO_Init(GPIOB,GPIO_Initure);

//PB2

GPIO_Initure.Pin=GPIO_PIN_2;//PB2

GPIO_Initure.Mode=GPIO_MODE_INPUT;//上拉输入

HAL_GPIO_Init(GPIOB,GPIO_Initure);

//PF9,11

GPIO_Initure.Pin=GPIO_PIN_9

GPIO_PIN_11;//PF9,11

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出

HAL_GPIO_Init(GPIOF,GPIO_Initure);

//PF10

GPIO_Initure.Pin=GPIO_PIN_10;//PF10

GPIO_Initure.Mode=GPIO_MODE_INPUT;//输入

GPIO_Initure.Pull=GPIO_PULLUP;//上拉

HAL_GPIO_Init(GPIOF,GPIO_Initure);

TP_Read_XY(tp_dev.x[0],tp_dev.y[0]);//第一次读取初始化

AT24CXX_Init();//初始化24CXX

if(TP_Get_Adjdata())return0;//已经校准

else//未校准?

LCD_Clear(WHITE);//清屏

TP_Adjust();//屏幕校准

TP_Get_Adjdata();

return1;

该函数比较简单,重点说一下:tp_dev.scan,这个结构体函数指针,默认是指向TP_Scan

的,如果是电阻屏则用默认的即可,如果是电容屏,则指向新的扫描函数GT_Scan、

OTTA_Scan或FT_Scan(根据芯片ID判断到底指向那个),执行电容触摸屏的扫描函

数,这几个函数在后续会介绍。

其他的函数我们这里就不多介绍了,保存touch.c文件,并把该文件加入到HARDWARE组下。

接下来打开touch.h文件,在该文件里面输入如下代码:

#defineTP_PRES_DOWN0x80//触屏被按下

#defineTP_CATH_PRES0x40//有按键按下了

#defineCT_MAX_TOUCH5//电容屏支持的点数,固定为5点

//触摸屏控制器

typedefstruct

u8(*init)(void);//初始化触摸屏控制器

u8(*scan)(u8);//扫描触摸屏.0,屏幕扫描;1,物理坐标;

void(*adjust)(void);//触摸屏校准

u16x[CT_MAX_TOUCH];//当前坐标

u16y[CT_MAX_TOUCH];//电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次

//扫描时触屏的坐标,用x[4],y[4]存储第一次按下时的坐标.

u8sta;//笔的状态

//b7:按下1/松开0;

//PF9,11

GPIO_Initure.Pin=GPIO_PIN_9

GPIO_PIN_11;//PF9,11

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出

HAL_GPIO_Init(GPIOF,GPIO_Initure);

//PF10

GPIO_Initure.Pin=GPIO_PIN_10;//PF10

GPIO_Initure.Mode=GPIO_MODE_INPUT;//输入

GPIO_Initure.Pull=GPIO_PULLUP;//上拉

HAL_GPIO_Init(GPIOF,GPIO_Initure);

TP_Read_XY(tp_dev.x[0],tp_dev.y[0]);//第一次读取初始化

AT24CXX_Init();//初始化24CXX

if(TP_Get_Adjdata())return0;//已经校准

else//未校准?

LCD_Clear(WHITE);//清屏

TP_Adjust();//屏幕校准

TP_Get_Adjdata();

return1;

该函数比较简单,重点说一下:tp_dev.scan,这个结构体函数指针,默认是指向TP_Scan

的,如果是电阻屏则用默认的即可,如果是电容屏,则指向新的扫描函数GT_Scan、

OTTA_Scan或FT_Scan(根据芯片ID判断到底指向那个),执行电容触摸屏的扫描函

数,这几个函数在后续会介绍。

其他的函数我们这里就不多介绍了,保存touch.c文件,并把该文件加入到HARDWARE组下。

接下来打开touch.h文件,在该文件里面输入如下代码:

#defineTP_PRES_DOWN0x80//触屏被按下

#defineTP_CATH_PRES0x40//有按键按下了

#defineCT_MAX_TOUCH5//电容屏支持的点数,固定为5点

//触摸屏控制器

typedefstruct

u8(*init)(void);//初始化触摸屏控制器

u8(*scan)(u8);//扫描触摸屏.0,屏幕扫描;1,物理坐标;

void(*adjust)(void);//触摸屏校准

u16x[CT_MAX_TOUCH];//当前坐标

u16y[CT_MAX_TOUCH];//电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次

//扫描时触屏的坐标,用x[4],y[4]存储第一次按下时的坐标.

u8sta;//笔的状态

//b7:按下1/松开0;

ctiic.c和ctiic.h是电容触摸屏的IIC接口部分代码,与第二十八章的myiic.c和myiic.h基本

一样,这里就不单独介绍了,记得把ctiic.c加入HARDWARE组下。接下来看看:otta.c,

在该文件输入如下代码:

//向OTTA写入一次数据

//reg:起始寄存器地址

//buf:数据缓缓存区

//len:写数据长度

//返回值:0,成功;1,失败.

u8OTTA_WR_Reg(u16reg,u8*buf,u8len)

u8i;u8ret=0;

CT_IIC_Start();

CT_IIC_Send_Byte(OTT_CMD_WR);CT_IIC_Wait_Ack();//发送写命令

CT_IIC_Send_Byte(reg8);CT_IIC_Wait_Ack();//发送高8位地址

CT_IIC_Send_Byte(reg0XFF);CT_IIC_Wait_Ack();//发送低8位地址

for(i=0;ilen;i++)

CT_IIC_Send_Byte(buf);ret=CT_IIC_Wait_Ack();//发数据

if(ret)break;

CT_IIC_Stop();//产生一个停止条件

returnret;

//从OTTA读出一次数据

//reg:起始寄存器地址

//buf:数据缓缓存区

//len:读数据长度

voidOTTA_RD_Reg(u16reg,u8*buf,u8len)

u8i;

CT_IIC_Start();

CT_IIC_Send_Byte(OTT_CMD_WR);CT_IIC_Wait_Ack();//发送写命令

CT_IIC_Send_Byte(reg8);CT_IIC_Wait_Ack();//发送高8位地址

CT_IIC_Send_Byte(reg0XFF);CT_IIC_Wait_Ack();//发送低8位地址

CT_IIC_Start();

CT_IIC_Send_Byte(OTT_CMD_RD);CT_IIC_Wait_Ack();//发送读命令

for(i=0;ilen;i++)buf=CT_IIC_Read_Byte(i==(len-1)?0:1);//发数据

CT_IIC_Stop();//产生一个停止条件

//传感器打开/关闭操作

//cmd:1,打开传感器;0,关闭传感器

voidOTTA_SensorControl(u8cmd)

u8regval=0X00;

if(cmd)regval=0X80;

OTTA_WR_Reg(OTT_CTRL_REG,regval,1);

//初始化触摸屏

//返回值:0,初始化成功;1,初始化失败

u8OTTA_Init(void)

u8regval=0;

GPIO_InitTypeDefGPIO_Initure;

__HAL_RCC_GPIOF_CLK_ENABLE();//开启GPIOF时钟

GPIO_Initure.Pin=GPIO_PIN_11;//PF11

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出

GPIO_Initure.Pull=GPIO_PULLUP;//上拉

GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速

HAL_GPIO_Init(GPIOF,GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_10;//PF10

GPIO_Initure.Mode=GPIO_MODE_INPUT;//输入

HAL_GPIO_Init(GPIOF,GPIO_Initure);

CT_IIC_Init();//初始化电容屏的I2C总线

OTT_RST=0;//复位

delay_ms();

OTT_RST=1;//释放复位

delay_ms();

OTTA_SensorControl(1);//打开传感器

OTTA_RD_Reg(OTT_CTRL_REG,regval,1);//读取传感器运行寄存器的值来

//判断I2C通信是否正常

printf(CTPID:%x\r\n,regval);

if(regval==0x80)return0;

return1;

constu16OTT_TPX_TBL[5]={OTT_TP1_REG,OTT_TP2_REG,OTT_TP3_REG,OTT_TP4

_REG,OTT_TP5_REG};

//扫描触摸屏(采用查询方式)

//mode:0,正常扫描.

//返回值:当前触屏状态.

//0,触屏无触摸;1,触屏有触摸

u8OTTA_Scan(u8mode)

u8buf[4];

u8i=0;

u8res=0;

staticu8t=0;//控制查询间隔,从而降低CPU占用率

t++;

if((t%10)==0

t10)//空闲时,每进入10次,才检测1次,从而节省CPU使用率

OTTA_RD_Reg(OTT_GSTID_REG,mode,1);//读取触摸点的状态

if(mode0X1F)

tp_dev.sta=(mode0X1F)

TP_PRES_DOWN

TP_CATH_PRES;

for(i=0;i5;i++)

if(tp_dev.sta(1i))//触摸有效?

OTTA_RD_Reg(OTT_TPX_TBL,buf,4);//读取XY坐标值

if(tp_dev.touchtype0X01)//横屏

tp_dev.y=(((u16)buf[2]8)+buf[3])*OTT_SCAL_Y;

tp_dev.x=-((((u16)buf[0]8)+buf[1])*OTT_SCAL_X);

}else

tp_dev.x=(((u16)buf[2]8)+buf[3])*OTT_SCAL_Y;

tp_dev.y=(((u16)buf[0]8)+buf[1])*OTT_SCAL_X;

//printf(x[%d]:%d,y[%d]:%d\r\n,i,tp_dev.x,i,tp_dev.y);

res=1;

if(tp_dev.x[0]==0tp_dev.y[0]==0)mode=0;//数据全0,则忽略此次数据

t=0;//触发一次,则会最少连续监测10次,从而提高命中率

if((mode0X1F)==0)//无触摸点按下

if(tp_dev.staTP_PRES_DOWN)tp_dev.sta=~(17);//之前是按下,标记松开

else//之前就没有被按下

tp_dev.x[0]=0xffff;

tp_dev.y[0]=0xffff;

tp_dev.sta=0XE0;//清除点有效标记

if(t)t=10;//重新从10开始计数

returnres;

此部分总共5个函数,其中OTTA_WR_Reg和OTTA_RD_Reg分别用于读写

OTTA芯片,这里特别注意寄存器地址是16位的,与OTTA手册介绍的是有出入的,

必须16位才能正常操作。另外,重点介绍下OTTA_Scan函数,OTTA_Scan函数用

于扫描电容触摸屏是否有按键按下,由于我们不是用的中断方式来读取OTTA的数据的,

而是采用查询的方式,所以这里使用了一个静态变量来提高效率,当无触摸的时候,尽量减少

对CPU的占用,当有触摸的时候,又保证能迅速检测到。至于对OTTA数据的读取,则

完全是我们在上面介绍的方法,先读取手势ID寄存器(OTT_GSTID_REG),判断是不是有有

效数据,如果有,则读取,否则直接忽略,继续后面的处理。

其他的函数我们这里就不多介绍了,保存otta.c文件,并把该文件加入到HARDWARE

组下,otta.h代码我们这里就不贴出来了,大家参考开发板光盘源码即可。

接下来看下gt.c里面的代码,这里我们仅介绍GT_Init和GT_Scan两个函数,

代码如下:

//初始化GT触摸屏

//返回值:0,初始化成功;1,初始化失败

u8OTTA_Init(void)

u8regval=0;

GPIO_InitTypeDefGPIO_Initure;

__HAL_RCC_GPIOF_CLK_ENABLE();//开启GPIOF时钟

GPIO_Initure.Pin=GPIO_PIN_11;//PF11

GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出

GPIO_Initure.Pull=GPIO_PULLUP;//上拉

GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速

HAL_GPIO_Init(GPIOF,GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_10;//PF10

GPIO_Initure.Mode=GPIO_MODE_INPUT;//输入

HAL_GPIO_Init(GPIOF,GPIO_Initure);

CT_IIC_Init();//初始化电容屏的I2C总线

OTT_RST=0;//复位

delay_ms();

OTT_RST=1;//释放复位

delay_ms();

OTTA_SensorControl(1);//打开传感器

OTTA_RD_Reg(OTT_CTRL_REG,regval,1);//读取传感器运行寄存器的值来判断

I2C通信是否正常

printf(CTPID:%x\r\n,regval);

if(regval==0x80)return0;

return1;

constu16GT_TPX_TBL[5]={GT_TP1_REG,GT_TP2_REG,GT_TP3_REG,

GT_TP4_REG,GT_TP5_REG};

//扫描触摸屏(采用查询方式)

//mode:0,正常扫描.

//返回值:当前触屏状态.

//0,触屏无触摸;1,触屏有触摸

u8GT_Scan(u8mode)

u8buf[4];

u8i=0;u8res=0;u8temp;u8tempsta;

staticu8t=0;//控制查询间隔,从而降低CPU占用率

t++;

if((t%10)==0

t10)//空闲时,每10次CTP_Scan函数才检测1次,从而节省CPU使用率

GT_RD_Reg(GT_GSTID_REG,mode,1);//读取触摸点的状态

if(mode0X80((mode0XF)6))

temp=0;

GT_WR_Reg(GT_GSTID_REG,temp,1);//清标志

if((mode0XF)((mode0XF)6))

temp=0XFF(mode0XF);//将点的个数转换为1的位数,匹配tp_dev.sta定义

tempsta=tp_dev.sta;//保存当前的tp_dev.sta值

tp_dev.sta=(~temp)

TP_PRES_DOWN

TP_CATH_PRES;

tp_dev.x[4]=tp_dev.x[0];//保存触点0的数据

tp_dev.y[4]=tp_dev.y[0];

for(i=0;i5;i++)

if(tp_dev.sta(1i))//触摸有效?

GT_RD_Reg(GT_TPX_TBL,buf,4);//读取XY坐标值

if(tp_dev.touchtype0X01)//横屏

tp_dev.y=((u16)buf[1]8)+buf[0];

tp_dev.x=-(((u16)buf[3]8)+buf[2]);

}else

tp_dev.x=((u16)buf[1]8)+buf[0];

tp_dev.y=((u16)buf[3]8)+buf[2];

//printf(x[%d]:%d,y[%d]:%d\r\n,i,tp_dev.x,i,tp_dev.y);

res=1;

if(tp_dev.x[0]lcddev.width

tp_dev.y[0]lcddev.height)//非法数据(坐标超出了)

if((mode0XF)1)//其他点有数据,则复制第二点的数据到第一点.

tp_dev.x[0]=tp_dev.x[1];

tp_dev.y[0]=tp_dev.y[1];

t=0;//触发一次,则连续监测10次,从而提高命中率

}else//非法数据,则忽略此次数据(还原原来的)

tp_dev.x[0]=tp_dev.x[4];

tp_dev.y[0]=tp_dev.y[4];

mode=0X80;

tp_dev.sta=tempsta;//恢复tp_dev.sta

}elset=0;//触发一次,则会最少连续监测10次,从而提高命中率

if((mode0X8F)==0X80)//无触摸点按下

if(tp_dev.staTP_PRES_DOWN)//之前是被按下的

tp_dev.sta=~(17);//标记按键松开

}else//之前就没有被按下

tp_dev.x[0]=0xffff;

tp_dev.y[0]=0xffff;

tp_dev.sta=0XE0;//清除点有效标记

if(t)t=10;//重新从10开始计数

returnres;

以上代码,GT_Init用于初始化GT,该函数通过读取0X~0X这4个寄存

器,并判断是否是:“”,来确定是不是GT芯片,在读取到正确的ID后,软复位GT,

然后根据当前芯片版本号,确定是否需要更新配置,通过GT_Send_Cfg函数,发送配置信

息(一个数组),配置完后,结束软复位,即完成GT初始化。GT_Scan函数,用于读

取触摸屏坐标数据,这个和前面的OTTA_Scan大同小异,大家看源码即可。

保存gt.c文件,并把该文件加入到HARDWARE组下。另外,ft.c和ft.h的

代码,我们就不再介绍了,请大家参考光盘本例程源码。

最后我们打开test.c,修改部分代码,这里就不全部贴出来了,仅介绍三个重要的函数:

//5个触控点的颜色(电容触摸屏用)

constu16POINT_COLOR_TBL[5]={RED,GREEN,BLUE,BROWN,GRED};

//电阻触摸屏测试函数

voidrtp_test(void)

u8key;u8i=0;

while(1)

key=KEY_Scan(0);

tp_dev.scan(0);

if(tp_dev.staTP_PRES_DOWN)//触摸屏被按下

if(tp_dev.x[0]lcddev.widthtp_dev.y[0]lcddev.height)

if(tp_dev.x[0](lcddev.width-24)tp_dev.y[0]16)Load_Drow_Dialog();

elseTP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],RED);//画图

}elsedelay_ms(10);//没有按键按下的时候

if(key==KEY0_PRES)//KEY0按下,则执行校准程序

LCD_Clear(WHITE);//清屏

TP_Adjust();//屏幕校准

Load_Drow_Dialog();

i++;

if(i%20==0)LED0=!LED0;

//电容触摸屏测试函数

voidctp_test(void)

u8t=0;u8i=0;

u16lastpos[5][2];//最后一次的数据

while(1)

tp_dev.scan(0);

for(t=0;tCT_MAX_TOUCH;t++)

if((tp_dev.sta)(1t))

if(tp_dev.x[t]lcddev.widthtp_dev.y[t]lcddev.height)

if(lastpos[t][0]==0XFFFF)

lastpos[t][0]=tp_dev.x[t];

lastpos[t][1]=tp_dev.y[t];

lcd_draw_bline(lastpos[t][0],lastpos[t][1],tp_dev.x[t],tp_dev.y[t],2,

POINT_COLOR_TBL[t]);//画线

lastpos[t][0]=tp_dev.x[t];

lastpos[t][1]=tp_dev.y[t];

if(tp_dev.x[t](lcddev.width-24)tp_dev.y[t]16)

Load_Drow_Dialog();//清除

}elselastpos[t][0]=0XFFFF;

delay_ms(5);i++;

if(i%20==0)LED0=!LED0;

intmain(void)

HAL_Init();//初始化HAL库

Stm32_Clock_Init(RCC_PLL_MUL9);//设置时钟,72M

delay_init(72);//初始化延时函数

uart_init();//初始化串口

LED_Init();//初始化LED

KEY_Init();//初始化按键

LCD_Init();//初始化LCD

tp_dev.init();//触摸屏初始化

POINT_COLOR=RED;

LCD_ShowString(30,50,,16,16,WarShipSTM32);

LCD_ShowString(30,70,,16,16,TOUCHTEST);

LCD_ShowString(30,90,,16,16,ATOM

ALIENTEK);

LCD_ShowString(30,,,16,16,/9/19);

if(tp_dev.touchtype!=0XFF)

LCD_ShowString(30,,,16,16,PressKEY0toAdjust);//电阻屏才显示

delay_ms();

Load_Drow_Dialog();

if(tp_dev.touchtype0X80)ctp_test();//电容屏测试

elsertp_test();//电阻屏测试

下面分别介绍一下这三个函数。

rtp_test,该函数用于电阻触摸屏的测试,该函数代码比较简单,就是扫描按键和触摸屏,

如果触摸屏有按下,则在触摸屏上面划线,如果按中“RST”区域,则执行清屏。如果按键KEY0

按下,则执行触摸屏校准。

ctp_test,该函数用于电容触摸屏的测试,由于我们采用tp_dev.sta来标记当前按下的触摸

屏点数,所以判断是否有电容触摸屏按下,也就是判断tp_dev.sta的最低5位,如果有数据,

则划线,如果没数据则忽略,且5个点划线的颜色各不一样,方便区分。另外,电容触摸屏不

需要校准,所以没有校准程序。

main函数,则比较简单,初始化相关外设,然后根据触摸屏类型,去选择执行ctp_test还

是rtp_test。

软件部分就介绍到这里,接下来看看下载验证。

32.4下载验证

在代码编译成功之后,我们通过下载代码到ALIENTEK战舰STM32F上,电阻触摸屏

测试如图32.4.1所示界面:

图32.4.1电阻触摸屏测试程序运行效果

图中我们在电阻屏上画了一些内容,右上角的RST可以用来清屏,点击该区域,即可清屏重画。另外,按KEY0可以进入校准模式,如果发现触摸屏不准,则可以按KEY0,进入校准,重新校准一下,即可正常使用。

如果是电容触摸屏,测试界面如图32.4.2所示:

图32.4.2电容触摸屏测试界面

图中,同样输入了一些内容。电容屏支持多点触摸,每个点的颜色都不一样,图中的波浪

线就是三点触摸画出来的,最多可以5点触摸。注意:电容触摸屏支持:ALIENTEK4.3寸电

容触摸屏模块或者ALIENTEK新款7寸电容触摸屏模块(SSD+FT方案),老款的7

寸电容触摸屏模块(CPLD+GT方案)本例程不支持!!

同样,按右上角的RST标志,可以清屏。电容屏无需校准,所以按KEY0无效。KEY0校准仅对电阻屏有效。

1