tslib应用编程

文章内容来自百问网

目录

1. 电阻屏和电容屏

1.1 电阻屏原理

1.2 电阻屏数据

1.3 电容屏原理

1.4 电容屏数据

2. tslib

2.1 简介

2.2 相关库函数

2.2.1 打开触摸屏设备

2.2.2 关闭触摸屏设备

2.2.3 读取触摸屏数据

2.2.3.1 单点触摸

2.2.3.2 多点触摸

2.3 示例代码



1. 电阻屏和电容屏

1.1 电阻屏原理

电阻屏就是基于欧姆定律制作的,它有上下两层薄膜,这两层薄膜就是两个 电阻,如下图所示:

平时上下两层薄膜无触触,当点击触摸屏时,上下两层薄膜接触:这时就可 以测量触点电压。过程如下:

测量X坐标:

在xp、xm两端施加3.3V电压,yp和ym不施加电压(yp就相当于探针), 测量yp电压值。该电压值就跟X坐标成正比关系,假设:X = 3.3*Vyp/Xmax

测量Y坐标:

在yp、ym两端施加3.3V电压,xp和xm不施加电压(xp就相当于探针), 测量xp电压值。该电压值就跟Y坐标成正比关系,假设:Y = 3.3*Vxp/Ymax

在实际使用时,电阻屏的 Xmax、Ymax 无从得知,所以使用之前要先较准: 依次点击触摸屏的四个角和中心点,推算出X、Y坐标的公式:X = func(Vyp) Y = func(Vxp)

1.2 电阻屏数据

Linux 驱动程序中,会上报触点的X、Y数据,注意:这不是LCD的坐标值, 需要APP再次处理才能转换为LCD坐标值。

对应的input_event结构体中,“type、code、value”如下:

1.3 电容屏原理

电容屏中有一个控制芯片,它会周期性产生驱动信号,接收电极接收到信号, 并可测量电荷大小。当电容屏被按下时,相当于引入了新的电容,从而影响了接 收电极接收到的电荷大小。主控芯片根据电荷大小即可计算出触点位置。

我们只需要编写程序,通过I2C读取芯片寄存器即可得到这些数据。

1.4 电容屏数据

触摸屏能分辨是哪一个触点,上报数据时会先上报触点ID,再上报它的数据。

2. tslib

2.1 简介

tslib 是一个触摸屏的开源库,可以使用它来访问触摸屏设备,可以给输入设备添加各种“filter”(过滤器,就是各种处理),地址是: tslib

编译tslib 后,可以得到libts 库,还可以得到各种工具:较准工具、测试工具。

核心在于“plugins”目录里的“插件”,或称为“module”。这个目录下的每个文件都是一个module,每个module都提供2个函数:read、read_mt,前者用于读取单点触摸屏的数据,后者用于读取多点触摸屏的数据。

分析tslib的框架:

调用ts_open后,可以打开某个设备节点,构造出一个tsdev结构体。然后调用ts_config读取配置文件的处理,假设/etc/ts.conf内容如下:

 module_raw input 
 module pthres pmin=1 
 module dejitter delta=100 
 module linear 

每行表示一个“module”或“moduel_raw”。

对于所有的“module”,都会插入tsdev.list链表头,也就是tsdev.list 执行配置文件中最后一个“module”,配置文件中第一个“module”位于链表的尾部。

对于所有的“module_raw”,都会插入tsdev.list_raw链表头,一般只有 一个“module_raw”

因为是递归调用,所有最先使用input模块读取设备节点得到原始数据,再依次经过pthres模块、dejitter模块、linear模块处理后,才返回最终数据。

2.2 相关库函数

2.2.1 打开触摸屏设备

  • struct tsdev *ts_open(const char *dev_name, int nonblock);

    • const char *dev_name:指定了触摸屏的设备节点

    • int nonblock:以什么方式打开设备节点 阻塞0或非阻塞1

    • 返回值:成功返回struct tsdev *指针指向触摸屏设备句柄,失败返回NULL

  • struct tsdev *ts_setup(const char *dev_name, int nonblock);

    • const char *dev_name:指定了触摸屏的设备节点,其意义与ts_open相同,但该值可以填NULL,当dev_name设置为NULL时,ts_setup() 函数内部会读取 TSLIB_TSDEVICE 环境变量,获取该环境变量的内容以得知触摸屏的设备节点

    • int nonblock:以什么方式打开设备节点 阻塞0或非阻塞1

    • 返回值:成功返回struct tsdev *指针指向触摸屏设备句柄,失败返回NULL

2.2.2 关闭触摸屏设备

  • int ts_config(struct tsdev *ts);

    • struct tsdev *ts:指向触摸屏句柄

    • 返回值:成功返回0,失败返回-1

2.2.3 读取触摸屏数据

2.2.3.1 单点触摸
  • int ts_read(struct tsdev *ts, struct ts_sample *samp, int nr);

    • struct tsdev *ts:指向触摸屏句柄

    • struct ts_sample *samp:struct ts_sample * 类型的指针,指向一个 struct ts_sample 对象, struct ts_sample 数据结构描述了触摸点的信息

    • int nr:对一个触摸点的采样数,设置为1

    • 返回值:成功返回 0 ,失败返回 -1

    • /* 结构体参数的解释 */
      struct ts_sample {
       int x; //X 坐标
       int y; //Y 坐标
       unsigned int pressure; //按压力大小
       struct timeval tv; //时间
      };

2.2.3.2 多点触摸
  • int ts_read_mt(struct tsdev *ts, struct ts_sample_mt **samp, int max_slots, int nr);

    • struct tsdev *ts:指向触摸屏句柄

    • struct ts_sample_mt **samp:二重指针,多点触摸应用程序,每一个触摸点的信息使用 struct ts_sample_mt 数据结构来描述;一个触摸点的数据使用一个 struct ts_sample_mt 对象来装载,将它们组织成一个 struct ts_sample_mt 数组,调用 ts_read_mt() 时,将数组地址赋值给 samp 参数。

    • int max_slots:触摸屏支持的最大触摸点数

    • int nr:对一个触摸点的采样数,设置为1

    • 返回值:成功返回 0 ,失败返回 -1

    • /* 结构体参数的解释 */
      struct ts_sample_mt {
       /* ABS_MT_* event codes. linux/include/uapi/linux/input-event-codes.h
       * has the definitions.
       */
       int x; //X 坐标
       int y; //Y 坐标
       unsigned int pressure; //按压力大小
       int slot; //触摸点 slot
       int tracking_id; //ID
       int tool_type;
       int tool_x;
       int tool_y;
       unsigned int touch_major;
       unsigned int width_major;
       unsigned int touch_minor;
       unsigned int width_minor;
       int orientation;
       int distance;
       int blob_id;
       struct timeval tv; //时间
       /* BTN_TOUCH state */
       short pen_down; //BTN_TOUCH 的状态
      /* valid is set != 0 if this sample
       * contains new data; see below for the
       * bits that get set.
       * valid is set to 0 otherwise
       */
       short valid; //此次样本是否有效标志 触摸点数据是否发生更新
      };

2.3 示例代码

// 实现一个程序,不断打印2个触点的距离。 
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
​
#include <linux/input.h>
​
#include <sys/ioctl.h>
​
#include <tslib.h>
​
int distance(struct ts_sample_mt *point1, struct ts_sample_mt *point2)
{
    int x = point1->x - point2->x;
    int y = point1->y - point2->y;
​
    return x*x + y*y;
}
​
int main(int argc, char **argv)
{
    struct tsdev *ts; 
    int i;
    int ret;
    struct ts_sample_mt **samp_mt;
    struct ts_sample_mt **pre_samp_mt;  
    int max_slots;
    int point_pressed[20];
    struct input_absinfo slot;
    int touch_cnt = 0;
​
    ts = ts_setup(NULL, 0);
    if (!ts)
    {
        printf("ts_setup err\n");
        return -1;
    }
​
    if (ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot) < 0) {
        perror("ioctl EVIOGABS");
        ts_close(ts);
        return errno;
    }
​
    max_slots = slot.maximum + 1 - slot.minimum;
​
    samp_mt = malloc(sizeof(struct ts_sample_mt *));
    if (!samp_mt) {
        ts_close(ts);
        return -ENOMEM;
    }
    samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));
    if (!samp_mt[0]) {
        free(samp_mt);
        ts_close(ts);
        return -ENOMEM;
    }
​
    pre_samp_mt = malloc(sizeof(struct ts_sample_mt *));
    if (!pre_samp_mt) {
        ts_close(ts);
        return -ENOMEM;
    }
    pre_samp_mt[0] = calloc(max_slots, sizeof(struct ts_sample_mt));
    if (!pre_samp_mt[0]) {
        free(pre_samp_mt);
        ts_close(ts);
        return -ENOMEM;
    }
​
​
    for ( i = 0; i < max_slots; i++)
        pre_samp_mt[0][i].valid = 0;
​
    while (1)
    {
        ret = ts_read_mt(ts, samp_mt, max_slots, 1);
​
        if (ret < 0) {
            printf("ts_read_mt err\n");
            ts_close(ts);
            return -1;
        }
​
        for (i = 0; i < max_slots; i++)
        {
            if (samp_mt[0][i].valid)
            {
                memcpy(&pre_samp_mt[0][i], &samp_mt[0][i], sizeof(struct ts_sample_mt));
            }
        }
​
        touch_cnt = 0;
        for (i = 0; i < max_slots; i++)
        {
            if (pre_samp_mt[0][i].valid && pre_samp_mt[0][i].tracking_id != -1)
                point_pressed[touch_cnt++] = i;
        }
​
        if (touch_cnt == 2)
        {
            printf("distance: %08d\n", distance(&pre_samp_mt[0][point_pressed[0]], &pre_samp_mt[0][point_pressed[1]]));
        }
    }
    
    return 0;
}

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值