《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 模擬設(shè)計 > 設(shè)計應(yīng)用 > 基于S3C2410的觸摸屏驅(qū)動程序設(shè)計
基于S3C2410的觸摸屏驅(qū)動程序設(shè)計
摘要: 在觸摸屏的設(shè)計中,,抗干擾設(shè)計是難點和重點,,直接關(guān)系到觸摸屏的工作性能。實驗發(fā)現(xiàn)坐標采集時,,丟棄第一次采集值讀取的坐標轉(zhuǎn)換值效果較好。本文所介紹的驅(qū)動程序已經(jīng)在博創(chuàng)公司的教學(xué)實驗設(shè)備UP-NETarm2410-S平臺上經(jīng)過實際驗證,,從數(shù)據(jù)穩(wěn)定性和系統(tǒng)負載的角度看,,效果良好。同時通過修改程序內(nèi)部的定時器時鐘頻率可以改變筆在屏上移動所產(chǎn)生的數(shù)據(jù)量,。
Abstract:
Key words :

  引言

  隨著信息家電和通訊設(shè)備的普及,,作為與用戶交互的終端媒介,觸摸屏在生活中得到廣泛的應(yīng)用,。如何在系統(tǒng)中集成觸摸屏模塊以及在嵌入式操作系統(tǒng)中實現(xiàn)其驅(qū)動程序,,都成為嵌入式系統(tǒng)設(shè)計者需要考慮的問題。本文主要介紹在三星S3C2410X微處理器的硬件平臺上進行基于嵌入式Linux的觸摸屏驅(qū)動程序設(shè)計,。

  硬件實現(xiàn)方案

  SPI接口是Motorola推出的一種同步串行接口,,采用全雙工、四線通信系統(tǒng),,S3C2410X是三星推出的自帶觸摸屏接口的arm920T內(nèi)核芯片,,ADS7843為Burr-Brown生產(chǎn)的一款性能優(yōu)異的觸摸屏控制器。本文采用SPI接口的觸摸屏控制器ADS7843外接四線電阻式觸摸屏,,這種方式最顯著的特點是響應(yīng)速度更快,、靈敏度更高,微處理器與觸摸屏控制器間的通訊時間大大減少,,提高了微處理器的效率,。ADS7843與S3C2410的硬件連接如圖1所示,鑒于ADS7843差分工作模式的優(yōu)點,,在硬件電路中將其配置為差分模式,。


圖1 觸摸屏輸入系統(tǒng)示意圖

  嵌入式Linux系統(tǒng)下的驅(qū)動程序

  設(shè)備驅(qū)動程序是Linux內(nèi)核的重要組成部分,,控制了操作系統(tǒng)和硬件設(shè)備之間的交互,。Linux的設(shè)備管理是和文件系統(tǒng)緊密結(jié)合的,各種設(shè)備都以文件的形式存放在/dev目錄下,,成為設(shè)備文件,。應(yīng)用程序可以打開、關(guān)閉,、讀寫這些設(shè)備文件,,對設(shè)備的操作就像操作普通的數(shù)據(jù)文件一樣簡便。為開發(fā)便利,、提高效率,,本設(shè)計采用可安裝模塊方式開發(fā)調(diào)試觸摸屏驅(qū)動程序。

  設(shè)備驅(qū)動在加載時首先需要調(diào)用入口函數(shù)init_module(),該函數(shù)完成設(shè)備驅(qū)動的初始化工作,。其中最重要的工作就是向內(nèi)核注冊該設(shè)備,,對于字符設(shè)備調(diào)用register_chrdev()完成注冊,對于塊設(shè)備需要調(diào)用register_blkdev()完成注冊,。注冊成功后,,該設(shè)備獲得了系統(tǒng)分配的主設(shè)備號、自定義的次設(shè)備號,,并建立起與文件系統(tǒng)的關(guān)聯(lián),。字符設(shè)備驅(qū)動程序向Linux內(nèi)核注冊登記時,在字符設(shè)備向量表chrdevs中增加一個device_struct數(shù)據(jù)結(jié)構(gòu)條目,,這個設(shè)備的主設(shè)備標識符用作這個向量表的索引,。向量表中的每一個條目,即一個device_struct數(shù)據(jù)結(jié)構(gòu)包括兩個元素:一個登記的設(shè)備驅(qū)動程序的名稱的指針和一個指向一組文件操作的指針,。這塊文件操作本身位于這個設(shè)備的字符設(shè)備驅(qū)動程序中,,每一個都處理特定的文件操作,比如打開,、讀寫和關(guān)閉,。所謂登記,就是將由模塊提供的file_operations結(jié)構(gòu)指針填入device_struct數(shù)據(jù)結(jié)構(gòu)數(shù)組的某個表項,。登記以后,,位于上層的模塊(內(nèi)核)可以“看見”這個模塊了。但是,,應(yīng)用程序卻還不能“看見”它,,因而還不能通過系統(tǒng)調(diào)用它。要使應(yīng)用程序能“看見”這個模塊或者它所驅(qū)動的設(shè)備,,就要在文件系統(tǒng)中為其創(chuàng)建一個代表它的節(jié)點,。通過系統(tǒng)調(diào)用mknod()創(chuàng)建代表此項設(shè)備的文件節(jié)點——設(shè)備入口點,就可使一項設(shè)備在系統(tǒng)中可見,,成為應(yīng)用程序可以訪問的設(shè)備,。另外,設(shè)備驅(qū)動在卸載時需要回收相應(yīng)的資源,,令設(shè)備的相應(yīng)寄存器值復(fù)位并從系統(tǒng)中注銷該設(shè)備,。

  Linux操作系統(tǒng)通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。設(shè)備驅(qū)動模塊的功能就是擴展內(nèi)核的功能,,主要完成兩部分任務(wù):一個是系統(tǒng)調(diào)用,,另一個是處理中斷。圖2是一個設(shè)備驅(qū)動模塊動態(tài)掛接,、卸載和系統(tǒng)調(diào)用的全過程,。系統(tǒng)調(diào)用部分則是對設(shè)備的操作過程,比如open,read,,write,,ioctl等操作,設(shè)備驅(qū)動程序所提供的這組入口點由幾個結(jié)構(gòu)向系統(tǒng)進行說明,,分別是file_operations數(shù)據(jù)結(jié)構(gòu),、inode數(shù)據(jù)結(jié)構(gòu)和file 數(shù)據(jù)結(jié)構(gòu)。內(nèi)核內(nèi)部通過file結(jié)構(gòu)識別設(shè)備,,通過file_operations數(shù)據(jù)結(jié)構(gòu)提供文件系統(tǒng)的入口點函數(shù),,也就是訪問設(shè)備驅(qū)動的函數(shù),結(jié)構(gòu)中的每一個成員都對應(yīng)著一個系統(tǒng)調(diào)用,。在嵌入式系統(tǒng)的開發(fā)中,,我們一般僅僅實現(xiàn)其中幾個接口函數(shù):read、write,、open,、ioctl及release就可以完成應(yīng)用系統(tǒng)需要的功能。寫驅(qū)動程序的任務(wù)之一就是完成file_operations中的函數(shù)指針,。

 

 

 

  觸摸屏驅(qū)動程序設(shè)計

  觸摸屏驅(qū)動程序中重要數(shù)據(jù)結(jié)構(gòu)

  typedef struct {

  unsigned short pressure;

  unsigned short x;

  unsigned short y;

  unsigned short pad;

  } TS_RET;

  typedef struct {

  unsigned int PenStatus;

  TS_RET buf[MAX_TS_BUF];

  unsigned int head, tail;

  wait_queue_head_t wq;

  spinlock_t lock;

  } TS_DEV;

  static struct file_operations s3c2410_fops = {

  owner: THIS_MODULE,

  open: s3c2410_ts_open,

  read: s3c2410_ts_read,   release: s3c2410_ts_release,

  poll: s3c2410_ts_poll,    };

  在程序中有三個重要的數(shù)據(jù)結(jié)構(gòu):用于表示筆觸點數(shù)據(jù)信息的結(jié)構(gòu)TS_RET,,表示ADS7843中有關(guān)觸摸屏控制器信息的結(jié)構(gòu)TS_DEV,以及驅(qū)動程序與應(yīng)用程序的接口file_operations結(jié)構(gòu)的s3c2410_fops,。

  TS_RET結(jié)構(gòu)體中的信息就是驅(qū)動程序提供給上層應(yīng)用程序使用的信息,,用來存儲觸摸屏的返回值。上層應(yīng)用程序通過讀接口,,從底層驅(qū)動中讀取信息,,并根據(jù)得到的值進行其他方面的操作。

  TS_DEV結(jié)構(gòu)用于記錄觸摸屏運行的各種狀態(tài),,PenStatus包括PEN_UP,、PEN_DOWN和PEN_FLEETING。buf[MAX_TS_BUF]是用來存放數(shù)據(jù)信息的事件隊列,,head,、tail分別指向事件隊列的頭和尾。程序中的筆事件隊列是一個環(huán)形結(jié)構(gòu),,當有事件加入時,,隊列頭加一,當有事件被取走時,,隊列尾加一,當頭尾位置指針一致時讀取筆事件的信息,,進程會被安排進入睡眠,。wq等待隊列,包含一個鎖變量和一個正在睡眠進程鏈表。當有好幾個進程都在等待某件事時,,Linux會把這些進程記錄到這個等待隊列,。它的作用是當沒有筆觸事件發(fā)生時,阻塞上層的讀操作,,直到有筆觸事件發(fā)生,。lock使用自旋鎖,自旋鎖是基于共享變量來工作的,,函數(shù)可以通過給某個變量設(shè)置一個特殊值來獲得鎖,。而其他需要鎖的函數(shù)則會循環(huán)查詢鎖是否可用。MAX_TS_BUF的值為16,,即在沒有被讀取之前,,系統(tǒng)緩沖區(qū)中最多可以存放16個筆觸數(shù)據(jù)信息。

  s3c2410_fops就是內(nèi)核對驅(qū)動的調(diào)用接口,,完成了將驅(qū)動函數(shù)映射為標準接口,。上面的這種特殊表示方法不是標準C的語法,而是GNU編譯器的一種特殊擴展,,它使用名字進行結(jié)構(gòu)字段的初始化,,它的好處體現(xiàn)在結(jié)構(gòu)清晰,易于理解,,并且避免了結(jié)構(gòu)發(fā)生變化帶來的許多問題,。

  init_module函數(shù)

  這是模塊的入口函數(shù)。在函數(shù)內(nèi)部通過s3c2410_ts_init( )實現(xiàn)模塊的初始化工作,。在本設(shè)計中設(shè)備與系統(tǒng)之間以中斷方式進行數(shù)據(jù)交換,。整個觸摸屏的驅(qū)動程序處理比較復(fù)雜,而且耗時較長,,因而觸摸屏驅(qū)動程序不可能在中斷服務(wù)程序中完成,。在Linux操作系統(tǒng)中一般把中斷處理切為兩個部分或兩半。中斷處理程序是上半部——接收到一個中斷,,它就立即開始執(zhí)行,,但只做有嚴格時限的工作,例如對接收的中斷進行應(yīng)答或復(fù)位硬件,。這些工作都是在所有中斷被禁止的情況下完成的,,能夠被允許稍后完成的工作會推遲到下半部去。在Linux中下半部的實現(xiàn)有多種機制,。按觸摸屏?xí)r,,從ADS7843輸出的數(shù)值有一個抖動過程,即從ADS7846輸出的數(shù)值有一個不穩(wěn)定時期,,這個過程大約為10ms,。所以中斷處理程序的下半部處理函數(shù)采用內(nèi)核定時器機制,,使下半部在中斷發(fā)生50ms后再作處理。這樣有效地避開了ADS7843輸出值的不穩(wěn)定時期,,使中斷服務(wù)程序和中斷處理任務(wù)串行化,,達到了處理時間較長的觸摸屏事件的目的。驅(qū)動程序通過request_irq函數(shù)注冊并激活一個中斷處理程序,,以便處理中斷,。


圖2 設(shè)備驅(qū)動在內(nèi)核中的掛接、卸載和系統(tǒng)調(diào)用過程

 

 

  int reguest_irq(unsigned int irq, void(*handler)(int, void *, struct pt_regs *), unsigned long irq_flags, const char *dev_name, void *dev_id)

  參數(shù)irq表示所要申請的中斷號,;handler為向系統(tǒng)登記的中斷處理子程序,,中斷產(chǎn)生時由系統(tǒng)來調(diào)用;dev_name為設(shè)備名,;dev_id為申請時告訴系統(tǒng)的設(shè)備標識符,;irq_flags是申請時的選項,它決定中斷處理程序的一些特性,,其中最重要的是中斷處理程序是快速處理程序還是慢速處理程序,。

  本設(shè)計中觸摸屏控制器ADS7843的中斷輸出通過外部中斷5接在中斷控制器上,當觸摸屏上有觸摸事件發(fā)生時,,會引發(fā)中斷號為IRQ_EINT5的中斷服務(wù)程序s3c2410_isr_tc(),。圖3所示為該中斷處理程序的流程圖。


圖3 觸摸屏硬件中斷處理程序流程圖

  在s3c2410_isr_tc()中設(shè)定了定時器的定時時間為50ms,,并立即激活,。因此有觸摸屏硬件中斷的情況下50ms后就會引發(fā)定時中斷,中斷服務(wù)程序為ts_timer_handler(),,這個程序?qū)崿F(xiàn)了觸摸屏中斷的下半部,,即在過了抖動時間之后如果觸摸屏確實有有效事件發(fā)生則采集觸摸屏坐標,并將定時器的時間重新設(shè)為100ms并重新激活,,這樣做的目的是如果觸摸筆是拖動的情況,,以后每100ms采集一次坐標值,并存入緩沖區(qū),,如果不是拖動在采集一次坐標值之后,,在第二次進入ts_timer_handler()時,查詢管腳的狀態(tài)值,,則變?yōu)楦唠娖?,就將觸摸屏狀態(tài)tsdev.PenStatus設(shè)為PEN_UP,并釋放定時器,,為下次觸摸屏事件做好準備,,定時中斷服務(wù)程序流程圖如圖4所示。


圖4 定時中斷服務(wù)程序流程圖

 

 

  在s3c2410_ts_init()中的另一個重要任務(wù)是執(zhí)行接口函數(shù)s3c2410_ts_open(),,在這個函數(shù)中初始化緩沖區(qū)的頭尾指針,、觸摸屏狀態(tài)變量及觸摸屏事件等待隊列,。

  module_exit()

  該函數(shù)調(diào)用s3c2410_ts_exit(),,主要任務(wù)是撤銷驅(qū)動程序向內(nèi)核的登記以及釋放申請的中斷資源,。

  接口函數(shù)s3c2410_ts_read( )

  這個函數(shù)實現(xiàn)的任務(wù)是將事件隊列從設(shè)備緩存中讀到用戶空間的數(shù)據(jù)緩存中。實現(xiàn)的過程主要是通過一個循環(huán),,只有在事件隊列的頭,、尾指針不重合時,才能成功的從tsdev.tail指向的隊列尾部讀取到一組觸摸信息數(shù)據(jù),,并退出循環(huán),。否則調(diào)用讀取函數(shù)的進程就要進入睡眠。

  坐標讀取函數(shù)s3c2410_get_XY()

  在定時器中斷處理程序中,,當查詢到與相連的EINT5/GPF5為低電平時,,即表示有有效事件,應(yīng)該調(diào)用s3c2410_get_XY()函數(shù)采集筆觸信息,。

  ADS7843有多種轉(zhuǎn)換時序,,時序規(guī)定了芯片與設(shè)備及CPU間是如何配合工作的。設(shè)計中采用16個時鐘周期啟動一次轉(zhuǎn)換的坐標轉(zhuǎn)換方式,。ADS7843的操作時序如圖5所示,。坐標的讀取是通過多次采集取平均值的方法,以X坐標的讀取為例,,其讀取過程如圖6所示,。循環(huán)過程中的每一步都在8個時鐘周期內(nèi)完成,數(shù)據(jù)的處理嚴格按照時序進行,,Y坐標的采集與X坐標類似,。


圖5 ADS7843操作時序


圖6 X坐標采集流程

  結(jié)語

  在觸摸屏的設(shè)計中,抗干擾設(shè)計是難點和重點,,直接關(guān)系到觸摸屏的工作性能,。實驗發(fā)現(xiàn)坐標采集時,丟棄第一次采集值讀取的坐標轉(zhuǎn)換值效果較好,。本文所介紹的驅(qū)動程序已經(jīng)在博創(chuàng)公司的教學(xué)實驗設(shè)備UP-NETarm2410-S平臺上經(jīng)過實際驗證,,從數(shù)據(jù)穩(wěn)定性和系統(tǒng)負載的角度看,效果良好,。同時通過修改程序內(nèi)部的定時器時鐘頻率可以改變筆在屏上移動所產(chǎn)生的數(shù)據(jù)量,。

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載,。