摘 要: 給出一種在三星S5PV210處理器的Linux系統(tǒng)下基于PIC24F單片機實現(xiàn)的觸摸傳感系統(tǒng)的設(shè)計方案。利用PIC24F充電時間測量單元(CTMU)和ADC實現(xiàn)觸摸信息采集,S5PV210通過I2C總線與觸摸傳感器通信,讀取傳感器觸摸狀態(tài)信息;設(shè)計了PIC24F固件程序和其在主控S5PV210處理器Linux系統(tǒng)下的I2C設(shè)備驅(qū)動程序。測試結(jié)果表明,在主控Linux系統(tǒng)下可以精確獲得觸摸狀態(tài)信息。
關(guān)鍵詞: 觸摸傳感;CTMU;I2C;Linux驅(qū)動
0 引言
隨著科技的進步,各種形式的觸摸傳感器被應(yīng)用于機器人、家電、便攜式消費電子等領(lǐng)域。
常用觸摸傳感器主要有電阻式和電容式兩種,電容式以靈敏度高、抗損性好的特點得到廣泛應(yīng)用。一般電容傳感器由專用ASIC實現(xiàn),本文基于PIC24F MCU(微控制器)實現(xiàn)電容觸摸傳感器,由于傳感器只是MCU外接的金屬片,具有成本低、形狀靈活、外圍電路簡單的特點,主控端可在嵌入式Linux下通過I2C總線獲得多個傳感器狀態(tài)。
1 系統(tǒng)組成
如圖1所示,觸摸傳感系統(tǒng)由多個電容觸摸傳感器端(由PIC24F MCU實現(xiàn))和S5PV210主控端(運行Linux系統(tǒng))兩部分組成。電容傳感器端處理觸摸信息,主控端通過I2C總線與傳感器通信,得到其處理好的傳感器數(shù)據(jù)(包含傳感器ID和是否觸摸狀態(tài))。一片PIC24F最多可實現(xiàn)16個觸摸傳感器。
2 功能實現(xiàn)
2.1 基于PIC24F CTMU方式實現(xiàn)觸摸檢測
圖2為PIC24F CTMU框圖。
PIC24F的CTMU是由一個可調(diào)節(jié)恒流源和邏輯控制塊構(gòu)成的可配置模擬單元。觸摸檢測采用CTMU恒流源與A/D轉(zhuǎn)換器的連接[1]如圖3所示。
通過CTMU在傳感器上施加恒流源實現(xiàn)觸摸檢測。
I×T=C×V(1)
其中,I是CTMU恒流源電流,T是CTMU充電的固定周期,C是觸摸電路的電容,V是充電完成后經(jīng)A/D轉(zhuǎn)換器讀取的電壓值。
由于CTMU恒流源I是恒定的,設(shè)置充電周期T保持恒定,則電路中電容C的變化將表現(xiàn)為電壓V的變化,當(dāng)人手指接觸到傳感器時,總電容將增加,A/D轉(zhuǎn)換器讀取的電壓減小。
圖4為傳感器電壓采集子程序,它由CTMU單元和ADC單元配合完成[2]。傳感器電容與ADC的保持電容并聯(lián),每次測量電壓前使兩個電容接地放電至0 V,隨后控制CTMU的恒流源對兩個電容注入一定量的電荷,再通過ADC讀取電壓。可以計算觸摸前后電壓差值為:
其中,CF是手指電容,CB是金屬片基礎(chǔ)電容,CA/D是ADC保持電容,I是CTMU恒流源的電流,t是充電時間。
實際中由手指電容引起的電容增量為pF量級,為獲得較高的靈敏度,需增大ΔCTMU,由式(2)可知,減小基礎(chǔ)電容CB和適當(dāng)增加注入電荷(It)為有效方式。傳感器面積會影響CB,形狀不是主要影響因素,本文設(shè)計的傳感器尺寸為15 mm×15 mm的正方形,配置CTMU恒流源為最大55 μA(CTMUICON=0x0300)以提高充電速度和電量。
2.2 S5PV210與觸摸傳感器I2C通信
I2C總線(Inter Integrated Circuit)是主從結(jié)構(gòu)的兩線式(數(shù)據(jù)線SDA,時鐘線SCL)串行總線。它接口簡單、互聯(lián)成本低,數(shù)據(jù)的傳輸和時鐘頻率均由主機控制,因此各種傳感器芯片大都采用I2C通信。
開始通信時,由主機端S5PV210發(fā)送S,接著發(fā)送Addr(從機地址7 bit)、R/W(讀寫位1 bit)給PIC24F,PIC24F收到8 bit(Addr+R/W)確認是本機后,將SDA線拉低作為ACK,主機在第9個SCL采集到低電平ACK后,確認連接到從機,接著主從將根據(jù)R/W位接收或者發(fā)送1 B傳感器數(shù)據(jù)。本文為2個傳感器(一片PIC24F最多可實現(xiàn)16個傳感器,多于16個時可通過I2C總線進行擴展),設(shè)置傳感器1被觸摸則發(fā)送0x01,傳感器2被觸摸發(fā)送0x02,沒有觸摸為0x00。單片機PORTE口接有LED將接收數(shù)據(jù)賦給PORTE做為接收測試(0-亮,1-滅)。圖5為總線時序圖。
2.3 從機端電容觸摸傳感器固件設(shè)計
PIC24F固件程序流程如圖6所示。
系統(tǒng)初始化使能Time1、ADC、CTMU和I2C(slave模式),Time1中斷用于觸發(fā)讀取傳感器1和傳感器2經(jīng)CTMU和ADC處理的電壓值,并將有無觸摸(電壓降低)狀態(tài)保存到I2C的發(fā)送緩存里,隨后利用主機端發(fā)起通信引起的中斷發(fā)送觸摸狀態(tài)或接收數(shù)據(jù)。
2.4 主機端Linux I2C設(shè)備驅(qū)動設(shè)計
S5PV210 Linux下I2C驅(qū)動層次結(jié)構(gòu)如圖7所示。
Linux系統(tǒng)分為用戶層和內(nèi)核層,系統(tǒng)下應(yīng)用程序訪問硬件設(shè)備需要位于內(nèi)核層的設(shè)備驅(qū)動提供的接口支持[3]。
整個I2C驅(qū)動程序由I2C設(shè)備驅(qū)動和總線驅(qū)動兩部分組成,Linux下對S5PV210 I2C控制器驅(qū)動即總線驅(qū)動已經(jīng)支持,要做的是針對觸摸傳感器設(shè)計I2C設(shè)備驅(qū)動。I2C設(shè)備驅(qū)動在Linux中屬于字符設(shè)備,字符設(shè)備可以以設(shè)備文件形式存在,由應(yīng)用程序打開并進行讀寫操作,從而實現(xiàn)控制硬件的目的。
S5PV210有3個I2C主控制器,觸摸傳感器驅(qū)動采用第一個主控制器。Linux下設(shè)備驅(qū)動可以直接編譯到內(nèi)核,也可以在外部編譯好生成.ko文件,然后使用insmod命令動態(tài)加載到運行的內(nèi)核中,為了方便開發(fā)采用動態(tài)加載方式。
I2C設(shè)備驅(qū)動程序可分為兩部分[4]:首先定義和注冊I2C設(shè)備即i2c_client;然后定義和注冊I2C設(shè)備驅(qū)動即i2c_driver。i2c_client即是PIC24F模塊,所以要在i2c_client中設(shè)置PIC24F的設(shè)備名和地址信息,i2c_client里關(guān)鍵代碼及結(jié)構(gòu)有:
struct i2c_board_info pic_touch_info={
i2c_board_info("pic_touch",0x40),
//注意PIC實際地址0x80,這里要右移1位:0x80>>1=0x40
};//設(shè)置i2c_board_info結(jié)構(gòu)體保存設(shè)備名和設(shè)備地址
structi2c_adapter*i2c_adap;
i2c_adap=i2c_get_adapter(0);
//使用S5PV210第一個控制器
pic_touch_client=i2c_new_device(i2c_adap,&pic_touch_info);
//調(diào)用i2c_new_device創(chuàng)建并注冊I2C
//設(shè)備對應(yīng)的i2c_client結(jié)構(gòu)體
第二部分定義和注冊I2C設(shè)備驅(qū)動,其中i2c_driver為核心結(jié)構(gòu)體,設(shè)置驅(qū)動所能支持的設(shè)備列表pic_touch_id_table[],提供探測函數(shù)pic_touch_probe(),當(dāng)總線驅(qū)動發(fā)現(xiàn)i2c_client設(shè)備名與id_table中相同時,會自動發(fā)出設(shè)備地址,如果收到ACK,則確定設(shè)備存在,總線驅(qū)動會把設(shè)備掛接到此驅(qū)動并調(diào)用pic_touch_probe(),在此函數(shù)中注冊字符設(shè)備創(chuàng)建設(shè)備訪問節(jié)點,構(gòu)造file_openration結(jié)構(gòu)體,在此結(jié)構(gòu)體中編寫實際操作硬件的讀寫函數(shù)。
i2c_driver關(guān)鍵代碼及結(jié)構(gòu):
struct i2c_device_id pic_touch_id_table
[]={{"pic_touch",0},{}};//填充與i2c_client相同的
//設(shè)備名pic_touch,使此驅(qū)動適用于傳感器設(shè)備
//創(chuàng)建i2c_driver結(jié)構(gòu)體對象
struct i2c_driver pic_touch_driver={
.driver={
.name="pic_touchdrv",
.owner=THIS_MODULE,
},
.probe=pic_touch_probe,//設(shè)置探測函數(shù),此函數(shù)在驅(qū)動
//與i2c_client匹配時調(diào)用,在此函數(shù)中完成字符設(shè)備的注冊
.remove=__devexit_p(pic_touch_remove),
//去除驅(qū)動時調(diào)用
.id_table=pic_touch_id_table,
//在此id_table中查找本驅(qū)動支持的設(shè)備
};
探測函數(shù)pic_touch_probe()中關(guān)鍵段:
major=register_chrdev(0,"pic_touch",
&pic_touch_fops);//注冊字符設(shè)備
class=class_create(THIS_MODULE,"pic_touch");
device_create(class,NULL,MKDEV(major,0),NULL,"pic_touch");
//生成設(shè)備訪問節(jié)點/dev/pic_touch
構(gòu)造file_operations結(jié)構(gòu)體填充讀寫函數(shù)
file_operations pic_touch_fops={
.owner=THIS_MODULE,
.read=pic_touch_read,
.write=pic_touch_write,
};
pic_touch_read()和pic_touch_write()是實際操作硬件的函數(shù)。需要根據(jù)從機端觸摸傳感器I2C固件需求的時序設(shè)計。
本文采用Linux內(nèi)核提供的SMBus讀寫函數(shù)實現(xiàn),SMBus(System Management Bus)是I2C的子集。
讀函數(shù)pic_touch_read()關(guān)鍵程序段:
data=i2c_smbus_read_byte(pic_touch_client);
//從傳感器讀數(shù)據(jù)存在內(nèi)核緩沖data
copy_to_user(buf,&data,1);
//將讀取的傳感器數(shù)據(jù)data拷貝到用戶buf空間
寫函數(shù)pic_touch_write()關(guān)鍵程序段:
copy_from_user(&data,buf,1);
//從用戶空間buf拷貝1 B數(shù)據(jù)到內(nèi)核緩沖區(qū)data
i2c_smbus_write_byte(pic_touch_client,data)
//將數(shù)據(jù)發(fā)送給傳感器設(shè)備
3 測試
無觸摸ADC取值穩(wěn)定,觸摸后因每次觸摸面積不同使得讀取ADC值差別較大,本設(shè)計根據(jù)表1測試結(jié)果設(shè)置觸發(fā)閾值為0x0200,實際中需根據(jù)靈敏度要求和測試結(jié)果合理設(shè)置閾值,利用Time1中斷定時掃描讀取2個觸摸傳感器值,設(shè)置的中斷時間為480 ,CTMU充電時間為1.25 。
主控端Linux下讀取傳感器狀態(tài),先insmod加載驅(qū)動,生成設(shè)備節(jié)點/dev/pic_touch:
#insmod pic_touch_dev.ko
#insmod pic_touch_drv.ko
打印調(diào)試信息:
pic_touch_pad is probed, make chdev node:/dev/pic_touch
#ls/dev/pic_touch
/dev/pic_touch
無觸摸時,Linux下運行如下測試程序:
#./pic_touch_testrw r
readdata=0x00 touch state is:0x00
成功返回?zé)o觸摸狀態(tài)0x00。
分別觸摸傳感器1和傳感器2,運行測試程序:
#./pic_touch_testrw r
readdata=0x01 touch state is:0x01
#./pic_touch_testrw r
readdata=0x02 touch state is:0x02
成功讀取傳感器1和2被觸摸狀態(tài)0x01,0x02。
發(fā)送數(shù)據(jù)0xaa給傳感器接收測試LED:
#./pic_touch_testrw w 0xaa
cmmd=0xaa write success!,cmd=0xaa
發(fā)送成功,LED狀態(tài)正確。
為檢測傳感器性能,實測時傳感器表面蓋一層1 mm厚的透明塑料,LED同時指示傳感器狀態(tài)。測試結(jié)果表明,設(shè)置的觸摸傳感器掃描頻率和觸發(fā)閾值有很好的靈敏度和穩(wěn)定性,在主控端Linux I2C速率為100 kb/s下可實時精確地獲取傳感器觸摸狀態(tài)信息,達到設(shè)計目標。本文在Linux下基于MCU實現(xiàn)觸摸傳感系統(tǒng)也便于后續(xù)利用MCU擴展傳感器功能。
參考文獻
[1] Microchip Technology Inc.PIC24FJ256GA110 Family Data Sheet[Z]. 2010.
[2] Microchip Technology Inc.Microchip CTMU for Capacitive Touch Applications[Z]. 2009.
[3] 宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解(第2版)[M].北京:人民郵電出版社,2010.
[4] 韋東山.嵌入式Linux應(yīng)用開發(fā)完全手冊[M].北京:人民郵電出版社,2008.