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;

}

 

下一页
上一页
    • 联系电话

    • 0755—83453881
    • 服务时间

    • 周一至周五 9:00-18:00
    • 高通GT-HMI交流群