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(>911_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(>911_I2Cx);
// HAL_Delay(100);
// HAL_I2C_Init(>911_I2Cx);
// HAL_Delay(100);
gt911_init_count = 0;
}
uint8_t gt911_reset = 0x02;
HAL_I2C_Mem_Write(>911_I2Cx,GT911_CMD_WR,GT911_CTRL_REG,I2C_MEMADD_SIZE_16BIT,>911_reset,1,100);
HAL_Delay(10);
gt911_reset = 0x00;
HAL_I2C_Mem_Write(>911_I2Cx,GT911_CMD_WR,GT911_CTRL_REG,I2C_MEMADD_SIZE_16BIT,>911_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(>911_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(>911_I2Cx,GT911_CMD_WR,GT911_GSTID_REG,I2C_MEMADD_SIZE_16BIT,>911_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(>911_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(>911_I2Cx,GT911_CMD_WR,GT911_GSTID_REG,I2C_MEMADD_SIZE_16BIT,>911_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(>911_point);
printf("touch_num:%d\r\n",touch_num);
if(touch_num!=0)
{
uint16_t *p;
p = (uint16_t *) >911_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、输出结果
作者:m0_58944708