RA6M4驱动****GT911
在我使用的TFT—LCD屏中的触摸屏为GT911。
【原理图】
GT911---- IO
SCL ----400
SDA ----401
RST ----700
INT ----701
一、【GT911 I2C 地址】
GT911根据初始化的时序有两个地址。
GT911 的 I2C 从机地址由硬件引脚状态决定:
默认地址:0x5D(上电时 INT 引脚为低电平)。
备用地址:0x14(上电时 INT 引脚为高电平)。
硬件设计注意:地址选择与 RST 和 INT 引脚的连接方式相关,需确保引脚电平符合预期。
二、初始化
1、第一步,GT9xx的IIC地址选择
GT9 系列在通信中始终作为从设备,其I2C设备地址由7 位设备地址加1 位读写控制位组成,高7 位为地址,bit 0为读写
控制位。GT9 系列有两个从设备地址可供选择:

设置方法为:
把RST、INT引脚配置为输出模式。
A、把RST、INT拉低,延时10ms,把INT拉高,延时100us,把RST拉高,就可以把IIC地址设为0x28/0x29

B、把RST、INT拉低,延时10ms,把RST拉高,就可以把IIC地址设为0xBA/0xBB

2、第二步
把INT设置为悬浮输入模式(如果要用外部中断检测INT,也要在这里配置好),RST保持拉高输出。
3、第三步
更新GT9xx寄存器配置,如果不需要更新,可以直接跳过。
1)、往控制命令寄存器(0x8040)写入2,软复位GT9xx。
2)、把寄存器配置数组写入(0x8047-0x8100),一共186个寄存器,这些寄存器的功能可以查看数据手册。需要注意的是:
A,0X8047寄存器用于指示配置文件版本号,程序写入的版本号,必须大于等于GT9xx本地保存的版本号,才可以更新配置,否则当前写入配置无效。
B,0X80FF寄存器用于存储校验和,使得0X8047-0X80FF之间所有数据之和为0,如果校验不通过,当前配置无效。
C,0X8100用于控制是否将配置保存在本地,写0,则不保存配置,写1则保存配置。
3)、往控制命令寄存器(0x8040)写入0,结束软复位。
4、完成初始化过程。
三、读取触摸点坐标值
当有触摸发生时,GT9xx会有3个提示:
1、INT会输出上升沿或下降沿信号。
2、状态寄存器0x814E的最高位(buffer状态位)的值变为1,表示数据已准备好。
3、状态寄存器0x814E的低4位的值会变为触摸点个数,提示有多少个点被按
读完坐标后,要把0x814E寄存器清为0,表示坐标点已读。否则GT9xx会一直输出INT信号,不继续检测触摸。切记!
因此对应的,我们有3种读取方法:
1、轮询读取0x814E寄存器的值,如果最高位(buffer状态位)的值变为1,则依照低4位来读取相应个数的坐标值,读完后把0x814E寄存器清为0。如果最高位为0,则退出,继续下一次检测。
2、使用INT中断,当有触摸发生,INT输出信号触发外部中断。在中断服务程序中读取0x814E的低4位得到触摸点数,再去读取相应个数的坐标值,读完后把0x814E寄存器清为0。
四、RASC配置
根据原理图的设计,在原有的LVGL的工程中进行配置
1、配置Pin
打开工程的RASC配置方法如下:

2、添加stacks的r_master_iic
添加一个stacks,在其属性中选择通道为0,地址为0x14,并填写IIC的回调函数。

然后生成工程。
3、RST、INT配置
配置P700、P701为普通输出模式

4、配置IIC两条IO为内部上拉
由于选择默认的IIC的IO配置,电平上拉不了,因此需要配置他的IO如下:
五、代码编写
1、添加GT911.h到工程中:
#ifndef GT911_H
#define GT911_H
/***********************************************************************************************************************
* Includes
**********************************************************************************************************************/
#include "hal_data.h"
#include <stdio.h>
/**********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/
#define TOUCH_POINT_TOTAL (5) /* 此芯片最多支持五点触控 */
/**********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/
typedef enum
{
TP_ROT_NONE = 0,
TP_ROT_90,
TP_ROT_180,
TP_ROT_270
} tp_rotation_t;
/***********************************************************************************************************************
* Exported global variables
**********************************************************************************************************************/
/***********************************************************************************************************************
* Exported global functions (to be accessed by other files)
**********************************************************************************************************************/
fsp_err_t drv_i2c_touchpad_init(void);
void touchpad_set_rotation(tp_rotation_t rotation);
fsp_err_t touchpad_is_touched(void);
void touchpad_get_pos(uint16_t *x, uint16_t *y, int index);
#endif /*GT911_H*/
2、插入GT911.c
#include "gt911.h"
#include <stdlib.h>
#include "common_utils.h"
#define GT911_RESET_PIN BSP_IO_PORT_07_PIN_00
#define GT911_INT_PIN BSP_IO_PORT_07_PIN_01
#define GT_CTRL_REG 0x8040
#define GT_CFGS_REG 0x8047
#define GT_CHECK_REG 0x80FF
#define GT_PID_REG 0x8140
#define GT_GSTID_REG 0x814E
#define GT_TP1_REG 0x814F
#define GT_TP2_REG 0x8157
#define GT_TP3_REG 0x815F
#define GT_TP4_REG 0x8167
#define GT_TP5_REG 0x816F
#define GT911_READ_X_MAX_REG 0x8048
#define GT911_READ_Y_MAX_REG 0x804a
#define GT911_READ_XY_REG 0x814E
#define GT911_CLEARBUF_REG 0x814E
#define GT911_CONFIG_REG 0x8047
#define GT911_COMMAND_REG 0x8040
#define GT911_PRODUCT_ID_REG 0x8140
#define GT911_VENDOR_ID_REG 0x814A
#define GT911_CONFIG_VERSION_REG 0x8047
#define GT911_CONFIG_CHECKSUM_REG 0x80FF
#define GT911_FIRMWARE_VERSION_REG 0x8144
typedef struct
{
uint8_t id;
uint16_t x;
uint16_t y;
uint16_t size;
} tp_point_info_t;
typedef struct
{
uint8_t tp_dev_addr;
uint16_t height;
uint16_t width;
tp_rotation_t rotation;
tp_point_info_t points_info[TOUCH_POINT_TOTAL];
} tp_drv_t;
static void i2c0_wait_for_tx(void);
static void i2c0_wait_for_rx(void);
static fsp_err_t gt911_write_reg(uint16_t reg, uint8_t *buf, uint8_t len);
static fsp_err_t gt911_read_reg(uint16_t reg, uint8_t *buf, uint8_t len);
static void gt911_clear_buf();
static void gt911_soft_reset(void);
static void gt911_get_gstid(uint8_t *buf);
static void gt911_get_version(uint8_t *buf);
static void gt911_get_vendor_id(uint8_t *buf);
static void gt911_get_product_id(uint8_t *buf);
static void gt911_get_max_x(uint8_t *buf);
static void gt911_get_max_y(uint8_t *buf);
static tp_drv_t g_tp_drv;
static volatile bool g_i2c0_tx_complete = false;
static volatile bool g_i2c0_rx_complete = false;
fsp_err_t drv_i2c_touchpad_init(void)
{
fsp_err_t err;
uint8_t buf[4];
err = g_i2c_master0.p_api->open (g_i2c_master0.p_ctrl, g_i2c_master0.p_cfg);
if (FSP_SUCCESS != err)
{
APP_PRINT ("%s %d\r\n", __FUNCTION__, __LINE__);
return err;
}
g_ioport.p_api->pinWrite (g_ioport.p_ctrl, GT911_RESET_PIN, BSP_IO_LEVEL_LOW);
g_ioport.p_api->pinWrite (g_ioport.p_ctrl, GT911_INT_PIN, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay (10, BSP_DELAY_UNITS_MILLISECONDS);
g_ioport.p_api->pinWrite (g_ioport.p_ctrl, GT911_RESET_PIN, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
g_ioport.p_api->pinCfg (g_ioport.p_ctrl, GT911_INT_PIN, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
touchpad_set_rotation (TP_ROT_NONE);
gt911_get_vendor_id (buf);
APP_PRINT ("gt911 vendor id = %02x %02x %02x %02x\r\n", buf[0], buf[1], buf[2], buf[3]);
gt911_get_product_id (buf);
APP_PRINT ("gt911 product id = %02x %02x %02x %02x\r\n", buf[0], buf[1], buf[2], buf[3]);
gt911_get_version (buf);
APP_PRINT ("version = 0x%x\r\n", buf[0]);
gt911_get_max_x (buf);
g_tp_drv.width = (uint16_t) ((buf[1] << 8) | buf[0]);
APP_PRINT ("touchpad max x = %d\r\n", g_tp_drv.width);
gt911_get_max_y (buf);
g_tp_drv.height = (uint16_t) ((buf[1] << 8) | buf[0]);
APP_PRINT ("touchpad max y = %d\r\n", g_tp_drv.height);
return err;
}
fsp_err_t touchpad_is_touched(void)
{
uint8_t touched_state, touch_num, buffer_status;
gt911_get_gstid (&touched_state);
touch_num = touched_state & 0xf;
buffer_status = (touched_state >> 7) & 1;
if (buffer_status == 1 && (touch_num <= TOUCH_POINT_TOTAL) && (touch_num > 0))
{
uint16_t pointers_regs[TOUCH_POINT_TOTAL] =
{ GT_TP1_REG, GT_TP2_REG, GT_TP3_REG, GT_TP4_REG, GT_TP5_REG };
for (int i = 0; i < touch_num; ++i)
{
uint8_t point_info_per_size = 7;
uint8_t *point_info_p = malloc (point_info_per_size * sizeof(uint8_t ));
gt911_read_reg (pointers_regs[i], point_info_p, point_info_per_size);
g_tp_drv.points_info[i].id = point_info_p[0];
g_tp_drv.points_info[i].x = (uint16_t) (point_info_p[1] + (point_info_p[2] << 8));
g_tp_drv.points_info[i].y = (uint16_t) (point_info_p[3] + (point_info_p[4] << 8));
g_tp_drv.points_info[i].size = (uint16_t) (point_info_p[5] + (point_info_p[6] << 8));
free (point_info_p);
uint16_t temp;
switch (g_tp_drv.rotation)
{
case TP_ROT_NONE:
g_tp_drv.points_info[i].x = g_tp_drv.width - g_tp_drv.points_info[i].x;
g_tp_drv.points_info[i].y = g_tp_drv.height - g_tp_drv.points_info[i].y;
APP_PRINT("touchX: %u touchfY:%u\r\n", g_tp_drv.points_info[i].x,g_tp_drv.points_info[i].y);
break;
case TP_ROT_270:
temp = g_tp_drv.points_info[i].x;
g_tp_drv.points_info[i].x = g_tp_drv.width - g_tp_drv.points_info[i].y;
g_tp_drv.points_info[i].y = temp;
break;
case TP_ROT_180:
break;
case TP_ROT_90:
temp = g_tp_drv.points_info[i].x;
g_tp_drv.points_info[i].x = g_tp_drv.points_info[i].y;
g_tp_drv.points_info[i].y = g_tp_drv.height - temp;
break;
default:
break;
}
}
gt911_clear_buf ();
return FSP_SUCCESS;
}
gt911_clear_buf ();
return FSP_ERR_INVALID_DATA;
}
void touchpad_set_rotation(tp_rotation_t rotation)
{
g_tp_drv.rotation = rotation;
}
void touchpad_get_pos(uint16_t *x, uint16_t *y, int index)
{
*x = g_tp_drv.points_info[index].x;
*y = g_tp_drv.points_info[index].y;
}
void i2c_master0_callback(i2c_master_callback_args_t *p_args)
{
switch (p_args->event)
{
case I2C_MASTER_EVENT_TX_COMPLETE:
{
g_i2c0_tx_complete = true;
break;
}
case I2C_MASTER_EVENT_RX_COMPLETE:
{
g_i2c0_rx_complete = true;
break;
}
default:
{
g_i2c0_tx_complete = g_i2c0_rx_complete = false;
break;
}
}
}
static void i2c0_wait_for_tx(void)
{
while (!g_i2c0_tx_complete)
;
g_i2c0_tx_complete = 0;
}
static void i2c0_wait_for_rx(void)
{
while (!g_i2c0_rx_complete)
;
g_i2c0_rx_complete = 0;
}
static void gt911_soft_reset(void)
{
uint8_t buf[1];
buf[0] = 0x02;
gt911_write_reg (GT911_COMMAND_REG, (uint8_t*) buf, 1);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
buf[0] = 0x0;
gt911_write_reg (GT911_COMMAND_REG, (uint8_t*) buf, 1);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
}
static void gt911_clear_buf()
{
uint8_t buf[1] =
{ 0 };
gt911_write_reg (GT911_CLEARBUF_REG, buf, 1);
}
static fsp_err_t gt911_write_reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
fsp_err_t err;
uint8_t regl = (uint8_t) (reg & 0xff);
uint8_t regh = (uint8_t) (reg >> 8);
uint8_t *write_package = malloc ((len + 2) * sizeof(uint8_t));
memcpy (write_package, ®h, 1);
memcpy (write_package + 1, ®l, 1);
memcpy (write_package + 2, buf, len);
err = g_i2c_master0.p_api->write (g_i2c_master0.p_ctrl, write_package, len + 2, 0);
i2c0_wait_for_tx ();
free (write_package);
return err;
}
static fsp_err_t gt911_read_reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
fsp_err_t err;
uint8_t tmpbuf[2];
tmpbuf[0] = (uint8_t) (reg >> 8);
tmpbuf[1] = (uint8_t) (reg & 0xff);
err = g_i2c_master0.p_api->write (g_i2c_master0.p_ctrl, tmpbuf, 2, 0);
i2c0_wait_for_tx ();
err = g_i2c_master0.p_api->read (g_i2c_master0.p_ctrl, buf, len, 0);
i2c0_wait_for_rx ();
return err;
}
static void gt911_get_max_x(uint8_t *buf)
{
gt911_read_reg (GT911_READ_X_MAX_REG, buf, 2);
}
static void gt911_get_max_y(uint8_t *buf)
{
gt911_read_reg (GT911_READ_Y_MAX_REG, buf, 2);
}
static void gt911_get_product_id(uint8_t *buf)
{
gt911_read_reg (GT911_PRODUCT_ID_REG, buf, 4);
}
static void gt911_get_vendor_id(uint8_t *buf)
{
gt911_read_reg (GT911_VENDOR_ID_REG, buf, 4);
}
static void gt911_get_version(uint8_t *buf)
{
gt911_read_reg (GT911_CONFIG_VERSION_REG, buf, 1);
}
static void gt911_get_gstid(uint8_t *buf)
{
gt911_read_reg (GT_GSTID_REG, buf, 1);
}
static fsp_err_t i2c_touchpad_read(void)
{
fsp_err_t err;
uint16_t x = 0, y = 0;
err = touchpad_is_touched ();
if (FSP_SUCCESS == err)
{
for (int i = 0; i < TOUCH_POINT_TOTAL; ++i)
{
touchpad_get_pos (&x, &y, i);
}
}
return err;
}
void app_i2c_touchpad_test(void)
{
fsp_err_t err;
err = drv_i2c_touchpad_init();
if(FSP_SUCCESS != err) __BKPT();
while (1)
{
i2c_touchpad_read();
}
}
六、LVGL触摸驱动的适配
1、打开lvgl中的编译开关
将lv_port_indev_template.h/c把if 0 修改为if 1打开代码编译。
2、修改lv_port_indev_template.c代码如下
#include "lv_port_indev_template.h"
#include "lvgl.h"
#include "gt911.h"
static void touchpad_init(void);
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);
lv_indev_t * indev_touchpad;
void lv_port_indev_init(void)
{
static lv_indev_drv_t indev_drv;
touchpad_init();
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touchpad_read;
indev_touchpad = lv_indev_drv_register(&indev_drv);
}
static void touchpad_init(void)
{
drv_i2c_touchpad_init();
}
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
fsp_err_t err;
static lv_coord_t last_x = 0;
static lv_coord_t last_y = 0;
err = touchpad_is_touched();
if(FSP_SUCCESS == err) {
touchpad_get_pos((uint16_t *)&last_x, (uint16_t *)&last_y, 0);
data->state = LV_INDEV_STATE_PR;
}
else {
data->state = LV_INDEV_STATE_REL;
}
last_x = ST7796_WIDTH - last_x;
last_y = ST7796_HEIGHT - last_y;
data->point.x = last_x;
data->point.y = last_y;
}
3、测试
在hal_enty中添加测lv_port_indev_init(),烧写到开发板中,打开segger view可以看到触摸屏后正确的输出坐标:
