日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

基于FT5x06嵌入式Linux电容触摸屏驱动

發布時間:2025/4/16 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于FT5x06嵌入式Linux电容触摸屏驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
***************************************************************************************************************************
作者:EasyWave ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 時間:2013.02.06

類別:Linux?內核驅動源碼分析??????????????????????????????????????????????????????聲明:轉載,請保留鏈接

注意:如有錯誤,歡迎指正。這些是我學習的日志文章......

***************************************************************************************************************************

一:FT5X06電容觸摸IC簡介

?????FT5x06系列ICs是單芯片電容式觸摸屏控制器IC,帶有一個內置的8位微控制器單元(MCU)。采用互電容的方法,在配合的相互的電容式觸摸面板,它支持真正的多點觸摸功能。FT5x06具有用戶友好的輸入的功能,這可以應用在許多便攜式設備,例如蜂窩式電話,移動互聯網設備,上網本和筆記本個人電腦。FT5x06系列IC包括FT5206/FT5306/FT5406。具體的功能如下圖所示:

?

二:硬件接口設計

從FT5X06的datasheet中,我們可以看到,FT5X06既可以工作的SPI的接口方式,也可以工作在I2C的接口方式,不管工作在SPI,還是工作在I2C,從硬件的接口設計上來說,這下面的幾個控制口,都是需要要接的。如下圖所示:

1):INT引腳,這個腳是一個中端信號,它用來通知HOST端FT5X06已經準備好,可以進行讀操作了。

2):WAKE引腳:這個功能主要的作用是將FT5X06從睡眠狀態轉換到工作狀態。

3):/RST引腳:FT5X06的芯片復位信號。

如何來設計硬件接口呢,這個我們可以從FT5X06的datasheet看出來,首先我們來看下FT5X06的上電時序,如下圖所示:

FT5X06的上電時序

FT5X06的RESET時序

FT5X06的wakeup時序

各自的最小的時間限制如下所所示:

因此,從上面的圖片和表格中,我們可以看出,在poweron中,必須確保在上電后,wakeup的電平為高電平,至于INT信號,只要確保無INT信號時,這個INT為高即可,這個可以從poweron的時序可以看出,它是一個低電平的動作,這個是驅動中來做的事情了。

接下來就是確定I2C的從地址,如下圖所示:[以下引用自網絡]

從地址高位必須為:3,低位必須根據i2ccon設定的值來確定。

根據FT5406數據手冊上的指令,我們先了解下驅動如何實現電容屏的多點觸摸,其實很簡單,主要需要觸摸屏IC FT5406 能夠捕獲多點數據,這點電容屏基本多能支持到捕獲2點以上,而FT5406 可以捕獲5個觸摸點,編寫驅動時,只要去獲取這幾個點的數據,然后上報就可以了。如下圖所示:[以下引用自網絡]

02H :捕獲的觸摸點個數????????????? 03H- 1EH?:對應每個點的x,y坐標數值。

?

三:Linux驅動源碼

??????? I2C的驅動需要根據具體的ARM芯片,一般來說,IC原廠,一般會將在linux的bsp中都會有I2C的驅動,這個部分不需要我們去寫的,我們只需要將FT5X06和BSP包中的I2C驅動匹配起來就好了。而整個FT5X06也是這樣做的。在linu內核中關于i2c的一般會有這個函數:i2c_board_info()i2c_board_info用于構建信息表來列出存在的I2C設備。這一信息用于增長新型I2C驅動的驅動模型樹。對于主板,它使用i2c_register_board_info()來靜態創建。對于子板,利用已知的適配器使用i2c_new_device()動態創建。

[cpp]?view plaincopyprint?
  • struct?i2c_board_info?{??
  • ????char?type[I2C_NAME_SIZE];????
  • ????unsigned?short?flags;????
  • ????unsigned?short?addr;????
  • ????void?*platform_data;????
  • ????struct?dev_archdata?*archdata;????
  • ????int?irq;????
  • };??
  • static?struct?i2c_board_info?i2c_devs0[]?__initdata?=?{??
  • #ifdef?CONFIG_TOUCHSCREEN_CDTLCD??
  • {??
  • I2C_BOARD_INFO("ft5x0x_ts",?0x3x),??
  • .irq?=?IRQ_EINT1,??
  • },??
  • #endif???
  • };??

  • 最后在內核初始化的部分調用int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);函數即可。如下詳細的解釋:
    @busnum: 指定這些設備屬于哪個總線
    @info: I2C設備描述符向量
    @len: 向量中描述符的數量;為了預留特定的總線號,可以是0。
    i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));


    下面貼出部分代碼:[下面的代碼是Android下的Linux驅動,如果要修改到通用的Linux內核中,需要修改代碼的]

    [cpp]?view plaincopyprint?
  • static?int???
  • ft5x0x_ts_probe(struct?i2c_client?*client,?const?struct?i2c_device_id?*id)??
  • {??
  • ????struct?ft5x0x_ts_data?*ft5x0x_ts;??
  • ????struct?input_dev?*input_dev;??
  • ????int?err?=?0;??
  • ????unsigned?char?uc_reg_value;???
  • #if?CFG_SUPPORT_TOUCH_KEY??
  • ????int?i;??
  • #endif??
  • ??????
  • ????printk("[FTS]?ft5x0x_ts_probe,?driver?version?is?%s.\n",?CFG_FTS_CTP_DRIVER_VERSION);??
  • ??????
  • ????if?(!i2c_check_functionality(client->adapter,?I2C_FUNC_I2C))?{??
  • ????????err?=?-ENODEV;??
  • ????????goto?exit_check_functionality_failed;??
  • ????}??
  • ??
  • ????ft5x0x_ts?=?kzalloc(sizeof(struct?ft5x0x_ts_data),?GFP_KERNEL);??
  • ????//ft5x0x_ts?=?kmalloc(sizeof(struct?ft5x0x_ts_data),?GFP_KERNEL);??
  • ????if?(!ft5x0x_ts)?{??
  • ????????err?=?-ENOMEM;??
  • ????????goto?exit_alloc_data_failed;??
  • ????}??
  • ????//memset(ft5x0x_ts,?0,?sizeof(struct?ft5x0x_ts_data));??
  • ??
  • ????this_client?=?client;??
  • ????i2c_set_clientdata(client,?ft5x0x_ts);??
  • ??
  • ????mutex_init(&ft5x0x_ts->device_mode_mutex);??
  • ????INIT_WORK(&ft5x0x_ts->pen_event_work,?ft5x0x_ts_pen_irq_work);??
  • ??
  • ????ft5x0x_ts->ts_workqueue?=?create_singlethread_workqueue(dev_name(&client->dev));??
  • ????if?(!ft5x0x_ts->ts_workqueue)?{??
  • ????????err?=?-ESRCH;??
  • ????????goto?exit_create_singlethread;??
  • ????}??
  • ??
  • ??
  • ????err?=?request_irq(IRQ_EINT(6),?ft5x0x_ts_interrupt,?IRQF_TRIGGER_FALLING,?"ft5x0x_ts",?ft5x0x_ts);??
  • ????if?(err?<?0)?{??
  • ????????dev_err(&client->dev,?"ft5x0x_probe:?request?irq?failed\n");??
  • ????????goto?exit_irq_request_failed;??
  • ????}??
  • ??
  • ??
  • ????disable_irq(IRQ_EINT(6));??
  • ??
  • ????input_dev?=?input_allocate_device();??
  • ????if?(!input_dev)?{??
  • ????????err?=?-ENOMEM;??
  • ????????dev_err(&client->dev,?"failed?to?allocate?input?device\n");??
  • ????????goto?exit_input_dev_alloc_failed;??
  • ????}??
  • ??????
  • ????ft5x0x_ts->input_dev?=?input_dev;??
  • ??
  • ????set_bit(ABS_MT_TOUCH_MAJOR,?input_dev->absbit);??
  • ????set_bit(ABS_MT_POSITION_X,?input_dev->absbit);??
  • ????set_bit(ABS_MT_POSITION_Y,?input_dev->absbit);??
  • ????set_bit(ABS_MT_WIDTH_MAJOR,?input_dev->absbit);??
  • ??
  • ????input_set_abs_params(input_dev,??
  • ?????????????????ABS_MT_POSITION_X,?0,?SCREEN_MAX_X,?0,?0);??
  • ????input_set_abs_params(input_dev,??
  • ?????????????????ABS_MT_POSITION_Y,?0,?SCREEN_MAX_Y,?0,?0);??
  • ????input_set_abs_params(input_dev,??
  • ?????????????????ABS_MT_TOUCH_MAJOR,?0,?PRESS_MAX,?0,?0);??
  • ????input_set_abs_params(input_dev,??
  • ?????????????????ABS_MT_WIDTH_MAJOR,?0,?200,?0,?0);??
  • ????input_set_abs_params(input_dev,??
  • ?????????????????ABS_MT_TRACKING_ID,?0,?5,?0,?0);??
  • ??
  • ??
  • ????set_bit(EV_KEY,?input_dev->evbit);??
  • ????set_bit(EV_ABS,?input_dev->evbit);??
  • ??
  • #if?CFG_SUPPORT_TOUCH_KEY??
  • ????//setup?key?code?area??
  • ????set_bit(EV_SYN,?input_dev->evbit);??
  • ????set_bit(BTN_TOUCH,?input_dev->keybit);??
  • ????input_dev->keycode?=?tsp_keycodes;??
  • ????for(i?=?0;?i?<?CFG_NUMOFKEYS;?i++)??
  • ????{??
  • ????????input_set_capability(input_dev,?EV_KEY,?((int*)input_dev->keycode)[i]);??
  • ????????tsp_keystatus[i]?=?KEY_RELEASE;??
  • ????}??
  • #endif??
  • ??
  • ????input_dev->name??????=?FT5X0X_NAME;??????//dev_name(&client->dev)??
  • ????err?=?input_register_device(input_dev);??
  • ????if?(err)?{??
  • ????????dev_err(&client->dev,??
  • ????????"ft5x0x_ts_probe:?failed?to?register?input?device:?%s\n",??
  • ????????dev_name(&client->dev));??
  • ????????goto?exit_input_register_device_failed;??
  • ????}??
  • ??
  • #ifdef?CONFIG_HAS_EARLYSUSPEND??
  • ????printk("==register_early_suspend?=\n");??
  • ????ft5x0x_ts->early_suspend.level?=?EARLY_SUSPEND_LEVEL_BLANK_SCREEN?+?1;??
  • ????ft5x0x_ts->early_suspend.suspend?=?ft5x0x_ts_suspend;??
  • ????ft5x0x_ts->early_suspend.resume??=?ft5x0x_ts_resume;??
  • ????register_early_suspend(&ft5x0x_ts->early_suspend);??
  • #endif??
  • ??
  • ????msleep(150);??//make?sure?CTP?already?finish?startup?process??
  • ??????
  • ????//get?some?register?information??
  • ????uc_reg_value?=?ft5x0x_read_fw_ver();??
  • ????printk("[FTS]?Firmware?version?=?0x%x\n",?uc_reg_value);??
  • ????ft5x0x_read_reg(FT5X0X_REG_PERIODACTIVE,?&uc_reg_value);??
  • ????printk("[FTS]?report?rate?is?%dHz.\n",?uc_reg_value?*?10);??
  • ????ft5x0x_read_reg(FT5X0X_REG_THGROUP,?&uc_reg_value);??
  • ????printk("[FTS]?touch?threshold?is?%d.\n",?uc_reg_value?*?4);??
  • ??
  • #if?CFG_SUPPORT_AUTO_UPG??
  • ????fts_ctpm_auto_upg();??
  • #endif??????
  • ??
  • #if?CFG_SUPPORT_UPDATE_PROJECT_SETTING??
  • ????fts_ctpm_update_project_setting();??
  • #endif??
  • ??
  • ????enable_irq(IRQ_EINT(6));??
  • ???//create?sysfs??
  • ???err?=?sysfs_create_group(&client->dev.kobj,?&ft5x0x_attribute_group);??
  • ???if?(0?!=?err)??
  • ??{??
  • ????dev_err(&client->dev,?"%s()?-?ERROR:?sysfs_create_group()?failed:?%d\n",?__FUNCTION__,?err);??
  • ????sysfs_remove_group(&client->dev.kobj,?&ft5x0x_attribute_group);??
  • ??}??
  • ???else??
  • ????{??
  • ????????printk("ft5x0x:%s()?-?sysfs_create_group()?succeeded.\n",?__FUNCTION__);??
  • ????}??
  • ??
  • ????printk("[FTS]?==probe?over?=\n");??
  • ????return?0;??
  • ??
  • exit_input_register_device_failed:??
  • ????input_free_device(input_dev);??
  • exit_input_dev_alloc_failed:??
  • //??free_irq(client->irq,?ft5x0x_ts);??
  • ????free_irq(IRQ_EINT(6),?ft5x0x_ts);??
  • exit_irq_request_failed:??
  • //exit_platform_data_null:??
  • ????cancel_work_sync(&ft5x0x_ts->pen_event_work);??
  • ????destroy_workqueue(ft5x0x_ts->ts_workqueue);??
  • exit_create_singlethread:??
  • ????printk("==singlethread?error?=\n");??
  • ????i2c_set_clientdata(client,?NULL);??
  • ????kfree(ft5x0x_ts);??
  • exit_alloc_data_failed:??
  • exit_check_functionality_failed:??
  • ????return?err;??
  • }??
  • static?int?__devexit?ft5x0x_ts_remove(struct?i2c_client?*client)??
  • {??
  • ????struct?ft5x0x_ts_data?*ft5x0x_ts;??
  • ????printk("==ft5x0x_ts_remove=\n");??
  • ????ft5x0x_ts?=?i2c_get_clientdata(client);??
  • ????unregister_early_suspend(&ft5x0x_ts->early_suspend);??
  • //??free_irq(client->irq,?ft5x0x_ts);??
  • ????mutex_destroy(&ft5x0x_ts->device_mode_mutex);??
  • ????free_irq(IRQ_EINT(6),?ft5x0x_ts);??
  • ????input_unregister_device(ft5x0x_ts->input_dev);??
  • ????kfree(ft5x0x_ts);??
  • ????cancel_work_sync(&ft5x0x_ts->pen_event_work);??
  • ????destroy_workqueue(ft5x0x_ts->ts_workqueue);??
  • ????i2c_set_clientdata(client,?NULL);???
  • ????del_timer(&test_timer);??
  • ????return?0;??
  • }??
  • ??
  • static?const?struct?i2c_device_id?ft5x0x_ts_id[]?=?{??
  • ????{?FT5X0X_NAME,?0x3x?},{?}??
  • };??
  • ??
  • ??
  • MODULE_DEVICE_TABLE(i2c,?ft5x0x_ts_id);??
  • ??
  • static?struct?i2c_driver?ft5x0x_ts_driver?=?{??
  • ????.probe??????=?ft5x0x_ts_probe,??
  • ????.remove?????=?__devexit_p(ft5x0x_ts_remove),??
  • ????.id_table???=?ft5x0x_ts_id,??
  • ????.driver?=?{??
  • ????????.name???=?FT5X0X_NAME,??
  • ????????.owner??=?THIS_MODULE,??
  • ????},??
  • };??
  • ??
  • static?int?__init?ft5x0x_ts_init(void)??
  • {??
  • ????int?ret;??
  • ????printk("==ft5x0x_ts_init==\n");??
  • ????ret?=?i2c_add_driver(&ft5x0x_ts_driver);??
  • ????printk("ret=%d\n",ret);??
  • ????return?ret;??
  • }??
  • ??
  • static?void?__exit?ft5x0x_ts_exit(void)??
  • {??
  • ????printk("==ft5x0x_ts_exit==\n");??
  • ????i2c_del_driver(&ft5x0x_ts_driver);??
  • }??
  • ??
  • module_init(ft5x0x_ts_init);??
  • module_exit(ft5x0x_ts_exit);??
  • ??
  • MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");??
  • MODULE_DESCRIPTION("FocalTech?ft5x0x?TouchScreen?driver");??
  • MODULE_LICENSE("GPL");??

  • 移植到通用的Linux的內核中,就不寫出來了,自己去研究吧。

    總結

    以上是生活随笔為你收集整理的基于FT5x06嵌入式Linux电容触摸屏驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。