核心函数参考示例
5 Dec 2024
Read time: 6 minute(s)
写寄存器函数:用于向 gt911 发送控制命令或数据
static rt_err_t gt911_write_reg(struct rt_i2c_client *dev, rt_uint8_t *data,
rt_uint8_t len)
{
struct rt_i2c_msg msgs;
msgs.addr = dev->client_addr; //CTP 从机地址
msgs.flags = RT_I2C_WR; //i2c 读写标志,这里是写标志
msgs.buf = data; //要写入的数据
msgs.len = len; //写入的长度
if (rt_i2c_transfer(dev->bus, &msgs, 1) == 1) { //i2c 标准读写接口,第一个参数是 i2c 总线句柄,第二个是 msgs,但三个 msgs 的数量
return RT_EOK;
} else {
return -RT_ERROR;
}
}
读寄存器函数:用于从 gt911 读取状态或数据
static rt_err_t gt911_read_regs(struct rt_i2c_client *dev, rt_uint8_t *reg,
rt_uint8_t *data, rt_uint8_t len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = dev->client_addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = reg; //要读取的寄存器的地址,一般是 8 位的地址,但如 gt911 就有 16 位,需要每一次写入高 8 位和低 8 位两个 buf
msgs[0].len = GT911_REGITER_LEN; //这个与寄存器地址长度对应,8 位写 1,16 位写 2
msgs[1].addr = dev->client_addr;
msgs[1].flags = RT_I2C_RD; //读标志
msgs[1].buf = data; //读取到数据存放位置
msgs[1].len = len; //要读取的长度
if (rt_i2c_transfer(dev->bus, msgs, 2) == 2) { //标准的 i2c 读流程都是先写后读,先把要读的寄存器发出去,再读数据,所以这里 msgs 的数量是 2
return RT_EOK;
} else {
return -RT_ERROR;
}
}
gt911 获得设备 ID 函数编写
static rt_err_t gt911_get_product_id(struct rt_i2c_client *dev,
rt_uint8_t *data, rt_uint8_t len)
{
rt_uint8_t reg[2];
reg[0] = (rt_uint8_t)(GT911_PRODUCT_ID >> 8);
reg[1] = (rt_uint8_t)(GT911_PRODUCT_ID & 0xff);
if (gt911_read_regs(dev, reg, data, len) != RT_EOK) {
LOG_E("read id failed");
return -RT_ERROR;
}
return RT_EOK;
}
以 gt911 获得设备 ID 的函数来讲解一下 gt911 读函数的使用:
-
第一步是定义一个 rt_uint8_t 的数组;
- 第二步将要读取的寄存器赋值给数组
-
16 位的 CTP 需将高 8 位赋值给 reg[0],低 8 位赋值给 reg[1]
-
8 位的 CTP 则只需要把寄存器直接赋给 reg[0]
-
-
第三步调用自己编写的 CTP 读函数把相关的参数传递过去。
注:
若某些触控芯片无设备 ID 寄存器,则此函数可直接返回成功状态。
gt911 获得设备信息参数函数
此函数旨在提取触控屏的关键信息,如分辨率、坐标范围。其编写逻辑与获取 ID 相似,利用读寄存器操作完成。
static rt_err_t gt911_get_info(struct rt_i2c_client *dev,
struct rt_touch_info *info)
gt911 读坐标点函数
static rt_size_t gt911_read_point(struct rt_touch_device *touch, void *buf,
rt_size_t read_num)
此为核心函数,负责读取触控点坐标及事件类型(如按下、移动、抬起)。利用之前定义的读写函数,结合逻辑判断处理触控事件,由于篇幅过长在这里不一一展开,建议参考 gt911 驱动。
gt911 控制函数
此函数提供了通过命令控制触控面板的能力,涵盖获取 ID、信息查询及参数设置等功能,是驱动对外交互的接口。
static rt_err_t gt911_control(struct rt_touch_device *touch, int cmd, void *arg)
gt911 ops 注册函数
此函数将读点和控制功能注册到触摸驱动框架中,确保系统能正确调用这些操作
static struct rt_touch_ops gt911_touch_ops = {
.touch_readpoint = gt911_read_point,
.touch_control = gt911_control,
};
gt911 gpio 引脚定义函数
此函数提供了通过命令控制触控面板的能力,涵盖获取 ID、信息查询及参数设置等功能,是驱动对外交互的接口。
static int rt_gt911_gpio_cfg()
{
unsigned int g, p;
long pin;
// RST
pin = drv_pin_get(GT911_RST_PIN); //复位引脚的宏定义
g = GPIO_GROUP(pin);
p = GPIO_GROUP_PIN(pin);
hal_gpio_direction_input(g, p);
// INT
pin = drv_pin_get(GT911_INT_PIN); //中断引脚的宏定义
g = GPIO_GROUP(pin);
p = GPIO_GROUP_PIN(pin);
hal_gpio_direction_input(g, p);
hal_gpio_set_irq_mode(g, p, 0);
return 0;
}
gt911 初始化函数
static int rt_hw_gt911_init(const char *name, struct rt_touch_config *cfg)
{
struct rt_touch_device *touch_device = RT_NULL; //初始化触摸设备句柄
touch_device =
(struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device)); //动态分配内存
if (touch_device == RT_NULL) {
LOG_E("touch device malloc fail");
return -RT_ERROR;
}
rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device)); //初始化内存空间为 0
/* hw init*/
// rst output 0
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT); //设置复位引脚的方向
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW); //设置输出低电平
rt_thread_delay(10); //一般设置完输出要延时一段时间,具体多少看规格书
// irq output 0
rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT); //设置中断引脚的方向
rt_pin_write(cfg->irq_pin.pin, PIN_LOW);
rt_thread_delay(2);
// rst output 1
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH); //设置输出高电平
rt_thread_delay(5);
// rst input
rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_INPUT);
//irq output 0
rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT);
rt_pin_write(cfg->irq_pin.pin, PIN_LOW);
rt_thread_delay(50);
rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_INPUT);
gt911_client.bus =
(struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name); //寻找 i2c 总线
if (gt911_client.bus == RT_NULL) {
LOG_E("Can't find %s device", cfg->dev_name);
return -RT_ERROR;
}
if (rt_device_open((rt_device_t)gt911_client.bus, RT_DEVICE_FLAG_RDWR) !=
RT_EOK) { //打开设备
LOG_E("open %s device failed", cfg->dev_name);
return -RT_ERROR;
}
gt911_client.client_addr = GT911_ADDRESS_HIGH; //将 CTP 的设备地址进行赋值
/* register touch device */
touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
touch_device->info.vendor = RT_TOUCH_VENDOR_GT;
rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
touch_device->ops = >911_touch_ops;
if (RT_EOK != rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL)) { //注册触摸设备
LOG_E("touch device gt911 init failed !!!");
return -RT_ERROR;
}
LOG_I("touch device gt911 init success");
return RT_EOK;
}
此函数完成硬件初始化、I²C 总线配置、设备结构体设置及注册触摸设备等关键步骤。遵循芯片规格书中关于复位和中断引脚的操作时序
gt911 驱动注册函数
static int rt_hw_gt911_port(void)
{
struct rt_touch_config cfg;
rt_uint8_t rst_pin;
rt_gt911_gpio_cfg();
rst_pin = drv_pin_get(GT911_RST_PIN); //复位引脚宏定义
cfg.dev_name = GT911_I2C_CHAN;
cfg.irq_pin.pin = drv_pin_get(GT911_INT_PIN); //中断引脚宏定义
cfg.irq_pin.mode = PIN_MODE_INPUT;
cfg.user_data = &rst_pin;
rt_hw_gt911_init("gt911", &cfg);
return 0;
}
INIT_DEVICE_EXPORT(rt_hw_gt911_port);
通过宏 INIT_DEVICE_EXPORT,驱动在系统启动时自动加载。只需调整引脚宏定义和设备名称,即可轻松适配不同型号的触控芯片,假设硬件 CTP 是 FT7411 则将示例中的 gt911 替换为 ft7411,以及修改对应的引脚宏定义
