本應(yīng)用筆記解釋了如何在DS5250安全微控制器上輕松實現(xiàn)磁條卡讀取和解碼。本文還演示了如何開發(fā)將磁條卡讀取功能與安全微控制器的更高級別安全性和加密功能相結(jié)合的應(yīng)用。本例使用DS5250評估(EV)板與磁條讀卡器接口。提供源代碼,可輕松移植到Maxim其他基于8051的微控制器。
概述
背面帶有磁性編碼條紋的卡通常稱為磁條卡,用于大量銀行、儲值和其他金融應(yīng)用。信用卡、ATM 卡和借記卡都是典型的磁條卡,有時還嵌入了智能卡芯片。其他例子是其他例子,例如用于游戲、復(fù)印機和公共交通的許多禮品卡、安全卡或房間鑰匙卡以及儲值卡。當(dāng)使用標(biāo)準ISO格式時,這些磁條卡的最大容量約為160字節(jié),通常不會存儲大量數(shù)據(jù)。與智能卡或便攜式閃存驅(qū)動器相比,磁條卡的存儲容量足以滿足最常使用這些卡的金融和銀行應(yīng)用。此外,磁條卡堅固耐用,價格低廉,不需要內(nèi)部電源,并且相對容易讀取。
本應(yīng)用筆記介紹如何使用DS5250安全微控制器與磁條讀卡器接口。之所以選擇DS5250,是因為它提供了構(gòu)建讀取磁條卡的通用器件(即銷售點(POS)終端)所需的關(guān)鍵安全和加密功能。
磁條讀卡器包含執(zhí)行低級任務(wù)的電路:將磁條上的磁通量解碼為比特流。DS5250管理更高層次的任務(wù):將這些位轉(zhuǎn)換為字符,然后讀取和驗證數(shù)據(jù)字段。
硬件和軟件要求
硬件
本示例應(yīng)用使用DS5250評估(EV)板(修訂版B),修改如下:
示例應(yīng)用程序還需要以下硬件:
讀卡器—MagTek 三軌刷卡讀卡器,帶 3V 解碼器 ASIC;部件號 21030001 修訂版 G 或更高版本
兩個上拉電阻(約10kΩ)
線性穩(wěn)壓器(能夠從5V電源產(chǎn)生3V至3.6V電壓)
用于測試的磁條卡(ATM卡,信用卡等)
以下各節(jié)介紹示例應(yīng)用程序的實現(xiàn)。完整的示例C代碼可從Analog的FTP站點下載。
連接讀卡器
MagTek 讀卡器有五個接口引腳(包括電源和接地):
引腳 1 - 頻閃
該信號始終是讀卡器的輸入。它由主微控制器驅(qū)動,以輸出卡數(shù)據(jù)位并置位復(fù)位序列。
引腳 2 - 數(shù)據(jù)
該信號通常用作讀卡器的輸出。它攜帶來自磁道 A/B/C 的卡數(shù)據(jù)位,這些磁道由 STROBE 信號計時輸出。在某些情況下(例如,當(dāng)置位復(fù)位序列時),該信號可由主微控制器驅(qū)動。
引腳 3 — VDD
為讀卡器供電(2.7V 至 3.6V)。
引腳 4 - 接地
引腳 5 - 接地
由于STROBE和數(shù)據(jù)引腳工作在3V電平,DS5250不能用標(biāo)準端口引腳直接驅(qū)動它們。因此,使用端口0的引腳(工作在漏極開路模式),當(dāng)DS5250對引腳進行三電平時,電阻將信號電平拉至3.6V。DS5250直接從數(shù)據(jù)線讀取數(shù)據(jù)信號,因為最小VIHDS5250端口引腳的電平足夠低,可以兼容3V I/O電平。(請參考DS5250數(shù)據(jù)資料了解更多詳細信息。
讀卡器工作在 3V 電平;它不能直接由DS5250使用的5V電源供電。由于DS5250評估板不提供3V電源,因此使用單獨的線性穩(wěn)壓器(如MAX1658)為讀卡器供電。參見圖1。

圖1.例如應(yīng)用程序的連接。
執(zhí)行復(fù)位序列
首次上電后,主微控制器必須重置讀卡器,然后才能接受刷卡。每次刷卡后也必須執(zhí)行此重置序列,以清除內(nèi)部讀卡器ASIC的內(nèi)存,并使讀卡器準備好接受新的刷卡。
為了復(fù)位讀卡器,主微控制器(即本應(yīng)用中的DS5250)必須按以下順序驅(qū)動頻閃和數(shù)據(jù)。(有關(guān)確切的電壓電平和時序參數(shù),請參閱 MagTek 文檔。
DATA 和 STROBE 都從高(空閑)狀態(tài)開始。
強制數(shù)據(jù)降低。
在數(shù)據(jù)保持低電平的情況下,將頻閃驅(qū)動為低電平,然后再次驅(qū)動為高電平。
再次將頻閃驅(qū)動為低電平,然后釋放數(shù)據(jù),使其浮高。
在數(shù)據(jù)浮動高電平時,將頻閃驅(qū)動為低電平,然后再次高電平。此時,讀卡器被重置并處于低功耗等待狀態(tài)。
將頻閃驅(qū)動為低,然后再次高。此操作“武裝”讀卡器并準備接受刷卡。
// Generate a long delay for card reset and read intervals. void longDelay() { int i, j; for (i = 1; i < 5; i++) { for (j = 1; j < 5000; j++) { ; } } } // Generate a shorter delay (used between STROBE/DATA transitions). void delay() { int i; for (i = 1; i < 1000; i++) { ; } } // Release the DATA line (P0.0) and allow it to float high. void dataHigh() { P0 |= 0x01; delay(); } // Drive the DATA line (P0.0) low. void dataLow() { P0 &= 0xFE; delay(); } // Release the STROBE line (P0.1) and allow it to float high. void strobeHigh() { P0 |= 0x02; delay(); } // Drive the STROBE line (P0.1) low. void strobeLow() { P0 &= 0xFD; delay(); } void resetCardReader() { dataHigh(); strobeHigh(); longDelay(); dataLow(); // Force DATA low. longDelay(); strobeLow(); // Drive STROBE low, then high again. strobeHigh(); strobeLow(); // Drive STROBE low, then release DATA. dataHigh(); longDelay(); strobeHigh(); // Drive STROBE low and high again two more times strobeLow(); // to complete the reset and leave the card reader strobeHigh(); // in the ready state, prepared to scan a card. strobeLow(); }
檢測刷卡
一旦讀卡器重置并布防,它就可以接受刷卡了。MagTek 讀卡器在刷卡時執(zhí)行整個讀卡周期;主微控制器無需干預(yù)??l上所有三個磁道(磁道 A、磁道 B 和磁道 C)的全部內(nèi)容都存儲在讀卡器 IC 上。在讀卡周期結(jié)束后,主微控制器可以一次一位地輸出這些數(shù)據(jù)。
讀卡器經(jīng)歷一個握手周期,以通知主設(shè)備何時開始讀卡并完成。
循環(huán)從頻閃低電平和數(shù)據(jù)高浮動(空閑狀態(tài))開始。
當(dāng)讀卡器檢測到磁條在讀卡器頭上移動時,它開始掃描讀卡。它將數(shù)據(jù)線驅(qū)動為低電平,以通知主站刷卡已經(jīng)開始。
主站的響應(yīng)是將STROBE驅(qū)動為高電平,然后再次降低。
讀卡器將數(shù)據(jù)再次驅(qū)動高電平。
讀卡周期完成后,讀卡器再次將數(shù)據(jù)驅(qū)動為低電平。此操作告知主節(jié)點刷卡已完成,并且卡數(shù)據(jù)已準備好打卡。
// Wait for the DATA line to be driven low by the card reader. void waitForDataLow() { int i = 0xFF; dataHigh(); // Make sure that DATA is floating high. while ((i & 1) == 1) { i = P0; } } .... resetCardReader(); printf("\r\n"); printf("Waiting for card swipe...\r\n"); printf("\r\n"); waitForDataLow(); // DATA low indicates that card swipe has begun. strobeHigh(); longDelay(); strobeLow(); longDelay(); waitForDataLow(); // DATA low indicates that card swipe is complete.
讀取和解碼卡數(shù)據(jù)
刷卡完成并且所有卡數(shù)據(jù)由讀卡器ASIC解碼和存儲后,讀卡器將DATA線驅(qū)動為低電平。如上所述,此操作會提醒DS5250卡數(shù)據(jù)已準備好打卡。此時,DS5250可以按順序檢索卡數(shù)據(jù)中的每個位,方法是將STROBE驅(qū)動為高電平,然后驅(qū)動低電平,以便每個位輸出。在STROBE被驅(qū)動為高電平然后被驅(qū)動為低電平之后,下一個位由讀卡器ASIC在數(shù)據(jù)線上計時。ASIC 將數(shù)據(jù)驅(qū)動高電平 0 位,將數(shù)據(jù)驅(qū)動低電平 1 位。
// Clock a single bit value out of the card reader by driving STROBE high, // then low, and reading the DATA line. int readBit() { int i; strobeHigh(); // Drive STROBE high. strobeLow(); // Drive STROBE low (DATA line now contains bit). i = P0; if ((i & 1) == 0) { return 1; // Low on DATA line indicates a 1 bit. } else { return 0; // High on DATA line indicates a 0 bit. } }
從讀卡器輸出的前 16 位是一個“前導(dǎo)碼”,指示讀卡器 ASIC 的版本。應(yīng)用程序可以丟棄這些位,因為它們不表示卡數(shù)據(jù)。
翻譯軌道 A
在 16 位前導(dǎo)碼之后,DATA 線路上時鐘輸出的下一個 704 位包含從磁條卡上的磁道 A 讀取的數(shù)據(jù)。使用標(biāo)準 ISO 格式編碼時,磁道 A 最多包含 76 個字符,使用 7 位字符集,其中包括字母數(shù)字和各種其他符號。
每個 7 位字符首先輸出最低有效位 (LSB)。最高位(即第七位)是奇偶校驗位,可以選擇用于驗證卡數(shù)據(jù)的完整性。不考慮奇偶校驗位,其余 6 位定義可在磁道 A 上編碼的 64 個字符之一。例如,000000b 表示空格字符,000001b 表示感嘆號。char7bit[64] 字符數(shù)組顯示在下面的代碼中。
// 0123456789012345678901234567890123456789012345678901234567890 123
char char7bit[64] =
" !'#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
// Clock out and decode a 7-bit character from the track memory, returning the
// character value. 7-bit (alphanumeric) characters are found on Track A only.
char read7BitChar()
{
int i, c;
// Each character is composed of 7 bits, which we clock out of the track memory
// beginning with the least significant bit. Bit 7 is parity, which is ignored.
c = 0;
for (i = 1; i < 128; i *= 2) {
c |= (readBit() * i);
}
c &= 0x3F;
return char7bit[c]; // Decode/return the character using the 7-bit table.
}
....
// Track A - 76 characters, 7 bits per alphanumberic character including parity.
printf("Track A > ");
for (i = 0; i < 76; i++) {
putchar(read7BitChar());
}
printf("\r\n\r\n");
// At this point, we have read 532 bits of the 704-bit Track A memory on the
// card reader IC. Flush the remaining 172 bits.
for (i = 0; i < 172; i++) {
readBit();
}
軌道 A 上保存的實際數(shù)據(jù)因卡類型而異。此外,軌道 A 可以包含字母字符。因此,軌道A通常用于存儲持卡人的姓名,可能的地址,帳號和其他數(shù)字信息。如上面的代碼所示,在時鐘輸出磁道B數(shù)據(jù)之前,必須讀出磁道A存儲器的所有704位(即使并非所有位都包含編碼數(shù)據(jù))。
翻譯軌道 B
磁道 B 的編碼與磁道 A 類似,不同之處在于這些字符是 5 位(4 位,加 1 位奇偶校驗位)編碼,而不是 7 位。軌道 B 字符集僅包含數(shù)字字符和符號,如下面的 char5bit[16] 字符數(shù)組所示。
// 0123456789012345
char char5bit[16] = "0123456789:;<=>?";
// Clock out and decode a 5-bit character from the track memory, returning the
// character value. 5-bit (numeric+symbol) characters are found on Tracks B and C.
char read5BitChar()
{
int i, c;
// Each character is composed of 5 bits, which we clock out of the track memory
// beginning with the least significant bit. Bit 5 is parity, which is ignored.
c = 0;
for (i = 1; i < 32; i *= 2) {
c |= (readBit() * i);
}
c &= 0x0F;
return char5bit[c]; // Decode/return the character using the 5-bit table.
}
....
// Track B - 40 characters, 5 bits per numeric/symbol character including parity.
printf("Track B > ");
for (i = 0; i < 40; i++) {
putchar(read5BitChar());
}
printf("\r\n\r\n");
與磁道 A 結(jié)束時一樣,在繼續(xù)讀取磁道 C 之前,必須讀取磁道 B 存儲器中的所有剩余位(如果需要磁道 C)。由于代碼已經(jīng)從磁道 B 存儲器讀取了 200 位(40 個字符 x 5 位),因此在訪問磁道 C 數(shù)據(jù)之前,必須額外輸出 504 位。
翻譯軌道 C
磁道 C 以與磁道 B 相同的方式編碼,并使用與磁道 B 相同的字符集,最多 107 個 編碼的 7 位字符。軌道C最初旨在包含一個可重寫的數(shù)據(jù)區(qū)域以支持離線金融交易,但它并不常用。大多數(shù)磁條卡不包含磁道C上的編碼數(shù)據(jù)。
結(jié)論
磁條卡用于各種金融、訪問控制、政府和儲值應(yīng)用。通過在DS5250評估板中增加一個簡單的MagTek刷卡讀卡器和少量支持硬件,可以開發(fā)將磁條卡讀取功能與安全微控制器的更高級別的安全性和加密功能相結(jié)合的應(yīng)用。使用Keil的μVision C編譯器,可以在DS5250安全微控制器上輕松實現(xiàn)磁條卡讀取和解碼演示的應(yīng)用。
審核編輯:郭婷
// Generate a long delay for card reset and read intervals.
void longDelay()
{
int i, j;
for (i = 1; i < 5; i++) {
for (j = 1; j < 5000; j++) {
;
}
}
}
// Generate a shorter delay (used between STROBE/DATA transitions).
void delay()
{
int i;
for (i = 1; i < 1000; i++) {
;
}
}
// Release the DATA line (P0.0) and allow it to float high.
void dataHigh()
{
P0 |= 0x01;
delay();
}
// Drive the DATA line (P0.0) low.
void dataLow()
{
P0 &= 0xFE;
delay();
}
// Release the STROBE line (P0.1) and allow it to float high.
void strobeHigh()
{
P0 |= 0x02;
delay();
}
// Drive the STROBE line (P0.1) low.
void strobeLow()
{
P0 &= 0xFD;
delay();
}
void resetCardReader()
{
dataHigh();
strobeHigh();
longDelay();
dataLow(); // Force DATA low.
longDelay();
strobeLow(); // Drive STROBE low, then high again.
strobeHigh();
strobeLow(); // Drive STROBE low, then release DATA.
dataHigh();
longDelay();
strobeHigh(); // Drive STROBE low and high again two more times
strobeLow(); // to complete the reset and leave the card reader
strobeHigh(); // in the ready state, prepared to scan a card.
strobeLow();
}
檢測刷卡
一旦讀卡器重置并布防,它就可以接受刷卡了。MagTek 讀卡器在刷卡時執(zhí)行整個讀卡周期;主微控制器無需干預(yù)??l上所有三個磁道(磁道 A、磁道 B 和磁道 C)的全部內(nèi)容都存儲在讀卡器 IC 上。在讀卡周期結(jié)束后,主微控制器可以一次一位地輸出這些數(shù)據(jù)。
讀卡器經(jīng)歷一個握手周期,以通知主設(shè)備何時開始讀卡并完成。
- 循環(huán)從頻閃低電平和數(shù)據(jù)高浮動(空閑狀態(tài))開始。
- 當(dāng)讀卡器檢測到磁條在讀卡器頭上移動時,它開始掃描讀卡。它將數(shù)據(jù)線驅(qū)動為低電平,以通知主站刷卡已經(jīng)開始。
- 主站的響應(yīng)是將STROBE驅(qū)動為高電平,然后再次降低。
- 讀卡器將數(shù)據(jù)再次驅(qū)動高電平。
- 讀卡周期完成后,讀卡器再次將數(shù)據(jù)驅(qū)動為低電平。此操作告知主節(jié)點刷卡已完成,并且卡數(shù)據(jù)已準備好打卡。
// Wait for the DATA line to be driven low by the card reader.
void waitForDataLow()
{
int i = 0xFF;
dataHigh(); // Make sure that DATA is floating high.
while ((i & 1) == 1) {
i = P0;
}
}
....
resetCardReader();
printf("\r\n");
printf("Waiting for card swipe...\r\n");
printf("\r\n");
waitForDataLow(); // DATA low indicates that card swipe has begun.
strobeHigh();
longDelay();
strobeLow();
longDelay();
waitForDataLow(); // DATA low indicates that card swipe is complete.
讀取和解碼卡數(shù)據(jù)
刷卡完成并且所有卡數(shù)據(jù)由讀卡器ASIC解碼和存儲后,讀卡器將DATA線驅(qū)動為低電平。如上所述,此操作會提醒DS5250卡數(shù)據(jù)已準備好打卡。此時,DS5250可以按順序檢索卡數(shù)據(jù)中的每個位,方法是將STROBE驅(qū)動為高電平,然后驅(qū)動低電平,以便每個位輸出。在STROBE被驅(qū)動為高電平然后被驅(qū)動為低電平之后,下一個位由讀卡器ASIC在數(shù)據(jù)線上計時。ASIC 將數(shù)據(jù)驅(qū)動高電平 0 位,將數(shù)據(jù)驅(qū)動低電平 1 位。
// Clock a single bit value out of the card reader by driving STROBE high,
// then low, and reading the DATA line.
int readBit()
{
int i;
strobeHigh(); // Drive STROBE high.
strobeLow(); // Drive STROBE low (DATA line now contains bit).
i = P0;
if ((i & 1) == 0) {
return 1; // Low on DATA line indicates a 1 bit.
} else {
return 0; // High on DATA line indicates a 0 bit.
}
}
從讀卡器輸出的前 16 位是一個“前導(dǎo)碼”,指示讀卡器 ASIC 的版本。應(yīng)用程序可以丟棄這些位,因為它們不表示卡數(shù)據(jù)。
翻譯軌道 A
在 16 位前導(dǎo)碼之后,DATA 線路上時鐘輸出的下一個 704 位包含從磁條卡上的磁道 A 讀取的數(shù)據(jù)。使用標(biāo)準 ISO 格式編碼時,磁道 A 最多包含 76 個字符,使用 7 位字符集,其中包括字母數(shù)字和各種其他符號。
每個 7 位字符首先輸出最低有效位 (LSB)。最高位(即第七位)是奇偶校驗位,可以選擇用于驗證卡數(shù)據(jù)的完整性。不考慮奇偶校驗位,其余 6 位定義可在磁道 A 上編碼的 64 個字符之一。例如,000000b 表示空格字符,000001b 表示感嘆號。char7bit[64]字符數(shù)組顯示在下面的代碼中。
// 0123456789012345678901234567890123456789012345678901234567890 123
char char7bit[64] =
" !'#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
// Clock out and decode a 7-bit character from the track memory, returning the
// character value. 7-bit (alphanumeric) characters are found on Track A only.
char read7BitChar()
{
int i, c;
// Each character is composed of 7 bits, which we clock out of the track memory
// beginning with the least significant bit. Bit 7 is parity, which is ignored.
c = 0;
for (i = 1; i < 128; i *= 2) {
c |= (readBit() * i);
}
c &= 0x3F;
return char7bit[c]; // Decode/return the character using the 7-bit table.
}
....
// Track A - 76 characters, 7 bits per alphanumberic character including parity.
printf("Track A > ");
for (i = 0; i < 76; i++) {
putchar(read7BitChar());
}
printf("\r\n\r\n");
// At this point, we have read 532 bits of the 704-bit Track A memory on the
// card reader IC. Flush the remaining 172 bits.
for (i = 0; i < 172; i++) {
readBit();
}
軌道 A 上保存的實際數(shù)據(jù)因卡類型而異。此外,軌道 A 可以包含字母字符。因此,軌道A通常用于存儲持卡人的姓名,可能的地址,帳號和其他數(shù)字信息。如上面的代碼所示,在時鐘輸出磁道B數(shù)據(jù)之前,必須讀出磁道A存儲器的所有704位(即使并非所有位都包含編碼數(shù)據(jù))。
翻譯軌道 B
磁道 B 的編碼與磁道 A 類似,不同之處在于這些字符是 5 位(4 位,加 1 位奇偶校驗位)編碼,而不是 7 位。軌道 B 字符集僅包含數(shù)字字符和符號,如下面的char5bit[16]字符數(shù)組所示。
// 0123456789012345
char char5bit[16] = "0123456789:;<=>?";
// Clock out and decode a 5-bit character from the track memory, returning the
// character value. 5-bit (numeric+symbol) characters are found on Tracks B and C.
char read5BitChar()
{
int i, c;
// Each character is composed of 5 bits, which we clock out of the track memory
// beginning with the least significant bit. Bit 5 is parity, which is ignored.
c = 0;
for (i = 1; i < 32; i *= 2) {
c |= (readBit() * i);
}
c &= 0x0F;
return char5bit[c]; // Decode/return the character using the 5-bit table.
}
....
// Track B - 40 characters, 5 bits per numeric/symbol character including parity.
printf("Track B > ");
for (i = 0; i < 40; i++) {
putchar(read5BitChar());
}
printf("\r\n\r\n");
與磁道 A 結(jié)束時一樣,在繼續(xù)讀取磁道 C 之前,必須讀取磁道 B 存儲器中的所有剩余位(如果需要磁道 C)。由于代碼已經(jīng)從磁道 B 存儲器讀取了 200 位(40 個字符 x 5 位),因此在訪問磁道 C 數(shù)據(jù)之前,必須額外輸出 504 位。
翻譯軌道 C
磁道 C 以與磁道 B 相同的方式編碼,并使用與磁道 B 相同的字符集,最多 107 個 編碼的 7 位字符。軌道C最初旨在包含一個可重寫的數(shù)據(jù)區(qū)域以支持離線金融交易,但它并不常用。大多數(shù)磁條卡不包含磁道C上的編碼數(shù)據(jù)。
結(jié)論
磁條卡用于各種金融、訪問控制、政府和儲值應(yīng)用。通過在DS5250評估板中增加一個簡單的MagTek刷卡讀卡器和少量支持硬件,可以開發(fā)將磁條卡讀取功能與安全微控制器的更高級別的安全性和加密功能相結(jié)合的應(yīng)用。使用Keil的μVision C編譯器,可以在DS5250安全微控制器上輕松實現(xiàn)磁條卡讀取和解碼演示的應(yīng)用。
-
微控制器
+關(guān)注
關(guān)注
48文章
8196瀏覽量
160535 -
解碼器
+關(guān)注
關(guān)注
9文章
1199瀏覽量
42663 -
讀卡器
+關(guān)注
關(guān)注
2文章
459瀏覽量
40979
發(fā)布評論請先 登錄
電腦相關(guān)的讀卡器
高速安全微控制器DS5250電子資料
DS5250 pdf datasheet
DS5250中文資料 (高速安全微控制器)
DS5250與磁卡讀卡器的連接
利用DS5250產(chǎn)生RSA密鑰
DS5250微控制器的模冪時序
利用DS5250產(chǎn)生RSA密鑰
使用Keil C編譯器處理DS5250
通過將DS5250用作安全協(xié)處理器來提高系統(tǒng)安全性

DS5250與磁條讀卡器接口
評論