写点什么

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

作者:DS小龙哥
  • 2022 年 4 月 07 日
  • 本文字数:2754 字

    阅读完需:约 9 分钟

1. 前言

这篇文章介绍在 Linux 下如何编写 FT5X06 系列芯片驱动,完成触摸屏的驱动开发, FT5X06 是一个系列,当前使用的具体型号是 FT5206,它是一个电容屏的触摸芯片,内置了 8 位的单片机(8051 内核),完成了坐标换算等很多处理,在通过 IIC,SPI 方式传递给外部单片机。



所说起触摸屏大家都不会陌生,现在手机、手表、家电、很多地方都支持触摸了。最开始的触摸屏都是电阻屏,在诺基亚时代的时候,使用的触摸屏都是电阻屏,后来 Android 兴起的时候,手机都向电容屏发展了。电阻屏需要自己去校准,电阻屏的手机上都有这个功能,发现触摸不灵敏之后,打开校准选项,根据屏幕上十字图标指引,按顺序点一下,完成坐标校准,电阻屏的屏幕还是软材质,必须要手指去戳才可以完成控制,而且只能支持单点触控。现在电容屏就很方便了,只需要手指去触摸屏即可完成操作,比电阻屏方便很多,还支持多点触控,当初 Android 手机刚兴起的时候,大街小巷的体验店,广告都是切水果游戏,切水果这个游戏就充分体验了多点触摸的效果,可以多个手指去切水果,当初这个游戏还是火爆的。


当前文章介绍的 FT5206 就是一颗电容屏的驱动芯片,最高支持 2 点触控,可以通过获取两个坐标点,这个系列的芯片最高支持 10 点触控。


当前使用的屏幕型号是 S702,这个屏幕是友善之臂生产的 LCD 屏,S702 这款屏幕采用的触摸芯片就是 FT5206,引出了 IIC 接口,支持笔中断,官方的内核里也提供了例子驱动可以参考。


开发板与触摸芯片的连线示例:



屏幕的实物图详情看下图的介绍:


2. FT5206 寄存器介绍

FT5206 支持通过 IIC 和 SPI 接口与外部主机通信,当前使用的屏幕硬件上只是引出了 IIC 接口,下面就介绍下 IIC 接口的时序,设备地址,还有 FT5206 的寄存器。


IIC 传输时序:



读写时序流程:



字段的解释:



下面的截图是介绍 FT5206 内部的寄存器地址,一些关键的地方我做了翻译:




从图上可以看出,基本上后面的寄存器地址都是重复的功能,只是坐标点不一样了,其中的 TOUCH2,TOUCH3.......这些都是存放触摸屏的坐标点的值。当前的 FT5206 只是支持 2 点触控,所有就只能读取两个寄存器坐标的值。在前面第一个寄存器 TD_STATUS 里的低 4 位,存放了当前同时按下的点数量,可以将两个手指按在屏幕上测试读取的值。 这些寄存器里读取的坐标值就是已经转换过后的值,也就是屏幕坐标,不需要再进行二次转换校准,非常方便。

3. 编写触摸屏驱动

Linux 下编写标准的触摸屏驱动需要使用到输入子系统,当前文章的重点是读取触摸屏的坐标,所以示例代码里不会加输入子系统的代码,只是在驱动层完成触摸屏笔中断响应,触摸屏的坐标点获取并打印。


驱动代码里涉及的技术点有: IIC 子系统、工作队列、内核中断等知识点。


这是开发板 LCD 屏幕的硬件原理图:


3.1 设备端代码(FT5206)

#include <linux/kernel.h>#include <linux/module.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/gpio.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <linux/i2c.h>
#define DEVICE_NAME "FT5X06_DEV"
static struct i2c_adapter *iic_adapter;static struct i2c_client *iic_client;static struct i2c_board_info iic_info;
static int __init iic_dev_init(void){ /*1. 根据总线编号获取IIC适配器结构体*/ iic_adapter=i2c_get_adapter(1); /*2. 填充板级信息*/ iic_info.addr=0x38; iic_info.irq=gpio_to_irq(EXYNOS4_GPX1(6)); strcpy(iic_info.type,DEVICE_NAME); /*3. 注册IIC设备端*/ iic_client=i2c_new_device(iic_adapter,&iic_info); printk("IIC设备端驱动安装成功.\n"); return 0;}

static void __exit iic_dev_exit(void){ /*1. 完成设备端注销*/ i2c_unregister_device(iic_client); printk("IIC设备端驱动卸载成功.\n");}
/*驱动的入口:insmod xxx.ko*/module_init(iic_dev_init);/*驱动的出口: rmmod xxx.ko*/module_exit(iic_dev_exit);/*模块的许可证*/MODULE_LICENSE("GPL");/*模块的作者*/MODULE_AUTHOR("wbyq");
复制代码

3.2 驱动端代码

#include <linux/kernel.h>#include <linux/module.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/gpio.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <linux/i2c.h>#include <linux/interrupt.h>#include <linux/workqueue.h>
static struct work_struct touch_work;static struct i2c_client *touch_client;
/*工作函数*/void tiny4412_touch_work_func(struct work_struct *work){ u8 touch_buff[7]; u16 x,y; /*1. 读取坐标数据*/ i2c_smbus_read_i2c_block_data(touch_client,0,7,touch_buff); /*2. 打印数据*/ x=(touch_buff[3]&0xF)<<8|touch_buff[4]; y=(touch_buff[5]&0xF)<<8|touch_buff[6]; printk("x=%d,y=%d,p=%d\n",x,y,touch_buff[2]&0xF);}
/*中断的服务函数*/irqreturn_t tiny4412_touch_irq_handler(int irq, void *dev){ /*调度工作: 将工作加入到工作队列*/ schedule_work(&touch_work); return IRQ_HANDLED;}
static int iic_probe(struct i2c_client *client, const struct i2c_device_id *dev_id){ printk("设备地址:0x%X\n",client->addr); printk("设备名称:%s\n",client->name);
touch_client=client; /*1. 初始化工作队列*/ INIT_WORK(&touch_work,tiny4412_touch_work_func); /*2. 注册中断*/ request_irq(client->irq,tiny4412_touch_irq_handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,client->name,NULL);
return 0;}
static int iic_remove(struct i2c_client *client){ /*1. 注销中断*/ free_irq(client->irq,NULL); return 0;}
static struct i2c_device_id iic_dev_id[]={ {"FT5X06_DEV",0}, {}};
static struct i2c_driver iic_driver={ .probe=iic_probe, .remove=iic_remove, .driver= { .name="iic_driver" }, .id_table=iic_dev_id};
static int __init iic_drv_init(void){ /*1. 注册IIC驱动端*/ i2c_add_driver(&iic_driver); printk("驱动安装成功.\n"); return 0;}
static void __exit iic_drv_exit(void){ /*2. 注销IIC驱动端*/ i2c_del_driver(&iic_driver); printk("驱动卸载成功.\n");}
/*驱动的入口:insmod xxx.ko*/module_init(iic_drv_init);/*驱动的出口: rmmod xxx.ko*/module_exit(iic_drv_exit);/*模块的许可证*/MODULE_LICENSE("GPL");/*模块的作者*/MODULE_AUTHOR("wbyq");
复制代码


发布于: 刚刚阅读数: 2
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
Linux驱动开发-编写FT5X06触摸屏驱动_4月月更_DS小龙哥_InfoQ写作平台