imx6ull——多点电容触摸

news2024/12/23 9:13:14

电容触摸寄存器

在这里插入图片描述
在这里插入图片描述
触点最多5个
在这里插入图片描述

触摸屏实现由 IIC驱动、中断驱动、 input子系统组成

触摸屏类型Type A和 Type B

Type A:适用于触摸点不能被区分或者追踪,此类型的设备上报原始数据 (此类型在实际使
用中非常少!
Type B:适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过 slot更新某一个
触摸点的信息, FT5426就属于此类型,一般的多点电容触摸屏 IC都有此能力。

Type B和 Type A相比最大的区别就是 Type B可以区分出触摸点, 因此可以减少发送到用户空间的数据。

Type A触摸点数据上报时序

 ABS_MT_POSITION_X x[0]  //第一个点x
 ABS_MT_POSITION_Y y[0]  //第一个点y
 SYN_MT_REPORT  //报告前一个	可以读取,后一个可以开始,使用 input_mt_sync触发此事件
 ABS_MT_POSITION_X x[1] 
 ABS_MT_POSITION_Y y[1] 
 SYN_MT_REPORT       // input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
 SYN_REPORT

Type A设备,内核驱动 需要一次性将触摸屏上所有的触摸点信息全部上报,每个触摸点的信息在本次上报事件流中的顺序不重要,因为事件的过滤和手指(触摸点 )跟踪是在内核空间处理的。

Type B触摸点数据上报时序

 ABS_MT_SLOT 0 //表示要上报第一个ID,input_mt_solt
 ABS_MT_TRACKING_ID 45 //自动分配ID,给ID赋值-1,表示删除此点
 ABS_MT_POSITION_X x[0] 
 ABS_MT_POSITION_Y y[0] 
 ABS_MT_SLOT 1 
 ABS_MT_TRACKING_ID 46 
 ABS_MT_POSITION_X x[1] 
 ABS_MT_POSITION_Y y[1] 
 SYN_REPORT

Type B使用 slot协议区分具体的触摸点, slot需要用到 ABS_MT_TRACKING_ID消息,这个 ID需要硬件提供,或者通过原始数据计算出来。
Type B设备驱动需要给每个识别出来的触摸点分配一个 slot,后面使用这个 slot来上报触摸点信息。可以通过 slot的 ABS_MT_TRACKING_ID来新增、替换或删除触摸点。一个非负数的 ID表示一个有效的触摸点, -1这个 ID表示未使用 slot。一个以前不存在的 ID表示这是一个新加的触摸点,一个 ID如果再也不存在了就表示删除了。
有些设备识别或追踪的 触摸点信息要比他上报的多,这些设备驱动应该给硬件上报的每个触摸点分配一个 Type B的 slot。一旦检测到某一个 slot关联的触摸点 ID发生了变化,驱动就应该改变这个 slot的 ABS_MT_TRACKING_ID,使这个 slot失效。如果硬件设备追踪到了比他正在上报的还要多的触摸点,那么驱动程序应该发送 BTN_TOOL_*TAP消息

多点电容驱动框架

  1. 接口采用I2C传输数据
  2. 使用中断采集触摸点数据
  3. 需要从触摸屏寄存器读取数据,使用input子系统
  4. typeB类型读取数据,MT协议上报数据(MT属于input子系统)

设备树填写

FT5426触摸芯片用到了 4个 IO,一个复位 IO、一个中断 IO、 I2C2的 SCL和 SDA

中断

&iomuxc下

		/*touch */
		pinctrl_tsc: tscgrp {  
			fsl,pins = < 
			 MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0xF080 /* TSC_INT */ 
			  >;  
		};

复位

&iomuxc_snvs下

		/* MT RET*/
		pinctrl_tsc_reset: tsc_reset{  
			fsl,pins = < 
			 MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x10B0 
			  >; 
		 };

I2C SCL,SDA

		pinctrl_i2c2: i2c2grp {
			fsl,pins = <
				MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
				MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
			>;
		};

I2C下的设备FT5426

位于 &i2c2{ }中

&i2c2 {
	clock_frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c2>;
	status = "okay";

 	/* touch FT5426 */
 		ft5426: ft5426@38 {
   	   	compatible = "edt,edt-ft5426";
     	reg = <0x38>;  /* 器件地址 */
      	pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_tsc    /* 中断节点 */
                    &pinctrl_tsc_reset >;   /* 复位节点 */
     	interrupt-parent = <&gpio1>;  /* GPIO组为 GPIO1 */
      	interrupts = <9 0>; /* GPIO1组的 IOI09,0为触发方式(上升沿,下降沿等,没查到 */
      	reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;  
      	interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; 
 	};
 	.........
 	.........
};

驱动编写

1. I2C驱动编写

#include <linux/module.h>
#include <linux/ratelimit.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/input/edt-ft5x06.h>
#include <linux/i2c.h>

/* ft5426 设备结构体*/
struct ft5426_dev
{
    void *private_data;
};

struct ft5426_dev ft5426;

static int ft5x06_read_regs(struct ft5x06_dev *dev, u8 reg, void *val, int len)
{
	int ret;
	struct i2c_msg msg[2];
	struct i2c_client *client = (struct i2c_client *)dev->client;

	/* msg[0]为发送要读取的首地址 */
	msg[0].addr = client->addr;			/* ft5x06地址 */
	msg[0].flags = 0;					/* 标记为发送数据 */
	msg[0].buf = &reg;					/* 读取的首地址 */
	msg[0].len = 1;						/* reg长度*/

	/* msg[1]读取数据 */
	msg[1].addr = client->addr;			/* ft5x06地址 */
	msg[1].flags = I2C_M_RD;			/* 标记为读取数据*/
	msg[1].buf = val;					/* 读取数据缓冲区 */
	msg[1].len = len;					/* 要读取的数据长度*/

	ret = i2c_transfer(client->adapter, msg, 2);
	if(ret == 2) {
		ret = 0;
	} else {
		ret = -EREMOTEIO;
	}
	return ret;
}

static s32 ft5x06_write_regs(struct ft5x06_dev *dev, u8 reg, u8 *buf, u8 len)
{
	u8 b[256];
	struct i2c_msg msg;
	struct i2c_client *client = (struct i2c_client *)dev->client;
	
	b[0] = reg;					/* 寄存器首地址 */
	memcpy(&b[1],buf,len);		/* 将要写入的数据拷贝到数组b里面 */
		
	msg.addr = client->addr;	/* ft5x06地址 */
	msg.flags = 0;				/* 标记为写数据 */

	msg.buf = b;				/* 要写入的数据缓冲区 */
	msg.len = len + 1;			/* 要写入的数据长度 */

	return i2c_transfer(client->adapter, &msg, 1);
}

static int ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    printk("ft5426_probe!\r\n");
    return 0;
}
static int ft5x06_ts_remove(struct i2c_client *client)
{	
    return 0;
}
/*
 *  传统驱动匹配表
 */ 
static const struct i2c_device_id ft5x06_ts_id[] = {
	{ "edt-ft5206", 0, },
	{ "edt-ft5426", 0, },
	{ /* sentinel */ }
};

/*
 * 设备树匹配表 
 */
static const struct of_device_id ft5x06_of_match[] = {
	{ .compatible = "edt,edt-ft5206", },
	{ .compatible = "edt,edt-ft5426", },
	{ /* sentinel */ }
};

/* i2c驱动结构体 */	
static struct i2c_driver ft5x06_ts_driver = {
	.driver = {
		.owner = THIS_MODULE,
		.name = "edt_ft5x06",
		.of_match_table = of_match_ptr(ft5x06_of_match),
	},
	.id_table = ft5x06_ts_id,
	.probe    = ft5x06_ts_probe,
	.remove   = ft5x06_ts_remove,
};


/*设备入口函数*/
static int __init ft5x06_init(void)
{
    int ret=0;
    ret=i2c_add_driver(&ft5x06_ts_driver);
    return ret;
}

/*设备出口函数*/
static void __exit ft5x06_exit(void)
{
    i2c_del_driver(&ft5x06_ts_driver);
}

module_init(ft5x06_init);
module_exit(ft5x06_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LIU");

2. 中断和复位

  1. 设备结构体
struct ft5426_dev
{
	struct device_node	*nd; 				/* 设备节点 		*/
	int irq_pin,reset_pin;					/* 中断和复位IO		*/
	int irqnum;								/* 中断号    		*/
	void *private_data;						/* 私有数据 		*/
	struct i2c_client *client;				/* I2C客户端 		*/
};
  1. probe 函数

复位初始化

/* 初始化复位*/
static int ft5x06_ts_reset(struct i2c_client *client, struct ft5x06_dev *dev)
{
	int ret = 0;

	if (gpio_is_valid(dev->reset_pin)) {  		/* 检查IO是否有效 */
		/* 申请复位IO,并且默认输出低电平 */
		ret = devm_gpio_request_one(&client->dev,	
					dev->reset_pin, GPIOF_OUT_INIT_LOW,
					"edt-ft5x06 reset");
		if (ret) {
			return ret;
		}

		msleep(5);
		gpio_set_value(dev->reset_pin, 1);	/* 输出高电平,停止复位 */
		msleep(300);
	}

	return 0;
}

中断处理函数

/*中断处理函数*/
static irqreturn_t ft5x06_handler(int irq, void *dev_id)
{
    printk("ft5x06_handler\r\n");
     return IRQ_HANDLED;
}

中断初始化

static int ft5x06_ts_irq(struct i2c_client *client, struct ft5x06_dev *dev)
{
	int ret = 0;

	/* 1,申请中断GPIO */
	if (gpio_is_valid(dev->irq_pin)) {
		ret = devm_gpio_request_one(&client->dev, dev->irq_pin,
					GPIOF_IN, "edt-ft5x06 irq");
		if (ret) {
			dev_err(&client->dev,
				"Failed to request GPIO %d, error %d\n",
				dev->irq_pin, ret);
			return ret;
		}
	}

	/* 2,申请中断,client->irq就是IO中断, */
	ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
					ft5x06_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
					client->name, &ft5x06);
	if (ret) {
		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
		return ret;
	}

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/686665.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SikuliX 实战

一. SikuliX是什么 SikuliX的前身是 Sikuli。Sikuli是由MIT&#xff08;麻省理工学院&#xff09;研究团队发布的一种基于OpenCV图像识别技术的自动化工具软件。 Sikuli 是2009 年由在麻省理工学院用户界面设计小组作为一个开源研究项目&#xff0c;负责人分别是Tsung-Hsiang …

42 # 前端 blob 类型

前端的二进制 文件类型 Blob&#xff1a;二进制文件类型input 的 typefile&#xff1a;file 类型&#xff0c;继承于 Blob 前端实现下载功能 实现下载字符串到文件里&#xff0c;需要将字符串包装成二进制类型 <!DOCTYPE html> <html lang"en"><h…

文字对话如何配音?安利你三款制作对话配音的软件

对话配音怎么配&#xff1f;安利三个好用的对话配音软件给你 一分钟告诉你对话配音怎么配 对话配音怎么配&#xff1f;超简单的对话配音制作教程来啦 对话配音软件有哪些&#xff1f;给你安利这三款对话配音软件 对话配音如何操作&#xff1f;分享你三个对话配音小技巧 在电…

想学PMP,有考过的同学给个建议嘛?

PMP中国和国外的考试形式略有不同&#xff0c;这里只介绍一下PMP中国考试的相关信息。 1.PMP考试相关信息 考试形式&#xff1a;笔试 考试时间&#xff1a;230分钟&#xff08;3小时50分钟&#xff09;&#xff0c;一般考试时间在上午9:00~12:50&#xff0c;也会因为特殊情况…

C++primer(第五版)第二章(变量和基本类型)

2.1基本内置类型 2.1.1算术类型 C的基本内置类型包括算数类型和空类型,空类型就是void,算术类型我从原书中截下来放在下面: 从上表我们可以得知C规定int至少和short一样大,long至少和int一样大,longlong至少和long一样大. 其中char(字符)类型支持国际化,所以char会确保可以放…

学Java还是学Android?如何选择?

学Java和学Android都有其各自的好处和应用场景。下面是一些关于学习Java和学习Android的信息&#xff0c;以帮助你做出选择&#xff1a;刚好我这里有嵌入式、plc、单片机的资料需要的在评论区扣6或私我 学习Java&#xff1a; Java是一种通用的编程语言&#xff0c;广泛应用于服…

Simulink自动把所有的double数据转换成single数据

目录 前言 子系统double自动转single操作步骤 总结 前言 在基于模型的开发建模中&#xff0c;模块大多默认的数据类型是double&#xff0c;很多MCU支持的是单精度的浮点&#xff0c;生成代码的部分需要把double转成single数据类型&#xff0c;当然在建模的时候可以配置每一…

GCP学习笔记(三)——存储和安全

文章目录 一、Cloud Storage二、Cloud Bigtable三、Cloud SQL四、Cloud Spanner五、Firestore六、Cloud Datastore七、安全1. Data Loss Prevention2. Stackdriver3. IAM 八、网络概述 在GCP中&#xff0c;我们需要序列化数据使数据能够进行存储和转换。Avro时一种数据序列化方…

清华唐杰新作WebGLM,参数100亿可联网

WebGLM是一个基于大语言模型&#xff08;LLM&#xff09;的联网问答聊天机器人&#xff0c;它的作者是清华大学计算机系唐杰教授团队&#xff0c;它的论文入选了KDD2023会议。 WebGLM的特点是它可以利用Web搜索和检索功能来增强LLM的能力和泛化性&#xff0c;从而实现一个高效、…

智驾产品价值逻辑变了,新一代智驾芯片的核心要求

“根据创新扩散理论&#xff0c;智能汽车的早期用户主要是‘发烧友’&#xff0c;但是真正起量需要依靠‘大众群体’。要想抓住智能驾驶普及的黄金增长机遇&#xff0c;必须捕捉到两个群体的差异化需求&#xff0c;理解行业规则的变化。在当下&#xff0c;智驾产品必须重视功能…

MySQL架构介绍

MySQL架构介绍 和其它数据库相比&#xff0c;MySQL有点与众不同&#xff0c;它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上&#xff0c;插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和…

【软考网络管理员】2023年软考网管初级常见知识考点(15)-网络管理与存储

涉及知识点 网络管理功能&#xff0c;网络管理模型&#xff0c;SNMP协议原理与版本&#xff0c;数据备份&#xff0c;DAS/NAS/SAN技术 软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 文章目录 涉及知识点一、网络管理功能二、…

容器访问外部网络之Linux ip_forward 数据包转发

文章目录 1 问题解决1.1 问题&#xff1a;1.2 原因&#xff1a;1.3 解决&#xff1a;临时打开&#xff1a;永久打开&#xff1a; 2 net.ipv4.ip_forward内核参数通俗解释3 在Linux中验证并实践net.ipv4.ip_forward设置 IP 地址设置路由信息打开 IP Forward 功能关闭主机 R 的防…

【LeetCode】动态规划 刷题训练(四)

文章目录 面试题 17.16. 按摩师(打家劫舍|)题目解析状态转移方程完整代码 213. 打家劫舍 II题目解析状态转移方程完整代码 740. 删除并获得点数题目解析预处理状态转移方程完整代码 面试题 17.16. 按摩师(打家劫舍|) 点击查看&#xff1a;按摩师 一个有名的按摩师会收到源源不…

【vue小知识】给DOM元素动态的添加上一个类||v-bind的妙用

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;vue文件怎么给DOM元素加上一个类 项目场景&#xff1a; 在前端页面逻辑操作中通常是存在click事件,添加点击效果是为了让页面操作起来更加的有操作性与互动性,那么有什么方式可以实现…

13个有趣的Python高级脚本!

关注“Python专栏”微信公众号&#xff0c;回复暗号【面试大全】&#xff0c;立即领取面试题简历模板。 每天我们都会面临许多需要高级编码的编程挑战。你不能用简单的 Python 基本语法来解决这些问题。在本文中&#xff0c;我将分享 13 个高级 Python 脚本&#xff0c;它们可以…

IP路由选择过程

1.1路由选择基础 路由选择是指将分组从一个设备通过互联网络发往位于不同网络上的另一个设备的操作。路由器不关注网络中的主机&#xff0c;而只关注互联起来的网络以及通往各个网络的最佳路径。 目标主机的逻辑网络地址用来获取通过可路由网络传送到指定网络中的分组&#xf…

(一)CSharp-Socket

一、套接字 Windows Sockets 只支持一个通信域&#xff1a;网际域&#xff08;AF-INET&#xff09;&#xff0c;这个域被使用网际协议族通信的进程所使用。 TCP/IP 的 Socket 则提供3种类型的套接字 1、流式套接字&#xff08;SOCK_STREAM&#xff09; 提供面向连接、可靠的数…

STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045

STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045 Proteus仿真小实验&#xff1a; STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045 功能&#xff1a; Protues版本&#xff1a;8.9 硬件组成&#xff1a;STM32F103R6单…

gif格式怎么转换成mp4? 这两个方法实用方便!

GIF&#xff08;Graphics Interchange Format&#xff09;文件是一种常见的动态图像格式&#xff0c;而MP4&#xff08;MPEG-4 Part 14&#xff09;则是一种流行的视频文件格式。有时候&#xff0c;您可能想要将GIF文件转换为MP4格式&#xff0c;以便在不同的平台和设备上进行更…