11 电容触摸模块
11.1 引脚介绍
电容模块IC是用GT911,这个模块是用IIC通信,还有一个中断引脚,如有触摸按下中断引脚会有电平变化。图4.1是GT911与主控连接图。
图4.1
11.2 寄存器介绍
图4.2是介绍本次用到的寄存器功能,如想知道其他寄存器功能,请自行查询。读取芯片ID可测试硬件通信是否正常。
图4.2
11.3 电容触摸驱动程序
#define TP_GPIO_RST GPIOA
#define TP_PIN_RST PIN5
#define TP_GPIO_INT GPIOD
#define TP_PIN_INT PIN0
#define TP_PORT_SCL PORTA
#define TP_PIN_SCL PIN1
#define TP_PIN_SCL_FUN PORTA_PIN1_I2C0_SCL
#define TP_PORT_SDA PORTA
#define TP_PIN_SDA PIN0
#define TP_PIN_SDA_FUN PORTA_PIN0_I2C0_SDA
#define GT_CTRL_REG 0X8040 //GT911控制寄存器
#define GT_CFGS_REG 0X8047 //GT911配置起始地址寄存器
#define GT_CHECK_REG 0X80FF //GT911校验和寄存器
#define GT_PID_REG 0X8140 //GT911产品ID寄存器
#define GT_GSTID_REG 0X814E //GT911当前检测到的触摸情况
#define GT_TP1_REG 0X8150 //第一个触摸点数据地址
#define GT_TP2_REG 0X8158 //第二个触摸点数据地址
#define GT_TP3_REG 0X8160 //第三个触摸点数据地址
#define GT_TP4_REG 0X8168 //第四个触摸点数据地址
#define GT_TP5_REG 0X8170 //第五个触摸点数据地址
/**
* @brief 向GT911写入一次数据
* @param reg 起始寄存器地址
* @param buf 数据缓缓存区
* @param len 写数据长度
* @return 0,成功;1,失败.
*/
uint8_t GT911_WR_Reg(uint16_t reg, uint8_t * buf, uint8_t len)
{
uint32_t i;
uint8_t ack;
ack = I2C_Start(I2C0, (GT9x_ADDR << 1) | 0, 1);
if (ack == 0)
goto wr_fail;
ack = I2C_Write(I2C0, reg >> 8, 1);
if (ack == 0)
goto wr_fail;
ack = I2C_Write(I2C0, reg & 0XFF, 1);
if (ack == 0)
goto wr_fail;
for (i = 0; i < len; i++) {
ack = I2C_Write(I2C0, buf[i], 1);
if (ack == 0)
goto wr_fail;
}
I2C_Stop(I2C0, 1);
return 0;
wr_fail:
I2C_Stop(I2C0, 1);
return 1;
}
/**
* @brief 从GT911读出一次数据
* @param reg 起始寄存器地址
* @param buf 数据缓缓存区
* @param len 读数据长度
* @return 0,成功;1,失败.
*/
uint8_t GT911_RD_Reg(uint16_t reg, uint8_t * buf, uint8_t len)
{
uint8_t i;
uint8_t ack;
ack = I2C_Start(I2C0, (GT9x_ADDR << 1) | 0, 1);
if (ack == 0) {
goto rd_fail;
}
ack = I2C_Write(I2C0, reg >> 8, 1);
if (ack == 0) {
goto rd_fail;
}
ack = I2C_Write(I2C0, reg & 0XFF, 1);
if (ack == 0) {
goto rd_fail;
}
swm_delay_ms(5);//此处必须延时等待一会再启动
ack = I2C_Start(I2C0, (GT9x_ADDR << 1) | 1, 1); //ReStart
if (ack == 0) {
goto rd_fail;
}
for (i = 0; i < len - 1; i++) {
buf[i] = I2C_Read(I2C0, 1, 1);
}
buf[i] = I2C_Read(I2C0, 0, 1);
I2C_Stop(I2C0, 1);
return 0;
rd_fail:
I2C_Stop(I2C0, 1);
return 1;
}
/**
* @brief G911软复位操作
*/
void GT911_Soft_Reset(void)
{
uint8_t buf[1];
buf[0] = 0x01;
GT911_WR_Reg(GT911_COMMAND_REG, (uint8_t *)buf, 1);
}
/**
* @brief GT911硬复位操作,RST为低电平时,INT持续为低电平,1ms后RST置为高电平,10ms后INT设置为输入,
* 使GT911地址设定为0xBA/0x28。
*/
void GT911_Reset_Sequence(uint8_t ucAddr) //未使用
{
//GT911_RST_INT_GPIO_Init();
switch (ucAddr) {
case 0xBA:
GT911_RST_0(); //RST引脚低电平
GT911_INT_0(); //INT引脚低电平
swm_delay_ms(30); //延时30ms,最短1
GT911_RST_1(); //RST引脚高电平
GT911_INT_0(); //INT引脚低电平
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_0();
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_1();
break;
case 0x28:
GT911_RST_0(); //RST引脚低电平
GT911_INT_1(); //INT引脚高电平
swm_delay_ms(30); //延时30ms,最短1
GT911_RST_1(); //RST引脚高电平
GT911_INT_1(); //INT引脚高电平
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_0();
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_1();
break;
default: //其他默认为0xBA
GT911_RST_0(); //RST引脚低电平
GT911_INT_0(); //INT引脚低电平
swm_delay_ms(30); //延时30ms,最短1
GT911_RST_1(); //RST引脚高电平
GT911_INT_0(); //INT引脚低电平
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_0();
swm_delay_ms(30); //延时30ms,最短20
GT911_INT_1();
break;
}
}
/**
* @brief GT911 初始化
* @return 0 初始化成功 1初始化失败非GT911
*/
uint8_t GT911_Init(void)
{
uint8_t temp[4]; uint16_t i = 0;
I2C_InitStructure I2C_initStruct;
PORT_Init(TP_PORT_SCL, TP_PIN_SCL, TP_PIN_SCL_FUN, 1); //配置为 I2C0 SCL 引脚
TP_PORT_SCL->PULLU |= (1 << TP_PIN_SCL); //必须使能上拉
TP_PORT_SCL->OPEND |= (1 << TP_PIN_SCL); //开漏
PORT_Init(TP_PORT_SDA, TP_PIN_SDA, TP_PIN_SDA_FUN, 1); //配置为 I2C0 SDA 引脚
TP_PORT_SDA->PULLU |= (1 << TP_PIN_SDA);
TP_PORT_SDA->OPEND |= (1 << TP_PIN_SDA);
I2C_initStruct.Master = 1;
I2C_initStruct.Addr10b = 0;
I2C_initStruct.MstClk = 100000;
I2C_initStruct.TXEmptyIEn = 0; //发送寄存器空中断使能
I2C_initStruct.RXNotEmptyIEn = 0;//接收寄存器非空中断使能
I2C_Init(I2C0, &I2C_initStruct);
I2C_Open(I2C0);
GPIO_Init(TP_GPIO_INT, TP_PIN_INT, 0, 0, 1, 0); // 输入,开启下拉。复位时INT为低,选择0xBA作为地址
GPIO_Init(TP_GPIO_RST, TP_PIN_RST, 1, 1, 0, 0); //复位引脚初始化
GPIO_ClrBit(TP_GPIO_RST, TP_PIN_RST);//复位拉低
swm_delay_ms(10);
GPIO_SetBit(TP_GPIO_RST, TP_PIN_RST); //复位拉高
swm_delay_ms(10);
temp[0] = 0x02;
GT911_WR_Reg(GT_CTRL_REG, temp, 1); // 软复位
swm_delay_ms(100);
GT911_Reset_Sequence(0xBA);//硬复位 设置复位后地址0xBA
GT911_RD_Reg(GT_PID_REG, temp, 4);//读取产品ID
if (strcmp((char *)temp, "911") == 0)//ID==911
{
temp[0] = 0X02;
GT911_WR_Reg(GT_CTRL_REG, temp, 1);//软复位GT911
GT911_RD_Reg(GT_CFGS_REG, temp, 1);//读取GT_CFGS_REG寄存器
swm_delay_ms(10);
temp[0] = 0X00;
GT911_WR_Reg(GT_CTRL_REG, temp, 1);//结束复位
return 0;
}
return 1;
}
/**
* @brief 触摸扫描
* @param mode 0 正常扫描
* @return 0 无触摸 1有触摸
*/
uint8_t GT911_Scan(uint8_t mode)
{
uint8_t buf[4];
uint8_t i = 0, res = 0;
uint8_t temp, temp_sta;
uint8_t cnt = 0;
uint8_t status = 0;
uint8_t ret_reset = 0;
//读取触摸点的状态
if (GT911_RD_Reg(GT_GSTID_REG, &status, 1)) {
ret_reset = 1;
goto reset_lb;
}
if (TP_Dev.status & TP_PRES_DOWN) {
switch (status) {
case 0x00: {
res = 1;
goto ret_lb;
}
case 0xff: {
res = 0;
TP_Dev.status = 0x00;
goto ret_lb;
}
default:
break;
}
}
cnt = status & 0X0f;
if (status & 0X80 && cnt < 6) {
temp = 0;
//清标志
if (GT911_WR_Reg(GT_GSTID_REG, &temp, 1)) {
ret_reset = 1;
goto reset_lb;
}
}
if (!cnt) {
goto ret_lb;
}
temp = 0XFF << cnt; //将点的个数转换为1的位数,匹配TP_Dev.sta定义
temp_sta = TP_Dev.status; //保存当前的TP_Dev.sta值
TP_Dev.status = (~temp) | TP_PRES_DOWN | TP_CATH_PRES;
TP_Dev.x[4] = TP_Dev.x[0]; //保存触点0的数据
TP_Dev.y[4] = TP_Dev.y[0];
for (i = 0; i < 5; i++) {
if (TP_Dev.status & (1 << i)) {
//读取XY坐标值
if (GT911_RD_Reg(GT911_TPX_TBL[i], buf, 4)) {
ret_reset = 1;
goto reset_lb;
}
TP_Dev.x[i] = ((uint16_t)(buf[1] & 0X0F) << 8) + buf[0];
TP_Dev.y[i] = ((uint16_t)(buf[3] & 0X0F) << 8) + buf[2];
}
}
res = 1;
if (TP_Dev.x[0] < LCD_HDOT && TP_Dev.y[0] < LCD_VDOT) {
goto ret_lb;
}
/** 非法范围的值 */
if (cnt > 1) {
TP_Dev.x[0] = TP_Dev.x[1];
TP_Dev.y[0] = TP_Dev.y[1];
} else {
TP_Dev.x[0] = TP_Dev.x[4];
TP_Dev.y[0] = TP_Dev.y[4];
status = 0X80;
TP_Dev.status = temp_sta; //恢复TP_Dev.sta
}
ret_lb:
if ((status & 0X8F) == 0X80)//无触摸点按下
{
if (TP_Dev.status & TP_PRES_DOWN) //之前是被按下的
{
TP_Dev.status &= ~(1 << 7); //标记按键松开
} else {
TP_Dev.x[0] = 0xffff;
TP_Dev.y[0] = 0xffff;
TP_Dev.status &= 0XE0; //清除点有效标记
}
}
return res;
reset_lb:
if (ret_reset) {
GT911_Soft_Reset();
// GT911_Init();
}
return res;
}
-
- GT-HMI Designer用户手册
- GT-HMI Engine用户手册
- 高通字库芯片开发资料
- GTDB-X7ESP 高通智匠AI开发板规格书
- GTC-480480TFT40XP模块使用手册
- GTC-480272TFT43XP模块使用手册
- GTC-800480TFT50G模块使用手册
- GTC-800480TFT70GP模块使用手册
- GTC-1024600TFT101GP模块使用手册
- GT-GUI LCD 0.96寸液晶模组数据手册
- GT-GUI LCD 1.9寸液晶模组数据手册
- GT-GUI LCD 2.8寸液晶模组数据手册
- GT-GUI LCD 3.5寸液晶模组数据手册
- GUI-LCD开发板使用手册
- GT5GL128B标准GUI芯片规格书
- GT5GL64芯片产品规格书
高通字库交流群
GT-HMI交流群