2021-06-16FT5X06触摸实验-40

Posted 杨斌并

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-06-16FT5X06触摸实验-40相关的知识,希望对你有一定的参考价值。

FT5X06触摸实验

  • 安装完以下ft5x06触摸驱动会打印一下内容,说明驱动编写成功

    [12727.015690] ft5x06_driver_init
    [12727.015821] this is  ft5x06_probe
     ft5x06_device_node is ft5x06
    [12727.015963] ft5x06_irp_gpio is 52
    [12727.015973] ft5x06_reset_gpio is 41
    [12727.027780] input: ft5x06_input_test as /devices/virtual/input/input16
    [12727.029412] i2c_add_driver is success
    
  • 输入 cat /proc/bus/input/devices 后成功看到如下:name和代码中的要匹配, input 和打印中的要匹配


I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="ft5x06_input_test"
P: Phys=
S: Sysfs=/devices/virtual/input/input16
U: Uniq=
H: Handlers=event7 cpufreq
B: PROP=0
B: EV=b
B: KEY=400 0 0 0 0 1000000
B: ABS=1000003

busybox hexdump /dev/input/event7

Event typescodevaluevalue
0000000ea4e609b5f3c000c0001014a00010000
0000010ea4e609b5f3c000c0003000001760000
0000020ea4e609b5f3c000c0003000102700000
0000030ea4e609b5f3c000c0000000000000000
0000040ea4e609bddd3000c0001014a00000000
0000050ea4e609bddd3000c0000000000000000
#include <linux/input.h> //这个头文件中
/*
 * Event types
 */

#define EV_SYN			0x00
#define EV_KEY			0x01
#define EV_REL			0x02
#define EV_ABS			0x03
#define EV_MSC			0x04
#define EV_SW			0x05
#define EV_LED			0x11
#define EV_SND			0x12
#define EV_REP			0x14
#define EV_FF			0x15
#define EV_PWR			0x16
#define EV_FF_STATUS		0x17
#define EV_MAX			0x1f
#define EV_CNT			(EV_MAX+1)

/* Code 255 is reserved for special needs of AT keyboard driver */

#define BTN_DIGI		0x140
#define BTN_TOOL_PEN		0x140
#define BTN_TOOL_RUBBER		0x141
#define BTN_TOOL_BRUSH		0x142
#define BTN_TOOL_PENCIL		0x143
#define BTN_TOOL_AIRBRUSH	0x144
#define BTN_TOOL_FINGER		0x145
#define BTN_TOOL_MOUSE		0x146
#define BTN_TOOL_LENS		0x147
#define BTN_TOOL_QUINTTAP	0x148	/* Five fingers on trackpad */
#define BTN_TOUCH		0x14a
#define BTN_STYLUS		0x14b
#define BTN_STYLUS2		0x14c
#define BTN_TOOL_DOUBLETAP	0x14d
#define BTN_TOOL_TRIPLETAP	0x14e
#define BTN_TOOL_QUADTAP	0x14f	/* Four fingers on trackpad */


/*
 * Absolute axes 绝对区域
 */

#define ABS_X			0x00
#define ABS_Y			0x01
#define ABS_Z			0x02
#define ABS_RX			0x03
#define ABS_RY			0x04
#define ABS_RZ			0x05
#define ABS_THROTTLE		0x06
#define ABS_RUDDER		0x07
#define ABS_WHEEL		0x08
#define ABS_GAS			0x09
#define ABS_BRAKE		0x0a
#define ABS_HAT0X		0x10
#define ABS_HAT0Y		0x11
#define ABS_HAT1X		0x12
#define ABS_HAT1Y		0x13
#define ABS_HAT2X		0x14
#define ABS_HAT2Y		0x15
#define ABS_HAT3X		0x16
#define ABS_HAT3Y		0x17
#define ABS_PRESSURE		0x18
#define ABS_DISTANCE		0x19
#define ABS_TILT_X		0x1a
#define ABS_TILT_Y		0x1b
#define ABS_TOOL_WIDTH		0x1c

#define ABS_VOLUME		0x20

#define ABS_MISC		0x28

#define ABS_MT_SLOT		0x2f	/* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR	0x30	/* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR	0x31	/* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR	0x32	/* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR	0x33	/* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION	0x34	/* Ellipse orientation */
#define ABS_MT_POSITION_X	0x35	/* Center X touch position */
#define ABS_MT_POSITION_Y	0x36	/* Center Y touch position */
#define ABS_MT_TOOL_TYPE	0x37	/* Type of touching device */
#define ABS_MT_BLOB_ID		0x38	/* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID	0x39	/* Unique ID of initiated contact */
#define ABS_MT_PRESSURE		0x3a	/* Pressure on contact area */
#define ABS_MT_DISTANCE		0x3b	/* Contact hover distance */
#define ABS_MT_TOOL_X		0x3c	/* Center X tool position */
#define ABS_MT_TOOL_Y		0x3d	/* Center Y tool position */


#define ABS_MAX			0x3f
#define ABS_CNT			(ABS_MAX+1)
  • 各种事件
  1. ABS_MT_TRACKING_ID

    参数是类型B特有的。实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束)。无论在接触的类型相对应的slot发生了改变,驱动都应该通过改变这个值来使这个slot失效。并且下一次触摸的ID值会是这次的值加1。

  2. EV_ABS

    事件的一种类型。表示绝对坐标。

  3. EV_KEY

    事件的一种类型。表示是按键事件。

  4. BTN_TOUCH

    触碰按键。其值是DOWN或者UP。

  5. BTN_TOOL_FINGER

    按键的是finger,并且其值也是DOWN或者UP。

  6. ABS_MT_POSITION_X,ABS_MT_POSITION_Y

    相对于屏幕中心的x,y坐标。

  7. ABS_MT_TOUCH_MAJOR

    接触部分的长轴长度。相当于椭圆的长轴。

  8. ABS_MT_TOUCH_MINOR

    接触部分的短轴长度。相当于椭圆的短轴。

  9. EV_SYN

    事件类型的一种。在事件完成的时候更新数据。

  10. SYN_REPORT

    可以看到,在一次触摸中,就有好几次SYN_REPORT。是因为有很多的事件,或者是说SYN_REPORT就是一次事件的结束。上报内核

  • 点击屏幕后出现这些数据,下面我们解释下如上的数据
  1. 后两列是value
  2. 倒数第三列对应code
  3. 倒数第四列对应Event types
  • 第一行

    Event types 0001 代表 EV_KEY

    code 014a 代表 #define BTN_TOUCH 0x14a 是touch 事件 0代表抬起, 1 代表摁下

    value 0001 对应的是摁下

    第一行 这个事件的意思是 单个手指触摸到了屏幕

  • 第二行

    Event types 0003 代表#define EV_ABS 0x03 是触摸的绝对坐标

    code 0000 代表 #define ABS_X 0x00 是x轴的绝对坐标

    value 0176 换算十进制 是 374

    第二行的 这个事件的意思是 单个手指 触摸屏幕的x的坐标是 374

  • 第三行

    Event types 0003 代表#define EV_ABS 0x03 是触摸的绝对坐标

    code 0001 代表 #define ABS_Y 0x00 是y轴的绝对坐标

    value 0270 换算十进制 是624

    这个事件的意思是 单个手指 触摸屏幕的y的绝对坐标 是624

  • 第四行

    Event types 0000 代表 #define EV_SYN 0x00 是上报这个事件信号

    将摁下,触摸屏幕的点的坐标 上报给了内核

  • 第五行

    Event types 0001 代表 EV_KEY

    code 014a 代表 #define BTN_TOUCH 0x14a 是touch 事件 0代表抬起, 1 代表摁下

    value 0000 对应的是抬起

    这个事件意思是 单个手指离开了屏幕

  • 第六行

    Event types 0000 代表 #define EV_SYN 0x00 是上报这个事件信号

    将摁下,触摸屏幕的点的坐标 上报给了内核

代码

  • touch_test.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/workqueue.h>


//工作模式为正常状态的地址
#define DEVICE_MOOE 0x00
//为工作时的地址
#define ID_G_MODE 0xa4

struct device_node  *ftx06_device_node;
struct input_dev *ft5x06_dev;

static void ft5x06_fun(struct work_struct *work);

DECLARE_WORK(ft5x06_work,ft5x06_fun);
static struct i2c_client * ft5x06_client;
int irq;


static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len);

static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len){

    u8 buff[256];
     struct i2c_msg msgs[] = {
        [0] = {
            .addr   = ft5x06_client->addr,
            .flags  = 0,
            .len    = len + 1,
            .buf    = buff,
        },

        // [1] = {
        //     .addr   = ft5x06_client->addr,
        //     .flags  = 1,
        //     .len    = sizeof(data),
        //     .buf    = &data,
        // }
    };

    buff[0] = reg_addr;
    memcpy(&buff[1], &data, len);

    i2c_transfer(ft5x06_client->adapter, msgs, 1);

}

struct of_device_id  ft5x06_id[] = {
    {.compatible = "edt,ft5x0x_ts", 0},
    {.compatible = "edt,ft5x0x_ts", 0},
    {.compatible = "edt,ft5x0x_ts", 0},
    {}
};

struct i2c_device_id  ft5x06_id_ts[] = {
    {"xxxxx", 0},
    {},
};
static int ft5x06_read_reg(u8 reg_addr);
static int ft5x06_read_reg(u8 reg_addr){

    u8 data;
    struct i2c_msg msgs[] = {
        [0] = {
            .addr   = ft5x06_client->addr,
            .flags  = 0,
            .len    = sizeof(reg_addr),
            .buf    = &reg_addr,
        },

        [1] = {
            .addr   = ft5x06_client->addr,
            .flags  = 1,
            .len    = sizeof(data),
            .buf    = &data,
        }
    };

    i2c_transfer(ft5x06_client->adapter, msgs, 2);

    return  data;

}

static void ft5x06_fun(struct work_struct *work){

    int TOUCH1_XH, TOUCH1_XL,x;
    int TOUCH1_YH, TOUCH1_YL,y;
    int TD_STATUS;
    //读取TOUCH1_XH 寄存器的值
    TOUCH1_XH = ft5x06_read_reg(0x03);
    //读取TOUCH1_XL 寄存器的值
    TOUCH1_XL = ft5x06_read_reg(0x04);
    //获取x的坐标值
    x = ((TOUCH1_XH << 8) | TOUCH1_XL) & 0x0fff;
   
    //读取TOUCH1_YH 寄存器的值
    TOUCH1_YH = ft5x06_read_reg(0x05);
    //读取TOUCH1_YL 寄存器的值
    TOUCH1_YL = ft5x06_read_reg(0x06);
    //获取Y的坐标值
    y = ((TOUCH1_YH << 8) | TOUCH1_YL) & 0x0fff;

    //读取寄存器TD_STATUS 的值
    TD_STATUS = ft5x06_read_reg(0x02);
    //获取有没有手指在屏幕上
    TD_STATUS = TD_STATUS & 0xf;

    //判断有没有手指按上,如果有的话就要上报摁下的事件,没有就要上报抬手的事件
    if (TD_STATUS ==0)
    {   
        input_report_key(ft5x06_dev, BTN_TOUCH, 0);
        input_sync(ft5x06_dev);
    } else {
        input_report_key(ft5x06_dev, BTN_TOUCH, 1);
        input_report_abs(ft5x06_dev, ABS_X, x);
        input_report_abs(ft5x06_dev, ABS_Y, y);
        input_sync(ft5x06_dev);
    }
    

}

irq_handler_t ft5x06_handler(int irq, void * args){

    schedule_work(&ft5x06_work);

    return IRQ_HANDLED;

}




int ft5x06_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id){

    int ret;

    int ft5x06_irp_gpio;
    int ft5x06_reset_gpio;

    printk("this is  ft5x06_probe \\n ");
    ft5x06_client = i2c_client;//因为我们要在别的函数里面用到这个client,所以我们要把他们复制进来

    ftx06_device_node = of_find_node_by_path("/i2c@ff110000/ft5x06@38");

    //获得触摸芯片的节点
    if (ftx06_device_node == NULL)
    {
        printk("of_find_node_by_path is error \\n");
        return -1;
    }

    printk("ft5x06_device_node is %s \\n", ftx06_device_node->name);

    //获得中断号
    ft5x06_irp_gpio = of_get_named_gpio(ftx06_device_node, "touch-gpio", 0);

    if (ft5x06_irp_gpio < 0)
    {
       printk("of_get_named_gpio_irq is error \\n");
       return -1;
    }

    //获得复位引脚标号
    ft5x06_reset_gpio = of_get_named_gpio(ftx06_device_node, "reset-gpios", 0);
    
    if (ft5x06_reset_gpio < 0)
    {
        printk("of_get_named_gpio_reset is error \\n");
        return -1;
    }

    printk("ft5x06_irp_gpio is %d \\n", ft5x06_irp_gpio);
    printk("ft5x06_reset_gpio is %d \\n", ft5x06_reset_gpio);

    //申请中断引脚
    gpio_free(ft5x06_irp_gpio);
    ret = gpio_request(ft5x06_irp_gpio, "irq_gpio");

    if (ret < 0 )
    {
        printk("gpio_request_irp is error \\n ");
        return -1;
    }

    //申请复位引脚
    gpio_free(ft5x06_reset_gpio);
    ret = gpio_request(ft5x06_reset_gpio, "reset_gpio");

    if (ret < 0 )
    {
        printk("gpio_request_reset is error \\n ");
        return -1;
    }

    //把中断的引脚设置为输入
    gpio_direction_input(ft5x06_irp_gpio);

    //设置复位引脚的方向为输出,然后停止复位
    gpio_direction_output(ft5x06_reset_gpio, 0);

    msleep(5);

    gpio_set_value(ft5x06_reset_gpio, 1);

    irq = gpio_to_irq(ft5x06_irp_gpio);

    ret = request_irq(irq, ft5x06_handler, IRQ_TYPE_EDGE_FALLING|IRQF_TRIGGER_RISING, "ft5x06_irq", NULL);
    if (ret < 0)
    {
        printk("request_irq is error \\n");
        goto error_request_irq;
    }
    

    //设置工作模式为正常
    ft5x06_write_reg(DEVICE_MOOE, 0, 1);

    // ret = ft5x06_read_reg(ID_G_MODE, 1, 1);
    ft5x06_write_reg(ID_G_MODE, 1, 1);

    ft5x06_dev = input_allocate_device();
    ft5x06_dev->name = "ft5x06_input_test";

    //key 事件
    __set_bit(EV_KEY,ft5x06_dev->evbit);
    //绝对事件   触摸
    __set_bit(EV_ABS, ft5x06_dev->evbit);
    //支持按键检测 事件
    __set_bit(BTN_TOUCH,ft5x06_dev->keybit);

    //支持x坐标值的范围
    __set_bit(ABS_X, ft5x06_dev->absbit);
    //支持y坐标值的范围
    __set_bit(ABS_Y, ft5x06_dev->absbit);
    //支持压力值的检测
    __set_bit(ABS_PRESSURE, ft5x06_dev->keybit);

    //设置x坐标的范围
    input_set_abs_params(ft5x06_dev, ABS_X, 0, 800, 0, 0);
    //设置y坐标的范围
    input_set_abs_params(ft5x06_dev, ABS_Y, 0, 1280, 0, 0);
    //设置按压范围
    input_set_abs_params(ft5x06_dev, ABS_PRESSURE, 0, 255, 0, 0);


    ret = input_register_device(ft5x06_dev);

    if (ret < 0)
    {
        printk("input_register_device is error \\n");
        goto error_input_register;
    }

    return 0;

error_request_irq:
    free_irq(irq, NULL);
    return ret;
error_input_register:
    free_irq(irq, NULL);
    input_unregister_device(ft5x06_dev);
    input_free_device(ft5x06_dev);
    return ret;
}

int ft5x06_remove(struct i2c_client *i2c_client){
    printk("ft5x06_remove \\n ");
    return 0;
}


static struct i2c_driver ft5x06_driver = {
    .probe = ft5x06_probe,
    .remove = ft5x06_remove,
    .id_table = ft5x06_id_ts,
    .driver = {
        .owner = THIS_MODULE,
        .name = "ft5x06_test",
        .of_match_table = ft5x06_id,
    },
};


static int ft5x06_driver_init(void){

    int ret;

    printk("ft5x06_driver_init \\n");

    ret = i2c_add_driver(&ft5x06_driver);
    if (ret < 0)
    {
        printk("i2c_add_driver is error \\n ");
        return  ret ;
    }

    printk("i2c_add_driver is success \\n");

    return 0;

}

static void ft5x06_driver_exit(void){

    printk("ft5x06_driver_exit \\n");
    input_unregister_device(ft5x06_dev);
    input_free_device(ft5x06_dev);
    free_irq(irq, NULL);
    i2c_del_driver(&ft5x06_driver);

}

module_init(ft5x06_driver_init);
module_exit(ft5x06_driver_exit);
MODULE_LICENSE("GPL");

以上是关于2021-06-16FT5X06触摸实验-40的主要内容,如果未能解决你的问题,请参考以下文章

Linux驱动开发-编写FT5X06触摸屏驱动

2021-06-16

2021-06-16:返回一个数组中,选择的数字不能相邻的情况下, 最大子序列累加和。

2021-06-16

2021-06-16

2021.06.16即将到来的毕业