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 types | code | value | value | |||||
---|---|---|---|---|---|---|---|---|
0000000 | ea4e | 609b | 5f3c | 000c | 0001 | 014a | 0001 | 0000 |
0000010 | ea4e | 609b | 5f3c | 000c | 0003 | 0000 | 0176 | 0000 |
0000020 | ea4e | 609b | 5f3c | 000c | 0003 | 0001 | 0270 | 0000 |
0000030 | ea4e | 609b | 5f3c | 000c | 0000 | 0000 | 0000 | 0000 |
0000040 | ea4e | 609b | ddd3 | 000c | 0001 | 014a | 0000 | 0000 |
0000050 | ea4e | 609b | ddd3 | 000c | 0000 | 0000 | 0000 | 0000 |
#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)
- 各种事件
-
ABS_MT_TRACKING_ID
参数是类型B特有的。实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束)。无论在接触的类型相对应的slot发生了改变,驱动都应该通过改变这个值来使这个slot失效。并且下一次触摸的ID值会是这次的值加1。
-
EV_ABS
事件的一种类型。表示绝对坐标。
-
EV_KEY
事件的一种类型。表示是按键事件。
-
BTN_TOUCH
触碰按键。其值是DOWN或者UP。
-
BTN_TOOL_FINGER
按键的是finger,并且其值也是DOWN或者UP。
-
ABS_MT_POSITION_X,ABS_MT_POSITION_Y
相对于屏幕中心的x,y坐标。
-
ABS_MT_TOUCH_MAJOR
接触部分的长轴长度。相当于椭圆的长轴。
-
ABS_MT_TOUCH_MINOR
接触部分的短轴长度。相当于椭圆的短轴。
-
EV_SYN
事件类型的一种。在事件完成的时候更新数据。
-
SYN_REPORT
可以看到,在一次触摸中,就有好几次SYN_REPORT。是因为有很多的事件,或者是说SYN_REPORT就是一次事件的结束。上报内核
- 点击屏幕后出现这些数据,下面我们解释下如上的数据
- 后两列是value
- 倒数第三列对应code
- 倒数第四列对应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 = ®_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的主要内容,如果未能解决你的问题,请参考以下文章