用户名 立即注册 找回密码

微雪课堂

搜索
微雪课堂 STM32 STM32CubeMX系列教程 查看内容

STM32CubeMX系列教程23:LCD触摸控制

2016-5-23 16:39| 发布者: waveshare-admin| 查看: 48734| 评论: 3

摘要: 本章讲解微雪7inch Capacitive Touch LCD (F)屏幕的触摸控制。
一、触摸芯片简介
      7inch Capacitive Touch LCD (F)  是电容触摸屏,触控芯片是GT811,如下为GT811的中文数据手册。


GT811可同时识别5个触摸点位的实时位置,移动轨迹及触摸面积。其管脚定义如下。


参考应用电路如下图,实际上我们在使用的时候只需关心四个引脚即可。I2C_SDA,I2C_SCL为I2C通信引脚,/RSTB为系统复位引脚,INT为中断信号引脚,但有触摸时,INT输出触发信号,如果MCU对应的管脚开启外部中断则会触发MCU进入外部中断。


二、GT811控制方式

GT811提供标准的I2C通信接口,由SCL和SDA与MCU进行通信,其最高通信速度为600K bps。
GT811 的从设备地址有三组可选,以方便主控调配。三组地址分别为:0xBA/0xBB、 0x6E/0x6F 和 0x28/0x29。即:0xBA——对 GT811 进行写操作;0xBB——对 GT811 进行读操作。

上图为主 CPU 对 GT811 进行的写操作流程图。首先主 CPU 产生一个起始信号, 然后发送地址信息及读写位信息“0”表示写操作:0XBA。 在收到应答后,主 CPU 发送寄存器的 16 位地址,随后是 8 位要写入到寄存器的 数据内容。 GT811 寄存器的地址指针会在写操作后自动加 1,所以当主 CPU 需要对连续地 址的寄存器进行写操作时,可以在一次写操作中连续写入。写操作完成,主 CPU 发送停止信号结束当前写操作。


上图为主 CPU 对 GT811 进行的读操作流程图。首先主 CPU 产生一个起始信号, 然后发送设备地址信息及读写位信息“0”表示写操作:0XAA。 在收到应答后,主 CPU 发送首寄存器的 16 位地址信息,设置要读取的寄存器地 址。在收到应答后,主 CPU 重新发送一次起始信号,发送读操作:0XAB。收到 应答后,主 CPU 开始读取数据。 GT811 同样支持连续的读操作,默认为连续读取数据。主 CPU 在每收到一个 Byte 数据后需发送一个应答信号表示成功接收。在接收到所需的最后一个 Byte 数据 后,主 CPU 发送“非应答信号 NACK”,然后再发送停止信号结束通讯。

GT811有两组寄存器,一组为配置&功能设置寄存器,在初始化的时候配置。触摸屏配置参数由制造商提供。我们只需了解下面这个四个寄存器即可,此处为设置显示屏的分辨率。


另一组为输出信息寄存器,读取这组寄存器既可以判断当前屏幕的触摸状态。TouchpointFlag寄存器存储当前触摸的点数,tp0~tp4位触点状态标识为,当tp0置1时,即表示有触点0按下。
GT811最多支持5个触点,若刚开始一次由三个触点按下,tp0,tp1,tp2均置1,表示有三个触点。若此时第二个触点释放,则tp1清零,只有tp0,tp2为1。当再次有触点按下时,则为tp1置1,最新按下的是触点2,而不是触点3和触点4。


三、新建工程

    本章在前面显示字符个工程上修改,复制刚才的的工程修改文件夹名。打开Cube工程更加原理图重新配置。PD7设置为中断输入,本章采用模拟I2C,PD12,PD13设置为GPIO输出模式,PD11输出GPIO输出。并设置用户标签。


开启外部中断。


生成报告以及初始化代码,编译程序。若程序没有出错,下载下面的应用程序解压放在BSP文件里面并添加进工程中。

BSP.zip             


其中 TS_I2C 为模拟 I2C 驱动程序,下面为读写寄存器操作函数。

01/*******************************************************************************
02* Function Name  : I2C_WR_Reg
03* Description    : Writes to the selected register.
04* Input          : - reg: address of the selected register.
05*                  - buf: Need to write the BUF pointer.
06*                  - len: The length of the array
07* Output         : None
08* Return         : ret
09                   -0  succeed
10                                     -1  error
11* Attention         : None
12*******************************************************************************/
13uint8_t I2C_WriteReg(uint8_t I2c_Addr,uint16_t reg,uint8_t *buf,uint8_t len)
14{
15    uint8_t i;
16    uint8_t ret=0;
17    I2C_Start();  
18  
19    I2C_Send_Byte(I2c_Addr);   //Slaver Addr
20    I2C_Wait_Ack();
21  
22#ifdef I2C_MEMADD_16BIT
23    I2C_Send_Byte(reg>>8);          //Data Addr high
24    I2C_Wait_Ack();
25#endif
26      
27    I2C_Send_Byte(reg&0xFF);        //Data Addr low
28    I2C_Wait_Ack();  
29  
30    for(i=0;i<len;i++)
31    {     
32        I2C_Send_Byte(buf[i]); 
33        ret=I2C_Wait_Ack();
34        if(ret)break
35    }
36    I2C_Stop();               
37    return ret;
38}
39                                                     
40/*******************************************************************************
41* Function Name  : i2C_RD_Reg
42* Description    : Writes to the selected register.
43* Input          : - reg: address of the selected register.
44*                  - buf: Need to read the BUF pointer.
45*                  - len: The length of the array
46* Output         : None
47* Return         : None
48* Attention         : None
49*******************************************************************************/         
50void I2C_ReadReg(uint8_t I2c_Addr,uint16_t reg,uint8_t *buf,uint8_t len)
51{
52    uint8_t i;
53    I2C_Start();  
54    I2C_Send_Byte(I2c_Addr); 
55    I2C_Wait_Ack();
56      
57#ifdef I2C_MEMADD_16BIT
58    I2C_Send_Byte(reg>>8);          //Data Addr high
59    I2C_Wait_Ack();
60#endif
61      
62    I2C_Send_Byte(reg&0xFF);        //Data Addr low
63    I2C_Wait_Ack();                                                       
64    I2C_Stop();
65  
66    I2C_Start();           
67    I2C_Send_Byte(I2c_Addr+1);    
68    I2C_Wait_Ack();   
69  
70    for(i=0;i<len;i++)
71    {     
72        buf[i]=I2C_Read_Byte(i==(len-1)?0:1);
73    }
74    I2C_Stop();  
75}


GT811.c为触摸芯片的驱动文件,下面简单介绍一下初始化函数和读取触摸状态函数。程序开始先拉低复位管脚复位芯片,注意如果延时时间过短则会导致复位不成功。读取GT811的ID值判断通信是否正常。设置屏幕分辨率并将配置参数写入到配置&功能寄存器组中。

01/**
02  * @brief  Initialize the GT811 communication bus
03  *         from MCU to GT811 : ie I2C channel initialization (if required).
04  * @retval None
05  */
06  
07uint8_t GT811_Init(void)
08
09    I2C_Init();
10  
11    /* reset GT811 */
12    HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin, GPIO_PIN_RESET);
13    HAL_Delay(200);
14    HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin, GPIO_PIN_SET);
15    HAL_Delay(200);
16  
17    /* if Version is correct, send the configuration parameters */
18    if(GT811_ReadID() == GT811_VERSION_VALUE)
19    {
20        /* touch screen configuration parameter (touch screen manufacturers provide) */
21        uint8_t GTP_CFG_DATA[]=
22        {
23            0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0x05,0x55,0x15,0x55,0x25,0x55,0x35,0x55,0x45,0x55,
24            0x55,0x55,0x65,0x55,0x75,0x55,0x85,0x55,0x95,0x55,0xA5,0x55,0xB5,0x55,0xC5,0x55,0xD5,0x55,0xE5,0x55,
25            0xF5,0x55,0x1B,0x03,0x00,0x00,0x00,0x13,0x13,0x13,0x0F,0x0F,0x0A,0x50,0x30,0x05,0x03,0x64,0x05,0xe0,
26            0x01,0x20,0x03,0x00,0x00,0x32,0x2C,0x34,0x2E,0x00,0x00,0x04,0x14,0x22,0x04,0x00,0x00,0x00,0x00,0x00,
27            0x20,0x14,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x30,0x25,0x28,0x14,0x00,
28            0x00,0x00,0x00,0x00,0x00,0x01,
29        };
30  
31        /* config  */
32        GTP_CFG_DATA[62] = GT811_MAX_WIDTH >> 8; 
33        GTP_CFG_DATA[61] = GT811_MAX_WIDTH & 0xff; 
34        GTP_CFG_DATA[60] = GT811_MAX_HEIGHT >> 8; 
35        GTP_CFG_DATA[59] = GT811_MAX_HEIGHT & 0xff;
36  
37        I2C_WriteReg(GT811_CMD_WR,GT811_CONFIG_REG,(uint8_t *)GTP_CFG_DATA,sizeof(GTP_CFG_DATA));
38    }
39    return HAL_OK;
40}


如下为读触摸状态函数,先通过I2C读去输出信息寄存器,判断TouchpointFlag寄存器的tp0~tp4是否置1,即是否有触摸,若有则将寄存器的值转为坐标值,存储在TS_StateTypeDef 结构体的指针内存中。

01void GT811_GetState(TS_StateTypeDef *TS_State)
02{
03    uint8_t RegBuf[34];
04  
05    /* Read touch message */
06    I2C_ReadReg(GT811_CMD_WR,GT811_READ_XY_REG,RegBuf,sizeof(RegBuf));
07  
08    /* get touch massage */
09    TS_State->SensorId = RegBuf[0x00] >> 6;
10    TS_State->touchDetected = RegBuf[0x00] & 0x1F;
11  
12    if(TS_State->touchDetected != 0)
13    
14        //Touch point 1 coordinates
15        TS_State->touchY[0] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x02] << 8) + RegBuf[0x03]);
16        TS_State->touchX[0] = (((uint16_t)RegBuf[0x04] << 8) + RegBuf[0x05]);
17        TS_State->touchWeight[0] = RegBuf[0x06]; 
18  
19        //Touch point 2 coordinates
20        TS_State->touchY[1] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x07] << 8) + RegBuf[0x08]);
21        TS_State->touchX[1] = (((uint16_t)RegBuf[0x09] << 8) + RegBuf[0x0A]);
22        TS_State->touchWeight[1] = RegBuf[0x0B]; 
23  
24        //Touch point 3 coordinates
25        TS_State->touchY[2] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x0C] << 8) + RegBuf[0x0D]);
26        TS_State->touchX[2] = (((uint16_t)RegBuf[0x0E] << 8) + RegBuf[0x0F]);
27        TS_State->touchWeight[2] = RegBuf[0x10]; 
28  
29        //Touch point 4 coordinates
30        TS_State->touchY[3] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x11] << 8) + RegBuf[0x18]);
31        TS_State->touchX[3] = (((uint16_t)RegBuf[0x19] << 8) + RegBuf[0x1A]);
32        TS_State->touchWeight[3] = RegBuf[0x1B]; 
33  
34        //Touch point 5 coordinates
35        TS_State->touchY[4] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x1C] << 8) + RegBuf[0x1D]);
36        TS_State->touchX[4] = (((uint16_t)RegBuf[0x1E] << 8) + RegBuf[0x1F]);
37        TS_State->touchWeight[4] = RegBuf[0x20];
38    }
39}


TS_StateTypeDef结构体在GT811.h中定义。

1typedef struct
2{
3    uint8_t  touchDetected;                /*!< Total number of active touches detected at last scan */
4    uint16_t touchX[TS_MAX_NB_TOUCH];      /*!< Touch X[0], X[1] coordinates on 12 bits */
5    uint16_t touchY[TS_MAX_NB_TOUCH];      /*!< Touch Y[0], Y[1] coordinates on 12 bits */
6    uint8_t  touchWeight[TS_MAX_NB_TOUCH]; /*!< Touch_Weight[0], Touch_Weight[1] : weight property of touches */
7    uint32_t SensorId; /*!< type of gesture detected : take value of type @ref TS_GestureIdTypeDef */
8} TS_StateTypeDef;


删除原来的应用代码,在main文件中添加头文件。

1/* USER CODE BEGIN Includes */
2#include "stm32746g_sdram.h"
3#include "stm32746g_LCD.h"
4#include "GT811.h"
5/* USER CODE END Includes */


声明变量,其中TS_State为当前触摸状态,TS_BKState为上一次触摸状态。TS_flag为触摸标志,TouchPoit存储触点数。PointColor存储各个触点的显示颜色。

01/* USER CODE BEGIN PV */
02/* Private variables ---------------------------------------------------------*/
03TS_StateTypeDef  TS_State={0};
04uint8_t TS_flag ;
05uint8_t TouchPoit;
06TS_StateTypeDef  TS_BKState;
07uint8_t value = 0;
08uint16_t i;
09uint32_t PointColor[]={LCD_COLOR_BLUE,LCD_COLOR_GREEN,LCD_COLOR_RED,LCD_COLOR_MAGENTA,LCD_COLOR_YELLOW};
10/* USER CODE END PV */



在while循环中添加如下应用程序,程序首先判断触摸标志,如果有触摸,则读取触摸状态。循环中分为三分部,第一部分即清楚上次显示的内容,即将显示内容设为背景色黑色覆盖。第二部分在对应触摸的位置显示一个点和水平垂直量两条先。第三部分就这次的触摸状态存储到备份状态结构体中,以便下一次擦除。

01/* USER CODE BEGIN WHILE */
02while (1)
03{
04/* USER CODE END WHILE */
05  
06/* USER CODE BEGIN 3 */
07    if(TS_flag == 1)
08    {
09        GT811_GetState(&TS_State);
10        if(TS_State.touchDetected != 0)
11        {
12            TouchPoit = TS_BKState.touchDetected;
13            for(i = 0;i < 5;i++)
14            {
15                if(TouchPoit & 0x01)
16                {
17                    BSP_LCD_SetTextColor(LCD_COLOR_BLACK);
18                    BSP_LCD_FillCircle(TS_BKState.touchX[i],TS_BKState.touchY[i],20);
19                    BSP_LCD_DrawVLine(TS_BKState.touchX[i], 55, 580);
20                    BSP_LCD_DrawHLine(5, TS_BKState.touchY[i], 1004);
21                }
22                TouchPoit >>= 1;
23            }
24              
25            TouchPoit = TS_State.touchDetected;
26            for(i = 0;i < 5;i++)
27            {
28                if(TouchPoit & 0x01)
29                {
30                    if(TS_State.touchY[i] <  75)TS_State.touchY[i] =  75;
31                    if(TS_State.touchY[i] > 580)TS_State.touchY[i] = 580;
32                    if(TS_State.touchX[i] <  20)TS_State.touchX[i] =  20;
33                    if(TS_State.touchX[i] > 1004)TS_State.touchX[i] = 1004;
34  
35                    BSP_LCD_SetTextColor(PointColor[i]);
36                    BSP_LCD_FillCircle(TS_State.touchX[i],TS_State.touchY[i],20);
37                    BSP_LCD_DrawVLine(TS_State.touchX[i], 55, 580);
38                    BSP_LCD_DrawHLine(5, TS_State.touchY[i], 1004);
39                    TS_BKState.touchX[i] = TS_State.touchX[i];
40                    TS_BKState.touchY[i] = TS_State.touchY[i];
41                }
42                TouchPoit >>= 1;
43            }
44            TS_BKState.touchDetected = TS_State.touchDetected;
45        }
46        TS_flag = 0;
47    }
48}
49/* USER CODE END 3 */


在main文件后面添加外部中断回调函数,当屏幕有触摸是触发中断,触摸标志位置1。

01/* USER CODE BEGIN 4 */
02/**
03  * @}
04  */
05void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
06{
07    if(
08GPIO_Pin == GPIO_PIN_7)
09    {
10        TS_flag = 1;
11    }
12}
13/* USER CODE END 4 */


编译程序下载到开发板中,触摸屏幕会显示触点。(以下为五点触控效果的显示)


523

顶一下

刚表态过的朋友 (523 人)

发表评论

最新评论

引用 hwgahwg 2020-7-26 15:15
学到了学到了
引用 游客 2019-5-17 12:43
实测F429IGT6,7寸GT911电容屏的例程  
修改了0x8065-0x806A的驱动频率,解决了单点触摸时,按住会快速连点的问题
uint8_t s_GT911_CfgParams[]=
{
0x00,0x20,0x03,0xE0,0x01,0x01,0x0C,0x00,0x02,0x08,
0X28,0X0C,0X50,0X32,0x03,0x05,0x00,0x00,0x00,0x00,
0x00,0x00,0x04,0x18,0x1A,0x1E,0x14,0x8B,0x2B,0x0E,
0x33,0x35,0x0C,0x08,0x00,0x00,0x00,0x01,0x02,0x1D,//frequency is not paired
0x00,0x01,0x00,0x00,0x00,0x03,0x64,0x32,0x00,0x00,
0x00,0x50,0xA0,0x94,0xD5,0x02,0x07,0x00,0x00,0x00,
0x9D,0x55,0x00,0x8D,0x62,0x00,0 ...
引用 Ezio_神仙醋 2017-1-19 15:07
学习了

查看全部评论(3)

微雪官网|产品资料|手机版|小黑屋|微雪课堂. ( 粤ICP备05067009号 )

GMT+8, 2025-4-2 13:25 , Processed in 0.045958 second(s), 26 queries .

返回顶部