总结篇

这一小节内容是对之前学习的十节课进行总复习,综合性非常强,完成触摸屏驱动需要学会如下知识:
1、驱动开发原理
第一节

2、platform平台总线模型
第三节

3、设备树
第四节

4、gpio子系统
第五节

5、中断原理
第六节

6、工作队列
第七节

7、input子系统
第九节

8、iic驱动原理
第十节

为了清晰描述触摸屏驱动实验,对代码每一句进行详细注释:

触摸屏驱动代码

#include<linux/init.h>
/*驱动模块*/
#include<linux/module.h>
/*IIC*/
#include <linux/i2c.h>
/*GPIO*/
#include <linux/gpio.h>
/*of函数获取gpio*/
#include <linux/of_gpio.h>
/*of函数获取中断*/
#include <linux/of_irq.h>
/*中断*/
#include <linux/interrupt.h>
/*输入子系统*/
#include <linux/input.h>
/*延时函数*/
#include <linux/delay.h>
/*工作队列*/
#include <linux/workqueue.h>
/*初始化设备节点*/
struct device_node *ft5x06_device_node;
/*定义设备编号*/
#define DEVICE_NODE 0X00
/*屏幕设备寄存器地址*/
#define ID_G_MODE 0Xa4
/*定义中断号*/
int irq;
/*定义输入子系统设备*/
static struct input_dev *ft5x06_dev;
/*定义IIC适配器*/
static struct i2c_client *ft5x06_client;
/*声明IIC写函数*/
static void ft5x06_write_reg(u8 reg_addr,u8 data,u8 len);
/*中断入口函数*/
static void ft5x06_func(struct work_struct *work);
/*初始化工作队列*/
DECLARE_WORK(ft5x06_work,ft5x06_func);/*定义IIC写函数*/
static void ft5x06_write_reg(u8 reg_addr,u8 data,u8 len)
{/*定义缓冲区大小*/u8 buff[256];/*初始化i2c_msg结构体*/struct i2c_msg msgs[] = {[0] = {/*主机地址*/.addr = ft5x06_client->addr,/*0为写*/.flags = 0,/*读取长度*/.len = len+1,/*缓存区的地址*/.buf = buff,}};/*存放寄存器的地址*/buff[0] = reg_addr;/*拷贝len字节的数据长度到buff[1]之后位置*/memcpy(&buff[1],&data,len);/*iic数据包传送,参数1:适配器,参数2:数据包,参数3:数量*/i2c_transfer(ft5x06_client->adapter,msgs,1);
}/*定义IIC读函数*/
static int ft5x06_read_reg(u8 reg_addr)
{/*定义读出数据的返回值*/u8 data;/*封装结构体*/struct i2c_msg msgs[] = {[0] = {/*主机地址*/.addr = ft5x06_client->addr,/*flags为0表示写入*/.flags = 0,/*读出字节长度*/.len = sizeof(reg_addr),/*读取函数的地址*/.buf = &reg_addr,},[1] = {.addr = ft5x06_client->addr,.flags = 1,.len = sizeof(data),.buf = &data,}};/*iic数据包传送,参数1:适配器,参数2:数据包,参数3:数量为2*/i2c_transfer(ft5x06_client->adapter,msgs,2);/*返回读取到的数据*/return data;}static const struct i2c_device_id ft5x06_id_ts[] = {{"xxx",0},{}
};static const struct of_device_id ft5x06_id[] =
{{.compatible = "edt,edt-ft5306",0,},{.compatible = "edt,edt-ft5x06",0,},{.compatible = "edt,edt-ft5406",0,},{}};static void ft5x06_func(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);//只想要12位,获取到X的坐标值x = ((TOUCH1_XH<<8)|TOUCH1_XL)&0x0fff;//读取TOUCH1_YH寄存器的值TOUCH1_YH = ft5x06_read_reg(0x05);//读取TOUCH1_XL寄存器的值TOUCH1_YL = ft5x06_read_reg(0x06);//只想要12位,获取到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,x);input_sync(ft5x06_dev);//上报完成}}static irqreturn_t ft5x06_handler(int irq,void* args)
{//启动中断下文schedule_work(&ft5x06_work);return IRQ_HANDLED;
}int ft5x06_probe(struct i2c_client *client,const struct i2c_device_id *id)
{/*定义返回值*/int ret;/*定义中断引脚*/int ft5x06_irq_gpio;/*定义复位引脚*/int ft5x06_reset_gpio;/*打印函数*/printk("ft5x06_probe\n");/*因为要在别的地方用到client,所以要把他复制出来*/ft5x06_client = client;/*设备树位置,根据设备树信息查找屏幕挂载的位置信息,获得触摸芯片的节点*/ft5x06_device_node = of_find_node_by_path("/soc/aips-bus@02100000/i2c@021a4000/edt-ft5x06@38");/*出错判断*/if (ft5x06_device_node == NULL){printk("of_find_node_by_path is error\n");return -1;}printk("ft5x06_device_node is %s \n",ft5x06_device_node->name);/*获得中断引脚的GPIO编号——节点名称,IO名称,第几个*/ft5x06_irq_gpio = of_get_named_gpio(ft5x06_device_node,"irq-gpios",0);/*出错判断*/if (ft5x06_irq_gpio<0){printk("ft5x06_irq_gpio of_get_namd_gpio is error\n");return -2;}/*获得复位引脚的GPIO编号——节点名称,IO名称,第几个*/ft5x06_reset_gpio = of_get_named_gpio(ft5x06_device_node,"reset-gpios",0);/*出错判断*/if (ft5x06_reset_gpio<0){printk("ft5x06_reset_gpio of_get_namd_gpio is error\n");return -3;}printk("ft5x06_irq_gpio is %d \n",ft5x06_irq_gpio);printk("ft5x06_reset_gpio is %d \n",ft5x06_reset_gpio);/*避免申请失败*/gpio_free(ft5x06_irq_gpio);/*申请中断引脚*/ret = gpio_request(ft5x06_irq_gpio,"irq_gpio");/*出错判断*/if (ret<0){printk("gpio_request is error\n");return -4;}/*申请复位引脚*/ret = gpio_request(ft5x06_reset_gpio,"reset_gpio");if (ret < 0){printk("gpio_request is error\n");return -5;}/*设置中断引脚为输入*/gpio_direction_input(ft5x06_irq_gpio);/*操作一下复位的引脚,设置方向为输出,然后停止复位*/gpio_direction_output(ft5x06_reset_gpio,0);msleep(5);/*设置输出为高电平*/gpio_set_value(ft5x06_reset_gpio,1);/*获取中断号*/irq = gpio_to_irq(ft5x06_irq_gpio);/*中断号、触发方式、中断名称、传递参数*/ret = request_irq(irq,ft5x06_handler,IRQ_TYPE_EDGE_FALLING|IRQF_ONESHOT,"ft5x06_irq",NULL);/*出错判断*/if (ret<0){printk("requset_irq is error\n");goto error_requset_irq;}/*工作模式为正常模式:地址:写入数据:数据长度*/ft5x06_write_reg(DEVICE_NODE,0,1);/*工作模式为中断模式:地址:写入数据:数据长度*/ft5x06_write_reg(ID_G_MODE,1,1);/*输入子系统申请设备*/ft5x06_dev = input_allocate_device();/*初始化设备名称*/ft5x06_dev->name = "ft5x06_input_test";/*支持按键事件*/__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);input_set_abs_params(ft5x06_dev,ABS_X,0,1024,0,0);/*设置Y坐标*/input_set_abs_params(ft5x06_dev,ABS_Y,0,600,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");goto error_input_register;}return 0;/*错误处理*/
error_requset_irq:free_irq(irq,NULL);  /*错误处理*/
error_input_register:/*释放中断*/free_irq(irq,NULL);/*注销设备*/input_unregister_device(ft5x06_dev);/*是否输入子系统*/input_free_device(ft5x06_dev);return ret;
}/*remove函数*/
int ft5x06_remove(struct i2c_client *i2c_client)
{return 0;
}/*初始化i2c_driver结构体*/
static struct i2c_driver ft5x06_driver = { /*必须初始化的成员*///int (*probe)(struct i2c_client *, const struct i2c_device_id *);  //int (*remove)(struct i2c_client *); //struct device_driver driver; //const struct i2c_device_id *id_table;/*driver成员初始化*/.driver = {/*表示当前模块下*/.owner = THIS_MODULE,/*驱动名称*/.name = "ft5x06_test",/*匹配id名称*/.of_match_table = ft5x06_id,},/*probe函数*/.probe = ft5x06_probe,/*remove函数*/.remove = ft5x06_remove,/*设备名称匹配*/.id_table = ft5x06_id_ts}; /*驱动初始化*/
static int ft5x06_driver_init(void)
{/*返回值定义*/int ret;/*添加iic驱动*/ret = i2c_add_driver(&ft5x06_driver);/*出错判断*/if (ret < 0){printk("i2c_add_driver is error\n");return ret;}printk("i2c_add_driver init\n");return 0;
}/*定义驱动退出函数*/
static void ft5x06_driver_exit(void)
{/*删除iic设备*/i2c_del_driver(&ft5x06_driver);/*释放中断*/free_irq(irq,NULL);/*注销输入子系统*/input_unregister_device(ft5x06_dev);/*释放设备*/input_free_device(ft5x06_dev);printk("i2c_del_driver exit\n");}
/*模块初始化*/
module_init(ft5x06_driver_init);
/*模块退出*/
module_exit(ft5x06_driver_exit);
MODULE_LICENSE("GPL");

迅为嵌入式linux驱动开发笔记(十一)—触摸屏驱动相关推荐

  1. 嵌入式Linux系统开发笔记(七)

    嵌入式Linux系统开发笔记(七) 七.U-Boot基础 1.概述 在移植 Linux之前我们需要先移植一个 bootloader 代码,这个 bootloader 代码用于启动 Linux 内核, ...

  2. 嵌入式Linux系统开发笔记(二)

    嵌入式Linux系统开发笔记(二) 二.Linux C 编程 1.设置VI编辑器TAB 键为 4 字节 VI 编辑器默认 TAB 键为 8 空格,我们改成 4 空格,用 vi 打开文件/etc/vim ...

  3. STM32MP157驱动开发——多点电容触摸屏驱动

    STM32MP157驱动开发--多点电容触摸屏驱动 一.简介 二.电容触摸屏驱动框架简介 多点触摸(MT)协议详解 三.驱动开发 1.添加 FT5426 设备节点 2.FT5426 节点配置 3.驱动 ...

  4. 嵌入式linux备份flash,嵌入式Linux裸机开发(十一)——Nandflash

    嵌入式Linux裸机开发(十一)--Nandflash 一.Nand Flash简介 NandFlash是Flash的一种,具有容量较大,改写速度快等优点,适用于大量数据的存储.NandFlash没有 ...

  5. 嵌入式Linux系统开发笔记(十五)

    Linux内核启动验证 5.1 编译内核 # 清除工程 # make distclean # 配置工程 make imx_atk_mfg_defconfig # 打开图形配置界面,对 Linux 进行 ...

  6. Linux驱动学习笔记之触摸屏驱动

    触摸屏归纳为输入子系统,这里主要是针对电阻屏,其使用过程如下 当用触摸笔按下时,产生中断. 在中断处理函数处理函数中启动ADC转换x,y坐标. ADC结束,产生ADC中断 在ADC中断处理函数里上报( ...

  7. RK3399驱动开发 | 06 - GT911触摸屏驱动调试及驱动浅析(Linux 5.4内核)

    更新内容 更新时间 完成初稿 2022-09-21 文章目录 一.GT911 1. 触摸芯片 2. 原理图 二.驱动调试 1. 测试gt911是否正常通信 2. 添加驱动 3. 添加设备树描述 4. ...

  8. RK3399驱动开发 | 07 - GT911触摸屏驱动调试及问题分析解决(基于RK SDK Linux 4.4.194内核)

    更新内容 更新时间 完成初稿 2022-09-21 文章目录 一.GT911 1. 触摸芯片 2. 原理图 二.驱动调试 1. 测试gt911是否正常通信 2. 添加驱动 3. 添加设备树描述 4. ...

  9. 迅为嵌入式Linux学习笔记4——进程

    迅为嵌入式Linux学习笔记4--进程 进程指的是正在运行的程序,是操作系统分配资源的最小单位. 进程ID 每个进程都有唯一的标识符,这个标识符就是进程ID,简称pid 进程间通信的方法 管道通信:分 ...

  10. 迅为嵌入式Linux学习笔记5——进程间通信

    迅为嵌入式Linux学习笔记5--进程间通信 管道通信 无名管道 无名管道只能实现有亲缘关系的进程之间的通信,比如父子进程. pipe函数: #include <unistd.h> int ...

最新文章

  1. (chap6 Http首部) 通用首部字段 Connection
  2. Python中shuffle() 函数的作用及用法
  3. 操作系统(十六)调度算法(一)
  4. 《走出软件作坊》读后感
  5. python中如何快速注释_python中如何快捷添加注释
  6. Facebook开源了两个无监督翻译模型,只用单语就能训练双语
  7. 加载JDBC驱动程序
  8. Linux MPLS 总结
  9. glDeleteTextures函数对内存的优化
  10. LPC1788系统时钟的设置
  11. 51nod方程的解数 1436
  12. 计算机再带word打不开,电脑上 word打不开怎么办(精选).doc
  13. BD-rate计算原理
  14. 2023年全国最新工会考试精选真题及答案3
  15. 三星S7edge从8.0降到6.0.1,只为流畅的飞一般的感觉
  16. 【正点原子MP157连载】第一章 Ubuntu系统安装-摘自【正点原子】【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
  17. SVG实现超酷素描动画
  18. cocos和Unity3d 图集
  19. odb格式Linux,AD如何输出ODB++文件的格式?
  20. 5.OpenCV基础

热门文章

  1. 程序的两种执行方式,静态语言和脚本语言
  2. Java例:计算某年某月有多少天
  3. 华为Nova 4 HL1VCEM (VCE-L22/VCE-AL00)手机图纸电路原理图+主板高清图片
  4. 文本型数字转化为数值的6个公式
  5. [摄影写真工作室网站模板]织梦模板+响应式模特艺术展示类网站+自适应手机版
  6. TCP协议及三次握手的过程
  7. 【Python】Scrapy完成电影信息爬取并存入数据库
  8. Python 之 格式化输出
  9. ~4.1 剑指 Offer 05. 替换空格
  10. *6-2 CCF 2015-03-3 节日