使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911)

article/2025/8/23 3:14:36

使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911)

初始化代码

/** @brief  GT911 初始化程序* @param  None* @retval None*/
void GT911_init()
{Dev_Now.GT911_RST=0;GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Pin = GT911_RST_PIN | GT911_INT_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;HAL_GPIO_Init(GT911_RST_PORT, &GPIO_InitStruct);HAL_GPIO_WritePin(GT911_RST_PORT,GT911_RST_PIN,GPIO_PIN_RESET);    HAL_Delay(1000);HAL_GPIO_WritePin(GT911_INT_PORT,GT911_INT_PIN,GPIO_PIN_RESET);    HAL_Delay(1000);HAL_GPIO_WritePin(GT911_RST_PORT,GT911_RST_PIN,GPIO_PIN_SET);    HAL_Delay(2000);GPIO_InitStruct.Pin = GT911_INT_PIN;GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GT911_INT_PORT, &GPIO_InitStruct);HAL_Delay(100);Dev_Now.GT911_RST=1;
}

主要数据读取代码:

regNum为读取的数据个数,如果只是读取1个点的触摸,改成9就可以。

#define regNum	41	//读取寄存器字节数
void GT911_Scan(void)
{uint8_t Clearbuf = 0;uint8_t i = 0;if (Dev_Now.Touch == 1){Dev_Now.Touch = 0;if(GTDMASendOK_F)	//判断DMA是否发送完成{GTDMASendOK_F = 0;if(HAL_I2C_Mem_Read_DMA(&hi2c1, CT_CMD_WR, GT911_READ_XY_REG, I2C_MEMADD_SIZE_16BIT, DMAbuf, regNum)) //IIC读取regNum个字节数据{IICReset();	//异常则重启IIC总线return;}}else{if(HAL_I2C_Mem_Write_DMA(&hi2c1, CT_CMD_WR, GT911_READ_XY_REG, I2C_MEMADD_SIZE_16BIT, &Clearbuf, 1))	//写入读取完成通知从设备{IICReset();	//异常则重启IIC总线return;}}}if(GTDMAReadOK_F)	//判断DMA是否接收完成{GTDMAReadOK_F = 0;if ((GT911buf[0]&0x80) == 0x00)	//坐标是否(或按键)已经准备好{if(HAL_I2C_Mem_Write_DMA(&hi2c1, CT_CMD_WR, GT911_READ_XY_REG, I2C_MEMADD_SIZE_16BIT, &Clearbuf, 1))//写入读取完成通知从设备{IICReset();	//异常则重启IIC总线return;}}else{Dev_Now.TouchpointFlag = GT911buf[0];Dev_Now.TouchCount = GT911buf[0]&0x0f;if(HAL_I2C_Mem_Write_DMA(&hi2c1, CT_CMD_WR, GT911_READ_XY_REG, I2C_MEMADD_SIZE_16BIT, &Clearbuf, 1))//写入读取完成通知从设备{IICReset();	//异常则重启IIC总线return;}Dev_Now.Touchkeytrackid[0] = GT911buf[1];		//第一个触摸点的坐标Dev_Now.X[0] = ((uint16_t)GT911buf[3] << 8) + GT911buf[2];Dev_Now.Y[0] = ((uint16_t)GT911buf[5] << 8) + GT911buf[4];Dev_Now.S[0] = ((uint16_t)GT911buf[7] << 8) + GT911buf[6];Dev_Now.Touchkeytrackid[1] = GT911buf[9];		//第二个触摸点的坐标Dev_Now.X[1] = ((uint16_t)GT911buf[11] << 8) + GT911buf[10];Dev_Now.Y[1] = ((uint16_t)GT911buf[13] << 8) + GT911buf[12];Dev_Now.S[1] = ((uint16_t)GT911buf[15] << 8) + GT911buf[14];Dev_Now.Touchkeytrackid[2] = GT911buf[17];		//第三个触摸点的坐标Dev_Now.X[2] = ((uint16_t)GT911buf[19] << 8) + GT911buf[18];Dev_Now.Y[2] = ((uint16_t)GT911buf[21] << 8) + GT911buf[20];Dev_Now.S[2] = ((uint16_t)GT911buf[23] << 8) + GT911buf[22];Dev_Now.Touchkeytrackid[3] = GT911buf[25];		//第四个触摸点的坐标Dev_Now.X[3] = ((uint16_t)GT911buf[27] << 8) + GT911buf[26];Dev_Now.Y[3] = ((uint16_t)GT911buf[29] << 8) + GT911buf[28];Dev_Now.S[3] = ((uint16_t)GT911buf[31] << 8) + GT911buf[30];Dev_Now.Touchkeytrackid[4] = GT911buf[33];		//第五个触摸点的坐标Dev_Now.X[4] = ((uint16_t)GT911buf[35] << 8) + GT911buf[34];Dev_Now.Y[4] = ((uint16_t)GT911buf[37] << 8) + GT911buf[36];Dev_Now.S[4] = ((uint16_t)GT911buf[39] << 8) + GT911buf[38];for (i = 0; i< Dev_Backup.TouchCount;i++)	//检查触摸点的坐标边界{if(Dev_Now.Y[i]<20)Dev_Now.Y[i]=20;if(Dev_Now.Y[i]>GT911_MAX_HEIGHT-20)Dev_Now.Y[i]=GT911_MAX_HEIGHT-20;if(Dev_Now.X[i]<20)Dev_Now.X[i]=20;if(Dev_Now.X[i]>GT911_MAX_WIDTH-20)Dev_Now.X[i]=GT911_MAX_WIDTH-20;}for (i=0;i<Dev_Now.TouchCount;i++){if(Dev_Now.Y[i]<20)Dev_Now.Y[i]=20;if(Dev_Now.Y[i]>GT911_MAX_HEIGHT-20)Dev_Now.Y[i]=GT911_MAX_HEIGHT-20;if(Dev_Now.X[i]<20)Dev_Now.X[i]=20;if(Dev_Now.X[i]>GT911_MAX_WIDTH-20)Dev_Now.X[i]=GT911_MAX_WIDTH-20;Dev_Backup.X[i] = Dev_Now.X[i];Dev_Backup.Y[i] = Dev_Now.Y[i];Dev_Backup.TouchCount = Dev_Now.TouchCount;}}}
}

错误复位代码

主要解决IIC偶尔出现死锁的问题,IICError 变量记录死锁的次数,移植的时候这个变量如果一直增加,说明时序出现了问题。

/** @brief  IIC引脚复位程序* @param  None* @retval None*/
static void i2c_hw_reset(void) {GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7 | GPIO_PIN_8, GPIO_PIN_SET);if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_RESET ||HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET) {//HAL_Delay(10);}GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);hi2c1.Instance->CR1 |= I2C_CR1_SWRST;hi2c1.Instance->CR1 &= ~I2C_CR1_SWRST;HAL_I2C_DeInit(&hi2c1);        //释放IO口为GPIO,复位句柄状态HAL_I2C_Init(&hi2c1);          //这句重新初始化I2C控制
}/** @brief  IIC复位程序* @param  None* @retval None*/
void IICReset(void)
{SET_BIT(hi2c1.Instance->CR1, I2C_CR1_STOP);	//发送一个停止位hi2c1.State = HAL_I2C_STATE_READY;			//改变IIC状态为准备状态hi2c1.Mode = HAL_I2C_MODE_NONE;				//标准模式i2c_hw_reset();								//复位IIC总线IICError ++;								//错误次数计数
}

DMA中断代码

DMA数据发送/接收中断处理

/*** @brief This function handles DMA1 stream0 global interrupt.*/
void DMA1_Stream0_IRQHandler(void)
{/* USER CODE BEGIN DMA1_Stream0_IRQn 0 */if(__HAL_DMA_GET_TC_FLAG_INDEX(&hdma_i2c1_rx))	//DMA传输完成判断{GTDMAReadOK_F = 1;memcpy(GT911buf, DMAbuf, sizeof(DMAbuf));}/* USER CODE END DMA1_Stream0_IRQn 0 */HAL_DMA_IRQHandler(&hdma_i2c1_rx);/* USER CODE BEGIN DMA1_Stream0_IRQn 1 *//* USER CODE END DMA1_Stream0_IRQn 1 */
}/*** @brief This function handles DMA1 stream6 global interrupt.*/
void DMA1_Stream6_IRQHandler(void)
{/* USER CODE BEGIN DMA1_Stream6_IRQn 0 */if(__HAL_DMA_GET_TC_FLAG_INDEX(&hdma_i2c1_tx))	//DMA传输完成判断{GTDMASendOK_F = 1;}/* USER CODE END DMA1_Stream6_IRQn 0 */HAL_DMA_IRQHandler(&hdma_i2c1_tx);/* USER CODE BEGIN DMA1_Stream6_IRQn 1 *//* USER CODE END DMA1_Stream6_IRQn 1 */
}

GT911数据准备完成中断

GT911数据准备完成后,会产生一个外部中断

/*** @brief This function handles EXTI line[9:5] interrupts.*/
void EXTI9_5_IRQHandler(void)
{/* USER CODE BEGIN EXTI9_5_IRQn 0 */if(Dev_Now.GT911_RST){Dev_Now.Touch =1;}/* USER CODE END EXTI9_5_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);/* USER CODE BEGIN EXTI9_5_IRQn 1 *//* USER CODE END EXTI9_5_IRQn 1 */
}

基于系统时钟1ms扫描一次

/*** @brief This function handles System tick timer.*/
void SysTick_Handler(void)
{/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_IncTick();/* USER CODE BEGIN SysTick_IRQn 1 */GT911_Scan();	//1ms扫描一次/* USER CODE END SysTick_IRQn 1 */
}

结果

单点触摸的数据如下:
在这里插入图片描述
多点触摸的数据如下:

在这里插入图片描述

最后附上Github地址

github地址:https://github.com/oy2n/stm32cube-gt911-dma.git


http://chatgpt.dhexx.cn/article/pQSXFYXU.shtml

相关文章

v3S驱动gt911触摸

文章目录 一、修改设备树二、编写驱动三、运行测试四、编译进内核1. 拷贝文件2. 修改对应的 Makefile3. 编译运行4.测试1.注释掉坐标信息 五、移植tslib1. buildroot配置tslib2. 配置tslib3. 测试 一、修改设备树 在sun8i-v3s-licheepi-zero-dock.dts中添加pio节点&#xff08…

gt911多点触摸实验

文章目录 一、设备树二、驱动程序三、测试四、编译进内核1. 拷贝文件2. 修改对应的 Makefile3. 编译运行4.测试 一、设备树 记得注释掉共用的引脚&#xff08;有好几处&#xff09; 在pinctrl_tsc节点下添加&#xff1a; pinctrl_tsc: tscgrp {fsl,pins <MX6UL_PAD_GPIO1_…

野火STM32F103驱动GT911触摸芯片

GT911触摸芯片 芯片介绍 GT911 是专为 7”~8”设计的新一代 5 点电容触控方案&#xff0c;拥有 26 个驱动通道和 14 个感 应通道&#xff0c;以满足更高的 touch 精度要求。 GT911 可同时识别 5 个触摸点位的实时准确位置&#xff0c;移动轨迹及触摸面积。并可根据主控需要&…

电容触摸屏控制芯片GT911

1.接口说明 GT9 非单层多点系列&#xff08;以下简称 GT9 系列&#xff09; 与主机接口共有 6 PIN&#xff0c;分别为&#xff1a; VDD、 GND、 SCL、SDA、 INT、 RESET。 主控的 INT 口线需具有上升沿或下降沿中断触发功能&#xff0c;并且当其在输入态时&#xff0c; 主控端必…

电容触摸屏GT911、GT928、GT9147的使用

一、介绍与硬件连接 GT911、GT928、GT9147都属于GT9系列非单层多点触控芯片&#xff0c;他们支持的触控点数不同&#xff08;GT928支持10个点、GT911支持5个点&#xff09;、驱动和感应通道也可能不同。可是他们的寄存器和IIC通讯时序是相同的&#xff0c;也就是说驱动程序是兼…

29-2-电容触摸屏控制芯片GT911

1.接口说明 GT9 非单层多点系列&#xff08;以下简称 GT9 系列&#xff09; 与主机接口共有 6 PIN&#xff0c;分别为&#xff1a; VDD、 GND、 SCL、SDA、 INT、 RESET。 主控的 INT 口线需具有上升沿或下降沿中断触发功能&#xff0c;并且当其在输入态时&#xff0c; 主控端…

hal编程 gt911 触摸芯片驱动 ( 枚举 结构体 熟用)( 安富莱 f429 4.3寸电容屏 )

使用板子类型以及屏幕类型 本文使用的是安富莱的板子stm32f429, 屏幕是TR433C1的4.3寸TFT显示屏, 480*272 RGB接口, 电容触摸 . I2C I2C简介、原理、时序请看这篇文章 使用cubemx工具的stm32用AT24C02实现简单密码(一点点面向对象的思想编程) gt911 gt911简介 gt911是深圳市…

python 倒计时手机app打卡_python 实现倒计时功能(gui界面)

运行效果&#xff1a; 完整源码&#xff1a; ##import library from tkinter import * import time from playsound import playsound ## display window root tk() root.geometry(400x300) root.resizable(0,0) root.config(bg blanched almond) root.title(techvidvan - cou…

桌面美化 Python tkinter倒计时工具

桌面美化 Python tkinter倒计时工具 效果一、壁纸设计二、倒计时小工具实现1.引入库2.倒计时函数3.绘制UI载入数据以及创建窗口创建Label控件控件布局绘制分割线绘制子窗口&#xff0c;用于修改倒计时目标其它设置 完整代码打包并开机自启动打包成EXE开机自启动 效果 使用tkin…

Python 内置模块tkinter —— 秒表计时器

# 秒表计时器""" 思考&#xff1a;1、怎么创建一个最简单的窗口&#xff1f;2、怎么保持窗口一直运行&#xff1f;3、不用方法mainloop&#xff08;&#xff09;怎么实现窗口一直运行&#xff1f;4、请问窗口的宽度*高度默认值为多少个像素点&#xff1f;5、利用…

Python-桌面计时器程序设计

该程序是我个人去年学习之初练习设计&#xff0c;程序功能并没有很完善和简便。设计想法是为了能够有一个可观性高的时间报时器&#xff0c;程序设计耗时2天&#xff0c;程序分成三个部分&#xff1a;主窗体、设置窗口、运行程序。 效果展示图 功能 正/反计时功能 到时提醒/关…

专利的写作

关于专利&#xff0c;由于是研究生阶段&#xff0c;发表专利有和学校合作的机构&#xff0c;支付2000给代理人&#xff0c;只需要将想法写明白&#xff0c;和代理人沟通好&#xff0c;受理那必然是有手就行。关于研究点&#xff0c;我已经推导完毕两个月了&#xff0c;因为要做…

手把手教你如何写专利申请书

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。众所周知&#xff0c;专利是最重要的一种知识产权&#xff0c;专利制度有利于保护技术创新&#xff0c;保护专利权人的利益&#xff0c;促进社会发展&#xff0c;把我国建设成一个科技强国&#xff0c;创新大国。对于企业而…

实用新型专利撰写

文件下载 表格可在国家知识产权网下载 直达地址 说明书摘要 1、文件写法 本实用新型公开了&#xff0c;其特征在于&#xff1a;______。主要组成部分&#xff1b;主要组成部分又由哪些部分组成&#xff1b;并说明位置关系&#xff08;位于xxx一侧&#xff0c;位于顶角处…&…

专利写法与相关知识

原文&#xff1a;https://www.cnblogs.com/bozhicheng/p/7204693.html by 薄小成 https://www.jianshu.com/p/4f48add262c1 这也是一个比较好的链接 从你幸运的进入大棚124实验室那刻起&#xff0c;发论文和写专利将贯穿你整个研究生生涯。相比于发论文&#xff0c;写专利这项工…

【数据库】简介

目录 0. 文章脉络 1. 信息和数据 2. 数据处理 3. 数据库管理数据的特点 4. 数据库系统 5. 数据库管理系统 6. 数据库的三级模式 0. 文章脉络 1. 信息和数据 信息是生活中能获取的一切事物的相关描述。用书上的话来说&#xff0c;信息就是一切新的&#xff0c;有用的事实…

数据库介绍之MySQL

文章目录 数据库优点分类常见数据库RDBMSSQL定义分类sql 脚本sql 语句规范 CRUD MySQL启动连接修改密码忘记密码三层结构结构表 三范式关系数据库设计三范式经典设计多对多一对多一对一 数据库 用来存储和管理数据的仓库 优点 可存储大量数据&#xff0c;方便检索保持数据的…

Cassandra数据库介绍

Cassandra 数据库&#xff0c;值得介绍的技术细节其实挺多的。因为它很多实现思路和关系型数据库或者其他的 NoSQL 数据库&#xff0c;是有一些不同的。这种不同是在数据库设计实现思路上也是根源上的。所以衍生开来的诸多特点&#xff0c;在介绍起来就不太容易和其他数据库去类…

MySQL入门之数据库介绍及MySQL介绍

------------------------------------------------------------------------------------------------------------- 教程大纲: http://blog.csdn.net/qq78442761/article/details/76018310 ------------------------------------------------------------------------------…

数据库概述与常见数据库介绍

前言 本栏目会从数据库概念开始到数据库的SQL优化持续更新&#xff08;站在Java开发的角度&#xff0c;不站在数据库管理员&#xff08;DBA&#xff09;角度&#xff09;&#xff0c;本篇是第一篇《数据库常用概念》以开启我的数据库之旅&#xff0c;主要是讲述MySQL 8.0数据库…