找回密码
 立即注册
首页 业界区 安全 《ESP32-S3使用指南—IDF版 V1.6》第三十四章 RGB触摸实 ...

《ESP32-S3使用指南—IDF版 V1.6》第三十四章 RGB触摸实验

明思义 2025-9-28 18:03:43
第三十四章 RGB触摸实验
1)实验平台:正点原子DNESP32S3开发板
2)章节摘自【正点原子】ESP32-S3使用指南—IDF版 V1.6
3)购买链接:https://detail.tmall.com/item.htm?&id=768499342659
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子DNESP32S3开发板技术交流群:132780729
1.jpeg

2.png

本章,作者将介绍如何使用ESP32-S3来驱动触摸屏,我们通过外接带触摸屏的LCD模块(比如正点原子RGBLCD模块),来实现触摸屏控制。在本章中,我们将向大家介绍ESP32-S3控制正点原子RGBLCD模块,实现触摸屏驱动(电容触摸),最终实现一个手写板的功能。
本章分为如下几个小节:
34.1 触摸屏简介
34.2 硬件设计
34.3 程序设计
34.4 下载验证
34.1 触摸屏简介
34.1.1 电容式触摸屏
现在几乎所有智能手机,包括平板电脑都是采用电容屏作为触摸屏,电容屏是利用人体感应进行触点检测控制,不需要直接接触或只需要轻微接触,通过检测感应电流来定位触摸坐标。正点原子4.3/7寸TFTLCD模块自带的触摸屏采用的是电容式触摸屏,下面简单介绍下电容式触摸屏的原理。
电容式触摸屏主要分为两种:
1、表面电容式电容触摸屏。
表面电容式触摸屏技术是利用ITO(铟锡氧化物,是一种透明的导电材料)导电膜,通过电场感应方式感测屏幕表面的触摸行为进行。但是表面电容式触摸屏有一些局限性,它只能识别一个手指或者一次触摸。
2、投射式电容触摸屏。
投射电容式触摸屏是传感器利用触摸屏电极发射出静电场线。一般用于投射电容传感技术的电容类型有两种:自我电容和交互电容。
自我电容又称绝对电容,是最广为采用的一种方法,自我电容通常是指扫描电极与地构成的电容。在玻璃表面有用ITO制成的横向与纵向的扫描电极,这些电极和地之间就构成一个电容的两极。当用手或触摸笔触摸的时候就会并联一个电容到电路中去,从而使在该条扫描线上的总体的电容量有所改变。在扫描的时候,控制IC依次扫描纵向和横向电极,并根据扫描前后的电容变化来确定触摸点坐标位置。笔记本电脑触摸输入板就是采用的这种方式,笔记本电脑的输入板采用XY的传感电极阵列形成一个传感格子,当手指靠近触摸输入板时,在手指和传感电极之间产生一个小量电荷。采用特定的运算法则处理来自行、列传感器的信号来确定手指的位置。
交互电容又叫做跨越电容,它是在玻璃表面的横向和纵向的ITO电极的交叉处形成电容。交互电容的扫描方式就是扫描每个交叉处的电容变化,来判定触摸点的位置。当触摸的时候就会影响到相邻电极的耦合,从而改变交叉处的电容量,交互电容的扫面方法可以侦测到每个交叉点的电容值和触摸后电容变化,因而它需要的扫描时间与自我电容的扫描方式相比要长一些,需要扫描检测X
Y根电极。目前智能手机/平板电脑等的触摸屏,都是采用交互电容技术。
正点原子所选择的电容触摸屏,也是采用的是投射式电容屏(交互电容类型),所以后面仅以投射式电容屏作为介绍。
投射式电容触摸屏采用纵横两列电极组成感应矩阵,来感应触摸。以两个交叉的电极矩阵,即:X轴电极和Y轴电极,来检测每一格感应单元的电容变化,如图34.1.1.1所示:
3.jpeg

图34.1.1.1 投射式电容屏电极矩阵示意图
示意图中的电极,实际是透明的,这里是为了方便大家理解。图中,X、Y轴的透明电极电容屏的精度、分辨率与X、Y轴的通道数有关,通道数越多,精度越高。以上就是电容触摸屏的基本原理,接下来看看电容触摸屏的优缺点:
电容触摸屏的优点:手感好、无需校准、支持多点触摸、透光性好。
电容触摸屏的缺点:成本高、精度不高、抗干扰能力差。
这里特别提醒大家电容触摸屏对工作环境的要求是比较高的,在潮湿、多尘、高低温环境下面,都是不适合使用电容屏的。
电容触摸屏一般都需要一个驱动IC来检测电容触摸,正点原子的电容触摸屏使用的是IIC接口输出触摸数据的触摸芯片。正点原子7’TFTLCD模块的电容触摸屏,采用的是15*10的驱动结构(10个感应通道,15个驱动通道),采用的是GT911/FT5206作为驱动IC。正点原子4.3’TFTLCD模块采用的驱动IC是:GT9xxx(GT9147/GT917S/GT911/GT1151/GT9271),不同型号感应通道和驱动通道数量都不一样,详看数据手册,但是这些驱动IC驱动方式都类似,这里我们以GT9147为例给大家做介绍,其他的大家参考着学习即可。
GT9147与MCU通过4根线连接:SDA、SCL、RST和INT。GT9147的IIC地址,可以是0X14或者0X5D,当复位结束后的5ms内,如果INT是高电平,则使用0X14作为地址,否则使用0X5D作为地址,具体的设置过程,请看:GT9147数据手册.pdf这个文档。本章我们使用0X14作为器件地址(不含最低位,换算成读写命令则是读:0X29,写:0X28),接下来,介绍一下GT9147的几个重要的寄存器。
1,控制命令寄存器(0X8040)
该寄存器可以写入不同值,实现不同的控制,我们一般使用0和2这两个值,写入2,即可软复位GT9147。在硬复位之后,一般要往该寄存器写2,实行软复位。然后,写入0,即可正常读取坐标数据(并且会结束软复位)。
2,配置寄存器组(0X8047~0X8100)
这里共186个寄存器,用于配置GT9147的各个参数,这些配置一般由厂家提供给我们(一个数组),所以我们只需要将厂家给我们的配置,写入到这些寄存器里面,即可完成GT9147的配置。由于GT9147可以保存配置信息(可写入内部FLASH,从而不需要每次上电都更新配置),我们有几点注意的地方提醒大家:1,0X8047寄存器用于指示配置文件版本号,程序写入的版本号,必须大于等于GT9147本地保存的版本号,才可以更新配置。2,0X80FF寄存器用于存储校验和,使得0X8047~0X80FF之间所有数据之和为0。3,0X8100用于控制是否将配置保存在本地,写0,则不保存配置,写1则保存配置。
3,产品ID寄存器(0X8140~0X8143)
这里总共由4个寄存器组成,用于保存产品ID,对于GT9147,这4个寄存器读出来就是:9,1,4,7四个字符(ASCII码格式)。因此,我们可以通过这4个寄存器的值,来判断驱动IC的型号,以便执行不同的初始化。
4,状态寄存器(0X814E)
该寄存器各位描述如表表34.1.1.1所示:
4.png

表 34.1.1.1 状态寄存器各位描述
这里,我们仅关心最高位和最低4位,最高位用于表示buffer状态,如果有数据(坐标/按键),buffer就会是1,最低4位用于表示有效触点的个数,范围是:0~5,0,表示没有触摸,5表示有5点触摸。最后,该寄存器在每次读取后,如果bit7有效,则必须写0,清除这个位,否则不会输出下一次数据!!这个要特别注意!!!
5,坐标数据寄存器(共30个)
这里共分成5组(5个点),每组6个寄存器存储数据,以触点1的坐标数据寄存器组为例,如表34.1.1.2所示:
5.png

表34.1.1.2 触点1坐标寄存器组描述
我们一般只用到触点的x,y坐标,所以只需要读取0X81500X8153的数据,组合即可得到触点坐标。其他4组分别是:0X8158、0X8160、0X8168和0X8170等开头的16个寄存器组成,分别针对触点24的坐标。同样GT9147也支持寄存器地址自增,我们只需要发送寄存器组的首地址,然后连续读取即可,GT9147会自动地址自增,从而提高读取速度。
GT9147相关寄存器的介绍就介绍到这里,更详细的资料,请参考:GT9147编程指南.pdf 这个文档。
GT9147只需要经过简单的初始化就可以正常使用了,初始化流程:硬复位à延时10msà结束硬复位à设置IIC地址à延时100msà软复位à更新配置(需要时)à结束软复位。此时GT9147即可正常使用了。然后,我们不停的查询0X814E寄存器,判断是否有有效触点,如果有,则读取坐标数据寄存器,得到触点坐标。特别注意,如果0X814E读到的值最高位为1,就必须对该位写0,否则无法读到下一次坐标数据。
电容式触摸屏部分,就介绍到这里。
34.1.2 触摸控制原理
前面已经简单地介绍了电阻屏和电容屏的原理,并且知道了不同类型的触摸屏其实是屏幕+触摸传感器组成。那么这里就会有两组相互独立的参数:屏幕坐标和触摸坐标。要实现触摸功能,就是要把触摸点和屏幕坐标对应起来。
我们以LCD显示屏为例,我们知道屏幕的扫描方向是可以编程设定的,而触摸点,在触摸传感器安装好后,AD值的变化向方向则是固定的,我们以最常见的屏幕坐标方向:先从左到右,再从上到下扫描为例,此时,屏幕坐标和触点AD的坐标有类似的规律:从坐标原点出发,水平方向屏幕坐标增加时,AD值的X方向也增加;屏幕坐标的Y方向坐标增加,AD值的Y方向也增加;坐标减少时对应的关系也类似,可以用图34.1.2.1的示意图来表示这种关系:
6.png

图34.1.2.1 屏幕坐标和触摸坐标的一种对应关系
这里再来引入两个概念,物理坐标和逻辑坐标。物理坐标指触摸屏上点的实际位置,通常以液晶上点的个数来度量。逻辑坐标指这点被触摸时A/D转换后的坐标值。仍以图34.1.2.1为例,我们假定液晶最左上角为坐标轴原点A,在液晶上任取一点B(实际人手比像素点大得多,一次按下会有多个触点,此处取十字线交叉中心),B在X方向与A相距100个点,在Y方向与A距离200个点,则这点的物理坐标B为(100,200)。如果我们触摸这一点时得到的X向A/D转换值为200,Y向A/D转换值为400,则这点的逻辑坐标B’为(200,400)。
需要特别说明的是,正点原子的电容屏的参数已经在出厂时由厂家调好,所以无需进行校准,而且可以直接读到转换后的触点坐标;对于电阻屏,请大家理解并熟记物理坐标和逻辑坐标逻辑上的对应关系,我们后面编程需要用到。
RGB屏相关内容,可参考正点原子提供的《ATK-MD0430R模块用户手册_V1.0》和《ATK-MD0430R模块使用说明_V1.0》,在这两个手册中,已经详细说明了RGB的工作原理及相关参数信息。
温馨提示:正点原子ATK-MD0430R模块搭载了GT9147电容式触摸屏IC,我们可通过IIC协议读取显示屏的触摸点。
34.2 硬件设计
34.2.1 例程功能
本章实验功能简介:经过一系列的初始化之后,进入电容触摸屏测试程序,用户可在画板上绘画字符、线条等,在测试界面的右上角会有一个清空的操作区域(RST),点击这个地方就会将输入全部清除,恢复白板状态。
34.2.2 硬件资源

  • LED灯
    LED-IO1
  • XL9555
    IIC_SDA-IO41
    IIC_SCL-IO42
  • RGBLCD
    LCD_BL-IO1_3(XL9555)
    LCD_DE-IO4
    LCD_VSYNC-NC
    LCD_HSYNC-NC
    LCD_PCLK-IO5
    LCD_R3-IO45
    LCD_R4-IO48
    LCD_R5-IO47
    LCD_R6-IO21
    LCD_R7-IO14
    LCD_G2-IO10
    LCD_G3-IO9
    LCD_G4-IO46
    LCD_G5-IO3
    LCD_G6-IO8
    LCD_G7-IO18
    LCD_B3-IO17
    LCD_B4-IO16
    LCD_B5-IO15
    LCD_B6-IO7
    LCD_B7-IO6
    34.2.3 原理图
    RGB接口与ESP32-S3的连接关系,如下图所示:
7.png

图34.2.3.1RGB接口与ESP32-S3的连接电路图
34.3 程序设计
34.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:
8.png

图34.3.1.1 RGB触摸屏实验程序流程图
34.3.2 RGB触摸屏函数解析
这一章节除了涉及到GPIO、IIC的API函数,便没有再涉及到其他API函数。因此,有关GPIO和IIC的API函数介绍,请读者回顾此前的第十章与第十九章的内容。接下来,笔者将直接介绍RGB触摸屏的驱动代码。
34.3.3 RGB触摸屏驱动解析
在IDF版例程24_touch中,作者在24_touch\components\BSP路径下新增了一个TOUCH文件夹,分别用于存放gt9xxx.c、gt9xxx.h和touch.c以及touch.h这四个文件。其中,gt9xxx.h和touch.h文件负责声明TOUCH相关的函数和变量,而gt9xxx.c和touch.c文件则实现了TOUCH的驱动代码。下面,我们将详细解析这四个文件的实现内容。
1,gt9xxx.h和touch.h文件
我们希望能方便地调用不同触摸芯片的坐标扫描函数,这里我们定义了一个函数指针(*scan)(uint8_t),我们只要把相应的芯片的初始化函数指针赋值给它,就可以使用这个通用接口方便地调用不同芯片的描述函数得到相应的触点坐标参数。同时,为了方便管理触摸,我们定义一个用于管理触摸信息的结构体类型。在前面的理论介绍时我们已经提到过,触摸芯片正常工作后,能在触摸点采集到本次触摸对应的AD信息,编程时需要用到,所以可以在gt9xxx.h和touch.h中定义下面的结构体:
  1. /* gt9xxx.h文件 */
  2. #defineGT9XXX_INT_GPIO_PIN            GPIO_NUM_40
  3. #defineGT9XXX_IIC_PORT                 I2C_NUM_1
  4. #defineGT9XXX_IIC_SDA                 GPIO_NUM_39
  5. #defineGT9XXX_IIC_CLK                  GPIO_NUM_38
  6. #defineGT9XXX_IIC_FREQ                400000                                 /* IIC FREQ */
  7. #defineGT9XXX_INT                     gpio_get_level(GT9XXX_INT_GPIO_PIN)    /* 中断引脚 */
  8. /* RGB_BL */
  9. #defineCT_RST(x)       do { x ?                              \
  10.                            xl9555_pin_write(CT_RST_IO, 1):  \
  11.                            xl9555_pin_write(CT_RST_IO, 0);  \
  12.                         } while(0)
  13. /* IIC读写命令 */
  14. #defineGT9XXX_CMD_WR                   0X28        /* 写命令 */
  15. #defineGT9XXX_CMD_RD                   0X29        /* 读命令 */
  16. /* GT9XXX 部分寄存器定义  */
  17. #defineGT9XXX_CTRL_REG                0X8040      /*GT9XXX控制寄存器 */
  18. #defineGT9XXX_CFGS_REG                0X8047      /*GT9XXX配置起始地址寄存器 */
  19. #defineGT9XXX_CHECK_REG               0X80FF      /*GT9XXX校验和寄存器 */
  20. #defineGT9XXX_PID_REG                 0X8140      /*GT9XXX产品ID寄存器 */
  21. #defineGT9XXX_GSTID_REG               0X814E      /*GT9XXX当前检测到的触摸情况 */
  22. #defineGT9XXX_TP1_REG                 0X8150      /* 第一个触摸点数据地址 */
  23. #defineGT9XXX_TP2_REG                 0X8158      /* 第二个触摸点数据地址 */
  24. #defineGT9XXX_TP3_REG                 0X8160      /* 第三个触摸点数据地址 */
  25. #defineGT9XXX_TP4_REG                 0X8168      /* 第四个触摸点数据地址 */
  26. #defineGT9XXX_TP5_REG                 0X8170      /* 第五个触摸点数据地址 */
  27. #defineGT9XXX_TP6_REG                 0X8178      /* 第六个触摸点数据地址 */
  28. #defineGT9XXX_TP7_REG                 0X8180      /* 第七个触摸点数据地址 */
  29. #defineGT9XXX_TP8_REG                 0X8188      /* 第八个触摸点数据地址 */
  30. #defineGT9XXX_TP9_REG                 0X8190      /* 第九个触摸点数据地址 */
  31. #defineGT9XXX_TP10_REG                0X8198      /* 第十个触摸点数据地址 */
  32. /********************************touch.h文件 *********************************/
  33. #defineTP_PRES_DOWN    0x8000  /* 触屏被按下 */
  34. #defineTP_CATH_PRES    0x4000  /* 有按键按下了 */
  35. #defineCT_MAX_TOUCH    10      /* 电容屏支持的点数,固定为5点 */
  36. /* 触摸屏控制器 */
  37. typedef struct
  38. {
  39.     uint8_t (*init)(void);      /* 初始化触摸屏控制器 */
  40.     uint8_t (*scan)(uint8_t);   /* 扫描触摸屏.0,屏幕扫描;1,物理坐标; */
  41.     uint16_t x[CT_MAX_TOUCH];   /* 当前坐标 */
  42.     uint16_t y[CT_MAX_TOUCH];   /* 电容屏有最多10组坐标,电阻屏则用x[0],y[0]代表:此次     扫描时,触屏的坐标,用
  43.                                  * x[9],y[9]存储第一次按下时的坐标.
  44.                                  */
  45.     uint16_t sta;               /* 笔的状态
  46.                                  * b15:按下1/松开0;
  47.                                  * b14:0,没有按键按下;1,有按键按下.
  48.                                  * b13~b10:保留
  49.                                  * b9~b0:电容触摸屏按下的点数(0,表示未按下,1表示按下)
  50.                                  */
  51.     /* 5点校准触摸屏校准参数(电容屏不需要校准) */
  52.     float xfac;                 /* 5点校准法x方向比例因子 */
  53.     float yfac;                 /* 5点校准法y方向比例因子 */
  54.     short xc;                   /* 中心X坐标物理值(AD值) */
  55.     short yc;                   /* 中心Y坐标物理值(AD值) */
  56.     /* 新增的参数,当触摸屏的左右上下完全颠倒时需要用到.
  57.      * b0:0, 竖屏(适合左右为X坐标,上下为Y坐标的TP)
  58.      *   1, 横屏(适合左右为Y坐标,上下为X坐标的TP)
  59.      * b1~6: 保留.
  60.      * b7:0, 电阻屏
  61.      *   1, 电容屏
  62.      */
  63.     uint8_t touchtype;
  64. }_m_tp_dev;
  65. extern_m_tp_dev tp_dev;   /* 触屏控制器在touch.c里面定义 */
复制代码
在上述代码中,用于保存一些RGB触摸屏重要参数信息,比如IIC命令和GT9XXX 部分寄存器地址的宏定义以及触摸屏校准参数等。
2,gt9xxx.c和touch.c文件
电容触摸芯片我们使用的是IIC接口的触摸IC。IIC接口部分代码,我们可以参考 iic.c和iic.h的代码,这里部分参考IIC章节的知识就可以了,这里不重复介绍。
9.png

图40.3.3.2 正点原子 LCD上的GT9XX触摸芯片通讯接口
gt9xxx_init的实现也比较简单,实现CT_INT引脚初始化,调用其IIC初始化接口即可。
同样地,我们需要通过IIC来读取触摸点的物理坐标,由于电容屏在设计时是根据屏幕进行参数设计的,参数已经保存在gt9xxx芯片的内部了,我们只需要按手册推荐的IIC时序把对应的XY坐标读出来,转换成LCD的像素坐标即可。gt9xx系列可以通过中断或轮询方式读限,我们使用的是轮询方式:
1,按第二节时序,先读取寄存器0x814E,若当前buffer(buffer status为1)数据准备好,则依据手指个数读、按键状态取相应个数的坐标、按键信息。
2,若在1中发现buffer数据(buffer status为0)未准备好,则等待1ms再进行读取。这样,gt9xxx_scan()函数的实现如下:
[code]/* GT9XXX 10个触摸点(最多) 对应的寄存器表 */const uint16_tGT9XXX_TPX_TBL[10] ={    GT9XXX_TP1_REG,    GT9XXX_TP2_REG,    GT9XXX_TP3_REG,    GT9XXX_TP4_REG,    GT9XXX_TP5_REG,    GT9XXX_TP6_REG,    GT9XXX_TP7_REG,    GT9XXX_TP8_REG,    GT9XXX_TP9_REG,    GT9XXX_TP10_REG,};/*** @brief      扫描触摸屏(采用查询方式)* @param      mode : 电容屏未用到次参数, 为了兼容电阻屏* @retval     当前触屏状态* @arg        0, 触屏无触摸;* @arg        1, 触屏有触摸;*/uint8_tgt9xxx_scan(uint8_t mode){    uint8_t buf[4];    uint8_t i = 0;    uint8_t res = 0;    uint16_t temp;    uint16_t tempsta;    static uint8_t t = 0;   /* 控制查询间隔,从而降低CPU占用率 */t++;/* 空闲时,每进入10次CTP_Scan函数才检测1次,从而节省CPU使用率 */    if ((t % 10) == 0 || t < 10)                                           {        gt9xxx_rd_reg(GT9XXX_GSTID_REG, &mode, 1); /* 读取触摸点的状态 */        if ((mode & 0X80) && ((mode & 0XF)

相关推荐

您需要登录后才可以回帖 登录 | 立即注册