个人总结之触摸屏调式(ILITEK系列)

2024-03-25 00:10

本文主要是介绍个人总结之触摸屏调式(ILITEK系列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

项目场景:

需要在安卓系统屏幕上增加一块触摸屏,实现该触摸功能,本项目使用的是ILITEK251系列IC采集触摸屏的点位数据,通过LVDS串行解串芯片传输,基于芯驰X9系列SOC平台实现。

一、软硬件框架

框架示意图
SOC:该芯片是一款多核异构的SOC,R5核跑的是传统的轻量级OS,例如freeRTOS等轻量级系统,A核可以跑像安卓、linux等多任务系统,这种生态的好处是R5核可以满足实时性的要求,同时A核可以实现高处理能力以及多生态环境,多核之间的通信原理是基于寄存器和中断,在共享内存中实现跨系统的数据访问。目前主流的通信实现采用Virtio下的RPMsg。更详细的可以自行去官网查看理解。

串行解串器:用一对差分信号线实现短距离的数据串行传输。一般是成对匹配使用,芯片和SOC之间采用IIC的协议通信,串行器,解串器分别可以看成是两个设备,挂在一条IIC的总线上。串行解串芯片内部自带中断控制INT,还会集成其他外设,例如LVDS、I2S、通用可透传的GPIO、SPI等等。

ILITEK:该触摸IC是负责采集触摸屏的报点数据,然后触发中断,中断通过解串器,由LINK传回串行器,硬件上串行器INT连接SOC的GPIO,配置GPIO为外部中断触发告知SOC。本项目中,由SOC通过IIC配置串行器的寄存器,实现触摸IC在IIC总线上的挂载,然后在SOC通过IIC对该IC芯片的寄存器读写,既一条IIC总线上挂载三个设备,串行器、解串器以及触摸IC。

二、驱动移植

1、首先对设备树进行配置:

&i2c8 {status = "okay";ilitek:ilitek@41 {compatible = "tchip,ilitek";//设备和驱动根据compatible属性配对reg = <0x41>;				//设备的I2C地址ilitek,irq-gpio = <&port4d 12 0x0>;//外部中断号108ilitek,vbus = "vcc_i2c";	//一些设备信息的描述ilitek,vdd = "vdd";ilitek,name = "ilitek_i2c";};
};

在具体的dts文件中,引用&i2c8,然后status使能okay,证明开启该节点与驱动进行配对,如果为disabled则不启动配对

i2c8: i2c@30b00000 {/*compatible = "snps,designware-i2c";*/compatible = "sd,virtual-i2c";//使用虚拟i2c连接R5核phy-num = /bits/ 8 <8>;reg = <0x0 0x30b00000 0x0 0x1000>;interrupts = <0 40 4>;#address-cells = <1>;#size-cells = <0>;clocks=<&I2C_SEC0_9>;clock-names = "i2c-clk";#clock-frequency = <100000>;timeout = <10>; /* ms */status = "disabled";};

修改原厂i2c8的设备树描述信息,因为实际的i2c8总线控制已经挂到R5核上,所以我们这里不使用实际的IIC总线,而是注册一个虚拟的IIC总线控制模拟器,会匹配另外一个虚拟化的IIC驱动,由这个控制器传递IIC通信数据给到R5核上实际对应的IIC驱动,然后发往设备端.

2、移植驱动文件到指定的内核目录下,对于触摸屏驱动,linux内核下有专门的输入子系统,该路径为/drivers/input/touchscreen,,修改input目录下的makefile
注释: #obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
增加:obj-y += touchscreen/
我这里为了方便调试,直接使用obj-y来使能编译 touchscreen/下的文件,正常的话应该make menuconfig来配置CONFIG_INPUT_TOUCHSCREEN = y
然后在 touchscreen/创建一个文件夹ilitek,修改touchscreen/下的makefile
增加:obj-y += ilitek/ 使能编译该目录下的文件,然后将驱动文件放入该目录下,清除内核输出信息,重新编译即可

三、驱动代码部分解析

static int __init ilitek_touch_driver_init(void)
{tp_msg("add ILITEK touch device driver\n");return i2c_add_driver(&ilitek_touch_device_driver);  //加入I2C总线匹配
}static void __exit ilitek_touch_driver_exit(void)
{tp_msg("remove touch device driver i2c driver.\n");#ifdef ILITEK_SPI_INTERFACEspi_unregister_driver(&ilitek_touch_device_driver);
#elsei2c_del_driver(&ilitek_touch_device_driver);
#endif
}
#endifmodule_init(ilitek_touch_driver_init);		//平台模块注册入口函数
module_exit(ilitek_touch_driver_exit);
MODULE_AUTHOR("ILITEK");
MODULE_LICENSE("GPL");``static struct i2c_driver ilitek_touch_device_driver = {
#endif.driver = {.name = ILITEK_TS_NAME,.owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = ilitek_touch_match_table,  //设备树的匹配表
#endif},.probe = ilitek_touch_driver_probe,								//如果驱动和设备配对成功则调用该函数.remove = ilitek_touch_driver_remove,};#ifdef CONFIG_OF
static struct of_device_id ilitek_touch_match_table[] = {{.compatible = "tchip,ilitek",},	//该信息要与设备树描述的compatible属性一致{},
};
#endifstatic int ilitek_touch_driver_probe(struct i2c_client *client,const struct i2c_device_id *id)
{if (!client) {tp_err("i2c client is NULL\n");return -ENODEV;}return ilitek_main_probe(client, &client->dev); //匹配成功以后执行主线函数
}

则选ilitek_main_probe函数中部分功能分析

int ilitek_main_probe(void *client, struct device *device)
{.......if (!(ts = kzalloc(sizeof(*ts), GFP_KERNEL))) {  //分配一块内存tp_err("allocate ts failed\n");return -ENOMEM;}ilitek_request_gpio();//注册一个外部的中断iots->dev = ilitek_dev_init(interface_i2c, &dev_cb, ts);//对ts结构注册一个回调函数集if (!ts->dev)goto err_free_gpio;ts->process_and_report = ilitek_read_data_and_report_3XX; //中断下半部执行函数ts->irq_trigger_type = IRQF_TRIGGER_FALLING;			  //下降沿触发if (ilitek_request_irq())//注册中断,申请一个软件中断号goto err_dev_exit;......ilitek_create_sysfsnode(); //在/sys/下创建信息节点ilitek_create_tool_node();//在/proc/下创建信息节点ilitek_init_netlink();//创建一个netlink,用于应用和驱动之间的通信......return 0;err_free_irq:free_irq(ts->irq, ts);err_dev_exit:ilitek_dev_exit(ts->dev);err_free_gpio:ilitek_free_gpio();kfree(ts);return -ENODEV;
}

看下中断函数的注册则选

static int ilitek_request_irq(void)
{int error;ts->irq = gpio_to_irq(ts->irq_gpio);//将GPIO号转换......tp_msg("ts->irq: %d\n", ts->irq);if (ts->irq <= 0)return -EINVAL;//方法一、中断注册函数,内核线程注册方法/*error = request_threaded_irq(ts->irq, NULL, ilitek_i2c_isr,ts->irq_trigger_type | IRQF_ONESHOT,"ilitek_touch_irq", ts);*///方法二、这是中断注册函数方法,配合工作队列error = request_irq(ts->irq, ilitek_i2c_isr, ts->irq_trigger_type, "ilitek_touch_irq", ts);	 if (error) {tp_err("request threaded irq failed, err: %d\n", error);return error;}//由于之前调试出点问题,怀疑过是不是方法一有问题,所以注册了一个工作队列代替//初始化一个工作队列INIT_WORK(&ts->my_workqueue,autofure_work);ts->irq_registerred = true;atomic_set(&ts->irq_enabled, 1);return 0;
}

看下中断下半部则选

int ilitek_read_data_and_report_3XX(void)
{......ts->buf[0] = 0x10;ret = ilitek_write_and_read(ts->buf, 1, 1, ts->buf, 32);//接收IIC过来的数据包if (ret < 0) {tp_err("get touch information err\n");if (ts->is_touched) {ilitek_touch_release_all_point();ilitek_check_key_release(x, y, 0);}return ret;}......//取出数据包中x y的坐标x = ((ts->buf[i * 5 + 1] & 0x3F) << 8) + ts->buf[i * 5 + 2];y = (ts->buf[i * 5 + 3] << 8) + ts->buf[i * 5 + 4];if (!(ts->touch_key_hold_press)) {if (ILITEK_REVERT_X)x = ts->dev->screen_info.x_max - x + ts->dev->screen_info.x_min;if (ILITEK_REVERT_Y)y = ts->dev->screen_info.y_max - y + ts->dev->screen_info.y_min;//根据分辨率将x y坐标转换#ifdef ILITEK_USE_LCM_RESOLUTION  x = (x - ts->dev->screen_info.x_min) * TOUCH_SCREEN_X_MAX /(ts->dev->screen_info.x_max - ts->dev->screen_info.x_min);y = (y - ts->dev->screen_info.y_min) * TOUCH_SCREEN_Y_MAX /(ts->dev->screen_info.y_max - ts->dev->screen_info.y_min);#endifts->is_touched = true;tp_msg("Touch id=%02X, x: %04d, y: %04d\n", i, x, y);ilitek_touch_down(i, x, y, 10, 128, 1);//触摸过程的上报}......input_sync(input); //每次上报应用都要sync一下return 0;
}

四、调试异常和解决

1、IIC通信不成功:
刚开始的硬件连接是soc-串行器-解串器-触摸屏,发现IIC只能访问串行器-解串器,却读取不到触摸屏的设备地址,然后屏幕和触摸IC都换了一个发现还是不行,后面尝试跳线SOC直连到触摸IC,发现读取成功,那问题就是串行解串转换出了问题,然后排查到解串器的SDA 、SCL是上拉到1.8V,然后通过电平转换到3.3V到触摸IC(触摸IC是3.3V的上拉),看似没问题,将电平转换芯片去掉然后解串器的SDA 、SCL上拉到3.3V,通信成功!!后面排查可能原因是电平转换过程中电平不稳定导致的通信失败。

2、IIC通信过程中,读写长字节数据会出现错误的异常:
SOC在发送和接收触摸IC的数据过程中,读写一些几个字节的数据通信都是正常,例如获取版本号、设置工作模式等等,但是当触发中断接收长字节数据时,后面十几个字节开始收到的数据都是不正常的,一开始觉得是触摸IC厂发过来的数据包有问题(战略上拉扯了很久…),然后实在没办法,我叫硬件给我改回来直连SOC试试(之前硬件工程师觉得都可以访问到设备就证明是没问题),然后我坚定要改回来试试,一改发现直连触摸IC一点问题都没有…还是配对芯片的问题,后面排查发现解串器的SDA、SCL是上拉来10K电阻,然后根据数据手册和他们原厂支持改成2.2K,完美通信成功。

3、有部分触摸区域没反应:
触摸过程中边缘的一块区域没反应,触摸也不会产生下降沿中断,然后他们IC技术支持一直说是SOC驱动的问题,我就说你中断信号都过不来,我这边只是做数据处理,后面使用他们提供的画线工具,接上USB到windows下画线,发现同样没有反应,最后是他们提供一版新的触摸IC固件,烧录后成功解决。

五、总结

驱动的调试过程中,都会遇到各种各样意想不到的问题,有时候要发散思维,从多个点切入,将某个疑难问题分部解析来看待,调试与硬件相关的问题都是很考验人的,所以遇到这些问题的时候要冷静多角度去考虑。

最后,在安卓系统中完成触摸的功能,验证来点击区域的正确性。

这篇关于个人总结之触摸屏调式(ILITEK系列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/843253

相关文章

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi