100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 迅为嵌入式linux驱动开发笔记(十一)—触摸屏驱动

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

时间:2020-09-09 08:34:19

相关推荐

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

总结篇

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

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");

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。