M1卡就是Mifare非接觸式感應(yīng)卡,M1卡數(shù)據(jù)保存期為10年,可改寫10萬次,讀無限次。無電源,自帶天線,工作頻率為13.56MHZ.M1卡內(nèi)含加密控制邏輯和通訊邏輯電路。M1卡主要有兩種,一種是S50和一種是S70。
M1卡的工作原理
讀寫器向M1卡發(fā)一組固定頻率的電磁波,卡片內(nèi)有一個 LC串聯(lián)諧振電路,其頻率與讀寫器發(fā)射的頻率相同,在電磁波的激勵下,LC諧振電路產(chǎn)生共振,從而使電容內(nèi)有了電荷,在這個電容的另一端,接有一個單向?qū)ǖ碾娮颖?,將電容?nèi)的電荷送到另一個電容內(nèi)儲存,當(dāng)所積累的電荷達到2V時,此電容可做為電源為其它電路提供工作電壓,將卡內(nèi)數(shù)據(jù)發(fā)射出去或接取讀寫器的數(shù)據(jù)。簡單地說,就是感應(yīng)產(chǎn)生電流來工作的一種卡片。
存儲結(jié)構(gòu)

第0扇區(qū)的塊0(即絕對地址0塊),它用于存放廠商代碼,已經(jīng)固化,不可更改。
每個扇區(qū)的塊0、塊1、塊2為數(shù)據(jù)塊,可用于存貯數(shù)據(jù)。數(shù)據(jù)塊可作兩種應(yīng)用:
★ 用作一般的數(shù)據(jù)保存,可以進行讀、寫操作。
★ 用作數(shù)據(jù)值,可以進行初始化值、加值、減值、讀值操作。
而每個扇區(qū)的控制塊,包括了密碼A、存取控制、密碼B。具體結(jié)構(gòu)如下:
控制塊的結(jié)構(gòu)
每個扇區(qū)都是獨立的,也就是說,每個扇區(qū)都可以設(shè)置獨立的密碼和數(shù)據(jù),從而實現(xiàn)一卡多用的好處,對于每個扇區(qū)的數(shù)據(jù)塊的數(shù)據(jù)寫入具有一定的格式要求,比如在用于余額計算的錢包功能時數(shù)據(jù)的格式為
數(shù)據(jù)塊格式
尋卡
首先我們用讀卡器讀卡時,讀卡器發(fā)送相應(yīng)的指令尋取感應(yīng)區(qū)內(nèi)的某一指定類型的卡片。
防沖撞
當(dāng)尋完卡后,就進入防沖撞,避免多卡亂像,此時讀取卡片序列號,對于卡片的序列號,經(jīng)過多次測驗可以確定它的格式為十六進制的4字節(jié)數(shù)組,網(wǎng)上很多資料并沒有說明此序列號的格式,所以在用單片機發(fā)送出去時必須轉(zhuǎn)換格式才能正常顯示。
選定卡片
選擇被選中的卡的序列號,并同時返回卡的容量代碼。
驗證卡片密碼
選定要處理的卡片之后,讀寫器就確定要訪問的扇區(qū)號,并對該扇區(qū)密碼進行密碼校驗,在三次相互認(rèn)證之后就可以通過加密流進行通訊。(在選擇另一扇區(qū)時,則必須進行另一扇區(qū)密碼校驗。)。一般的白卡的默認(rèn)密碼為6個0xFF數(shù)組,所以有些破解方法還是的破解密鑰才進行修改數(shù)值的。
讀取數(shù)據(jù)/寫入數(shù)據(jù)
驗證密碼后就能進行讀取相應(yīng)扇區(qū)的數(shù)據(jù)了。</br>
/////////////////////////////////////////////////////////////////////
//功 能:尋卡
//參數(shù)說明: req_code[IN]:尋卡方式
// 0x52 = 尋感應(yīng)區(qū)內(nèi)所有符合14443A標(biāo)準(zhǔn)的卡
// 0x26 = 尋未進入休眠狀態(tài)的卡
// pTagType[OUT]:卡片類型代碼
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返 回: 成功返回MI_OK //其中MI_OK=0
/////////////////////////////////////////////////////////////////////
`
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status; //status狀態(tài)
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; //存儲卡類型的數(shù)組
ClearBitMask(Status2Reg,0x08); //清RC522寄存器位函數(shù)
WriteRawRC(BitFramingReg,0x07); // 寫RC632寄存器函數(shù)
SetBitMask(TxControlReg,0x03); //置RC522寄存器位函數(shù)
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522 Buf,&unLen); //數(shù)組ucComMF522Buf已通過函數(shù)PcdComMF522()讀取得卡信息,其中unLen為數(shù)據(jù)長度
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1]; //使指針指向下一個地址
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:防沖撞
//參數(shù)說明: pSnr[OUT]:卡片序列號,4字節(jié)
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(unsigned char *pSnr) //防沖撞函數(shù)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) =ucComMF522Buf[i] ;
temp_ucTempbuf[i]=ucComMF522Buf[i];
if(temp_ucTempbuf[1]==16)
sen_char(temp_ucTempbuf[0]);
snr_check ^= ucComMF522Buf[i];
//sen_char(snr_check);
}
if (snr_check != ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:選定卡片
//參數(shù)說明: pSnr[IN]:卡片序列號,4字節(jié)
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdSelect(unsigned char *pSnr) //選定卡片函數(shù)
{
char status;
unsigned char i;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:驗證卡片密碼
//參數(shù)說明: auth_mode[IN]: 密碼驗證模式
// 0x60 = 驗證A密鑰
// 0x61 = 驗證B密鑰
// addr[IN]:塊地址
// pKey[IN]:密碼
// pSnr[IN]:卡片序列號,4字節(jié)
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr) //驗證卡片密碼
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
for (i=0; i<6; i++)
{ ucComMF522Buf[i+2] = *(pKey+i); }
for (i=0; i<6; i++)
{ ucComMF522Buf[i+8] = *(pSnr+i); }
status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:讀取M1卡一塊數(shù)據(jù)
//參數(shù)說明: addr[IN]:塊地址
// pData[OUT]:讀出的數(shù)據(jù),16字節(jié)
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRead(unsigned char addr,unsigned char *pData) //讀取M1卡一塊數(shù)據(jù)函數(shù)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
{
for (i=0; i<16; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}

