摘 要: 介紹了射頻卡的硬件結構和工作原理,給出了一套對射頻卡進行數據采集和實時處理的軟件設計方案,并采用C#語言編寫了關鍵的程序代碼。
關鍵詞: 射頻卡; 讀卡器; 定時器; 動態鏈接庫
射頻卡又稱非接觸式IC卡,它將RFID和IC技術完美結合,使卡片能夠在不需要電源及與讀卡器不接觸的情況下正常工作。目前射頻卡已經廣泛使用在社會生活的各個領域,如銀行卡、企業一卡通系統等。由于射頻卡具有使用人群的密集性以及使用時間不確定性的特點,就要求讀卡器能夠對射頻卡進行實時準確的數據采集并通過數據線把采集到的數據傳送給計算機,通過特定的處理軟件進行快速處理,并將處理結果反饋回射頻卡,從而實現計算機與射頻卡信息的雙向交互,滿足人們特定的要求。本文通過定時器技術實現對射頻卡信息的實時采集和交互處理,利用定時器的定時觸發功能實現對射頻卡讀寫函數的全天候循環調用,減輕系統的負載、優化系統的進程、提高系統的穩定性,從而保持計算機和射頻卡協同高效地工作。
1 射頻卡硬件結構與工作原理
本課題中射頻卡采用業界廣泛使用的由荷蘭飛利浦公司生產的M1卡,M1卡主要有射頻天線和ASIC兩部分組成,如圖1[1]。射頻天線是由特制的磁感線圈繞制而成,用來接收讀卡器發出的固定頻率的電磁波。ASIC主要由高速射頻RF接口、數據讀寫控制單元、存儲工具EEPROM構成。當讀卡器對射頻卡進行讀寫操作時,讀卡器會持續發出一組頻率固定的電磁波,電磁波的頻率與M1卡內置的LC諧振模塊的諧振頻率相同,從而造成LC諧振模塊發生共振,使諧振電路的電容內產生電荷,這個電容通過特殊的傳輸裝置單向傳輸到另外一個電容聚集起來。當積累的電荷電壓達到2 V時,此電荷實際上可以作為一個電源向卡內的各種電路裝置供電,從而實現讀卡器對射頻卡的讀寫操作。
高速射頻RF接口的主要功能是用來接收通過LC諧振電路產生的電源電壓以及諧振電路本身的復位信號和時鐘信號。數據讀寫控制單元的主要功能是對射頻接口傳遞的數據進行調制和解密并對數據按照特定的步驟與讀卡器進行數據的交互處理。讀卡器與計算機連接的串口初始化成功后,就開始在讀卡器射頻感應的工作范圍內尋找射頻卡[2]。如果同時感應到多張射頻卡,讀卡器會啟動反沖突機制控制模塊選定其中的一張。選定要處理的卡之后,讀寫器就確定要訪問的扇區號,并對該扇區密碼進行密碼校驗,在3次相互認證之后就可以通過加密流進行通訊,對讀卡器進行讀寫操作,操作成功后啟動報警控制模塊,提示操作成功,同時掛起該張卡。EEPROM是射頻卡的存儲單元,用來保存讀卡器寫入的信息。M1射頻卡存儲空間是8 KB。存儲空間分為16個扇區,每個扇區又分為4個塊,每個塊內存大小為16 B。64個塊按物理排序命名,序號從0塊一直到63塊。其中0塊保存的是射頻卡的序列號,出廠時由廠家直接寫入,不能更改。另外,每個扇區的第4塊是該扇區的密碼存儲塊,其中包括兩套密碼以及密碼讀取控制字節。其余3塊是數據塊,可以存儲數據并進行相應數據操作[3],如圖2所示。
2 軟件設計流程與程序實現
基于射頻卡使用環境及對數據處理實時性的特殊要求,必然要求讀卡器處于一種不間斷的監測狀態,能夠對進入讀卡器感應區域的射頻卡進行快速穩定的數據采集,并把這種處理結果實時傳輸給相連的計算機,通過專門的軟件進行信息的交互處理[4]。考慮到這些要求,在軟件的設計過程中使用C#中的timer控件來滿足這種要求,利用Timer控件的定時激發功能,使讀卡器能夠不間斷地檢測是否有卡進入感應區域。首先初始化串口,保證讀卡器和計算機的正常連接,如果讀卡器沒有檢測到有射頻卡處于工作區,就一直保持檢測狀態。如果讀卡器檢測到工作范圍內有卡,就按照正常讀寫操作流程(如圖3)對射頻卡進行操作,一張卡操作完成后,讀卡器會自動報警提示操作成功并掛起這張卡。在這種情況下,除非把這張卡移除工作區,否則讀卡器將無法繼續正常工作。
在分析了射頻卡的工作原理和軟件流程后,本文用C#語言來編寫具體的程序代碼,C#是微軟公司發布的一種面向對象的、運行于.NET Framework之上的高級程序設計語言[5]。為了便于產品的開發,廠家已經附帶給出了開發射頻卡程序所需要的動態連接庫。C#語言可以直接調用給動態連接庫,只需要在程序中加以引用說明即可。本課題采用的讀卡器為雙面D8讀卡器,附帶的動態鏈接庫文件為dcrf32.dll。此文件中包含了常用的射頻卡讀寫操作等系列函數。實現對射頻卡寫數據操作的部分關鍵代碼如下:
…
[DllImport("dcrf32.dll")]
public static extern int dc_init(short port, int baud);
[DllImport("dcrf32.dll")]
public static extern short dc_request(int icdev, char _Mode, ref uint TagType);
[DllImport("dcrf32.dll")]
public static extern short dc_select(int icdev, uint _SecNr, byte[] _Size);
[DllImport("dcrf32.dll")]
public static extern short dc_authentication(int icdev, int _Mode, int _SecNr);
[DllImport("dcrf32.dll")]
public static extern int dc_beep(int icdev, short _Msec);
[DllImport("dcrf32.dll")]
public static extern int dc_pro_halt(int icdev);
[DllImport("dcrf32.dll")]
public static extern short dc_exit(int icdev);
private void Card_Read();
{
_icdev=dc_init(Form3.Com, Form3.botelv);
//串口初始化
if (_icdev <= 0)
{MessageBox.Show(“串口初始化失敗!");
return;
}
byte[] name = System.Text.Encoding.Default.GetBytes
(txtN.Text);
byte[] sex = System.Text.Encoding.Default.GetBytes
(txtS.Text);
if (name.Length > 16)
{
MessageBox.Show("超過規定的數據長度,寫入失敗");
txtN.Text = null;
return;
}
if (sex.Length > 16) //數據長度檢測
{
MessageBox.Show("超過規定的數據長度,寫入失敗");
txtS.Text = null;
return;
}
int st;
ulong icCardNo = 0;
char tt = (char)0;
st = dc_card(IcDev, tt, ref icCardNo); //尋卡操作
if (st != 0)
{ txtCardId.Text = "";
txtN.Text = "";
txtS.Text = "";
MessageBox.Show("尋卡失敗!");
return;
}
int sector = 0;
st = dc_authentication(IcDev, 0, sector); //密碼驗證
if (st != 0)
{
MessageBox.Show("驗證密碼失敗!");
return;
}
try
{
string dt = txtS.Text;
st = dc_write(IcDev, 2, dt); //射頻卡寫操作
dc_beep(IcDev, 10); //蜂鳴操作
st=dc_halt(IcDev) ; //掛起操作
MessageBox.Show("修改成功");
}
catch
{
MessageBox.Show("更改卡中信息失敗");
}
dc_exit(IcDev); //關閉串口
}
private void timer1_Tick(object sender, EventArgs e)
//定時器操作
{
timer1.Interval = 1000;
timer1.Start();
Card_Read();
}
實際應用結果表明,采用C#語言結合定時器的特有功能編寫的射頻卡讀寫控制程序運行穩定,能夠很好地滿足工作現場的需要。在讀卡器對射頻卡進行讀寫操作的同時,并不影響軟件系統其他模塊的操作,具有較強的實用意義。
參考文獻
[1] 楊瑞,彩虹.射頻卡多線程讀寫原理及其實現[J].計算機與信息技術,2006(2):1-3.
[2] 蘇明強,劉偉.高性價比的MIFARE卡讀寫模塊的設計. [J].微計算機信息,2006,22(5-2):1-2.