stm32HAL库驱动gt911触摸屏

gt911是五点触摸屏,接下来采用轮询方法驱动。

中断我也写好了,测试后发现,没必要使用中断,触摸一次会触发三次中断,所以代码写得很绕,用了一个定时器来屏蔽这个中断,不如直接用一个定时器轮询来得直接。

gt911简单介绍

1、gt911有两种i2c地址,使用0x28和0x29

2、触摸屏参数一般是出厂时,商家写好了,我们一般不需要改,如果不小心改了参数,建议联系商家,让他把参数给你,重新写进寄存器里。

3、上电,初始化触摸屏,先往0x8040寄存器写0x02,等待10ms后,写0x00,软复位。

4、0x814E寄存器获取屏幕是否触摸,以及触摸点数,读取值是,0或128则无触摸,129一个触摸点,130两个,131三个。。。 。读取完后,非0值都要往这个寄存器写0x00复位,不然会一直触发INT引脚脉冲。

5、读取触摸数值,一个点的x要两个字节,低位在前,高位在后。y也是。

轮询方法

1、配置CubeMX

gt911可以使用400kHz的快速模式,所以我们配置为快速模式。

如果I2C没有接外部上拉电阻,一定要使用内部上拉。

配置gt911的RESET和INT引脚,如果RESET引脚没有外部上拉电阻,要配置为内部上拉推挽输出。INT随便,我们在代码里再重新配置,初始化后INT引脚一定是浮空模式,哪怕不使用中断。

2、编程

新建一个gt911.h文件,代码如下

#ifndef _GT911_H_
#define _GT911_H_

#include "i2c.h"
#define GT911_I2Cx hi2c1   //改成你的I2Cx

#define GT911_INT_PORT           GPIOB				 //改成你的配置
#define GT911_INT_PIN            GPIO_PIN_5    //改成你的配置

#define GT911_RESET_PORT           GPIOB			 //改成你的配置
#define GT911_RESET_PIN            GPIO_PIN_4  //改成你的配置

extern I2C_HandleTypeDef GT911_I2Cx;


#define GT911_CMD_WR 		0X28     	//写命令
#define GT911_CMD_RD 		0X29			//读命令
  
//GT911 寄存器 
#define GT911_CTRL_REG 		0X8040   	//GT911控制寄存器
#define GT911_CFGS_REG 		0X8047   	//GT911配置起始地址寄存器
#define GT911_CHECK_REG 	0X80FF   	//GT911校验和寄存器
#define GT911_PID_REG 		0X8140   	//GT911产品ID寄存器

#define GT911_GSTID_REG 	0X814E   	//GT911当前检测到的触摸情况
#define GT911_TP1_REG 		0X8150  	//第一个触摸点数据地址
#define GT911_TP2_REG 		0X8158		//第二个触摸点数据地址
#define GT911_TP3_REG 		0X8160		//第三个触摸点数据地址
#define GT911_TP4_REG 		0X8168		//第四个触摸点数据地址
#define GT911_TP5_REG 		0X8170		//第五个触摸点数据地址 


struct gt911_point_typedef  
{
	uint16_t x1;
	uint16_t y1;
	
	uint16_t x2;
	uint16_t y2;
	
	uint16_t x3;
	uint16_t y3;
	
	uint16_t x4;
	uint16_t y4;
	
	uint16_t x5;
	uint16_t y5;
	

};

extern struct gt911_point_typedef gt911_point;



void gt911_init(void);
uint8_t gt911_scan(struct gt911_point_typedef *point);


#endif /*_GT911_H_*/

新建一个gt911.c文件,代码如下

#include "gt911.h"
#include "stdio.h"



struct gt911_point_typedef gt911_point;





static void gt911_GPIO_address_config()
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	GPIO_InitStruct.Pin = GT911_INT_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;                
	GPIO_InitStruct.Pull = GPIO_PULLUP;                    
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;     
	HAL_GPIO_Init(GT911_INT_PORT, &GPIO_InitStruct); 				
	
	HAL_GPIO_WritePin(GT911_INT_PORT, GT911_INT_PIN, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GT911_RESET_PORT, GT911_RESET_PIN, GPIO_PIN_RESET);
	HAL_Delay(10);
	
	
	HAL_GPIO_WritePin(GT911_INT_PORT, GT911_INT_PIN, GPIO_PIN_SET);
	HAL_Delay(10);
	HAL_GPIO_WritePin(GT911_RESET_PORT, GT911_RESET_PIN, GPIO_PIN_SET);
	HAL_Delay(10);
	
	GPIO_InitStruct.Pin = GT911_INT_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;              
	GPIO_InitStruct.Pull = GPIO_NOPULL;                    /* 不带上下拉,浮空模式 */
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    
	HAL_GPIO_Init(GT911_INT_PORT, &GPIO_InitStruct); 
	HAL_Delay(100);
}

static uint8_t gt911_init_count=0;
void gt911_init(void)
{

	gt911_GPIO_address_config();
	uint8_t chip_id[4];
	uint8_t i2c_status;
	i2c_status = HAL_I2C_Mem_Read(&GT911_I2Cx,GT911_CMD_RD,GT911_PID_REG,I2C_MEMADD_SIZE_16BIT,chip_id,4,100);
	
	if(i2c_status!=0||chip_id[0]!='9')
	{
		printf("%s\r\n",chip_id);
		printf("I2C_init_status:%d\r\n",i2c_status);
		gt911_init_count++;
		
		if(gt911_init_count>3) return ;
		gt911_init();  //这里用了递归,不是很标准写法,如果出错,把这行屏蔽就行了
//			HAL_I2C_DeInit(&GT911_I2Cx);
//			HAL_Delay(100);
//			HAL_I2C_Init(&GT911_I2Cx);
//			HAL_Delay(100);
		gt911_init_count = 0;
	}
	
  
	
	uint8_t gt911_reset = 0x02;
	HAL_I2C_Mem_Write(&GT911_I2Cx,GT911_CMD_WR,GT911_CTRL_REG,I2C_MEMADD_SIZE_16BIT,&gt911_reset,1,100);
	
	HAL_Delay(10);
	gt911_reset = 0x00;
	HAL_I2C_Mem_Write(&GT911_I2Cx,GT911_CMD_WR,GT911_CTRL_REG,I2C_MEMADD_SIZE_16BIT,&gt911_reset,1,100);
	
}

/**
 * @brief       轮询读取gt911数据
 * @param       point: 传入gt911.h定义好的全局指针
 * @retval      返回触摸点的个数,0即是无触摸
 */
uint8_t gt911_scan(struct gt911_point_typedef *point)
{

		uint8_t touch_state=0;
		uint8_t gt911_gstid_reg_reset=0;
		uint8_t i2c_state=HAL_I2C_Mem_Read(&GT911_I2Cx,GT911_CMD_RD,GT911_GSTID_REG,I2C_MEMADD_SIZE_16BIT,&touch_state,1,100);
			
		if(i2c_state==1)
		{
			printf("i2c state:%d\r\n",i2c_state);
			gt911_init();
			return 0;			
		}
				
		//printf("touch_state:%d\r\n",touch_state);
		if(touch_state==128||touch_state==0)
		{
				//printf("not touch:%d\r\n",touch_state);			
				HAL_I2C_Mem_Write(&GT911_I2Cx,GT911_CMD_WR,GT911_GSTID_REG,I2C_MEMADD_SIZE_16BIT,&gt911_gstid_reg_reset,1,100);	
				return 0;
		}
		
		uint8_t touch_point[4];
		uint16_t *p;
		p = (uint16_t *) point;
		for(uint8_t i=0; i<(touch_state-128);i++)
		{
			
			
				HAL_I2C_Mem_Read(&GT911_I2Cx,GT911_CMD_RD,GT911_TP1_REG+i*8,I2C_MEMADD_SIZE_16BIT,touch_point,4,100);
				*p =(touch_point[1]<<8)|touch_point[0];
				p++;
				*p =(touch_point[3]<<8)|touch_point[2];
				p++;
			
			
		}

		
		HAL_I2C_Mem_Write(&GT911_I2Cx,GT911_CMD_WR,GT911_GSTID_REG,I2C_MEMADD_SIZE_16BIT,&gt911_gstid_reg_reset,1,100);	
		return touch_state-128;


}

在main.c文件中引入gt911.h,在main函数中初始化和读取数值


	gt911_init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		uint8_t touch_num;
		touch_num = gt911_scan(&gt911_point);
		printf("touch_num:%d\r\n",touch_num);
		if(touch_num!=0)
		{
			uint16_t *p;
			p = (uint16_t *) &gt911_point;
			for(int i= 0;i<touch_num;i++)
			{
				uint16_t x = *p;
				p++;
				uint16_t y = *p;
				p++;
				printf("x%d,y%d:%d,%d\r\n",i,i,x,y);
							
			}
			
		}
		
		HAL_Delay(100);
	
  }

3、输出结果

### STM32F1 驱动 GT911 触摸屏教程 #### 使用IIC接口配置 对于STM32F1系列微控制器来说,要实现与GT911触摸屏的有效通信,首先需要完成IIC接口的基础配置。这涉及到初始化IIC外设、设置SCL和SDA引脚为开漏输出模式,并确保这些引脚连接到外部上拉电阻。 ```c // 初始化IIC外设, 假定使用IICA2 void IIC_Init(void){ GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); // 开启GPIOB时钟 // SDA PB7 GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 复用功能开漏输出 GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // SCL PB6 GPIO_InitStruct.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); __HAL_RCC_I2C1_CLK_ENABLE(); } ``` 接着,在实际应用中还需要调用`HAL_I2C_Master_Transmit()`函数来向GT911发送命令或读取状态信息。为了简化编程流程并提高代码可维护性,建议创建专门用于处理特定于GT911交互逻辑的功能函数[^2]。 #### 使用SPI接口配置 当采用SPI作为通讯手段时,则应按照如下方式进行初步设定: - **选择合适的SPI通道**:比如这里选择了SPI1。 - **配置MOSI/MISO/SCK管脚**:将其分别指定为相应的SPI信号线。 - **调整SPI的工作模式及时序参数**:包括但不限于波特率的选择等。 ```c static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(__FILE__, __LINE__); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } /** * @brief Initialize the SPI pins. */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); /* Configure CS Pin as output push-pull type */ GPIO_InitStruct.Pin = SPI1_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SPI1_CS_GPIO_Port, &GPIO_InitStruct); /* Configure MOSI and SCLK Pins */ GPIO_InitStruct.Pin = SPI1_MOSI_Pin|SPI1_SCK_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } ``` 上述代码片段展示了如何针对STM32F1平台上的SPI1进行基本的硬件资源分配及初始化过程[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值