• 方案介紹
    • 一、環(huán)境介紹
    • 二、功能介紹
    • 三、MFR522介紹
    • 四、IC卡介紹
    • 五、核心代碼
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

STM32+MFRC522完成IC卡號(hào)讀取、密碼修改、數(shù)據(jù)讀寫(xiě)

01/30 08:38
4674
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請(qǐng)聯(lián)系.docx

共1個(gè)文件

一、環(huán)境介紹

MCU:??STM32F103ZET6

開(kāi)發(fā)軟件:?Keil5

非接觸式讀寫(xiě)卡模塊: MFRC522

完整工程源碼下載:
https://download.csdn.net/download/xiaolong1126626497/18905806

二、功能介紹

使用MFRC522模塊完成對(duì)IC卡卡號(hào)讀取、卡類(lèi)型區(qū)分、IC卡扇區(qū)密碼修改、扇區(qū)數(shù)據(jù)讀寫(xiě)等功能;底層采用SPI模擬時(shí)序,可以很方便的移植到其他設(shè)備,完成項(xiàng)目開(kāi)發(fā)。? 現(xiàn)在很多嵌入式方向的畢業(yè)設(shè)計(jì)經(jīng)常使用到該模塊,比如: 校園一卡通設(shè)計(jì)、水卡充值消費(fèi)設(shè)計(jì)、公交卡充值消費(fèi)設(shè)計(jì)等。

三、MFR522介紹

MF RC522 是應(yīng)用于13.56MHz 非接觸式通信中高集成度讀寫(xiě)卡系列芯片中的一員。是NXP 公司針對(duì)“三表”應(yīng)用推出的一款低電壓、低成本、體積小的非接觸式讀寫(xiě)卡芯片,是智能儀表和便攜式手持設(shè)備研發(fā)的較好選擇。

MF RC522 利用了先進(jìn)的調(diào)制和解調(diào)概念,完全集成了在13.56MHz 下所有類(lèi)型的被動(dòng)非接觸式通信方式和協(xié)議。支持 ISO14443A 的多層應(yīng)用。其內(nèi)部發(fā)送器部分可驅(qū)動(dòng)讀寫(xiě)器天線與ISO 14443A/MIFARE卡和應(yīng)答機(jī)的通信,無(wú)需其它的電路。接收器部分提供一個(gè)堅(jiān)固而有效的解調(diào)和解碼電路,用于處理ISO14443A 兼容的應(yīng)答器信號(hào)。數(shù)字部分處理ISO14443A 幀和錯(cuò)誤檢測(cè)(奇偶 &CRC)。此外,它還支持快速CRYPTO1 加密算法,用于驗(yàn)證MIFARE 系列產(chǎn)品。MFRC522 支持MIFARE?更高速的非接觸式通信,雙向數(shù)據(jù)傳輸速率高達(dá)424kbit/s。

作為13.56MHz 高集成度讀寫(xiě)卡系列芯片家族的新成員,MF RC522 與MF RC500和 MF RC530 有不少相似之處,同時(shí)也具備諸多特點(diǎn)和差異。它與主機(jī)間的通信采用連線較少的串行通信,且可根據(jù)不同的用戶(hù)需求,選取SPI、I2C 或串行UART(類(lèi)似RS232)模式之一,有利于減少連線,縮小PCB 板體積,降低成本。

四、IC卡介紹

非接觸式IC卡又稱(chēng)射頻卡,由IC芯片、感應(yīng)天線組成,封裝在一個(gè)標(biāo)準(zhǔn)的PVC卡片內(nèi),芯片及天線無(wú)任何外露部分。是世界上最近幾年發(fā)展起來(lái)的一項(xiàng)新技術(shù),它成功的將射頻識(shí)別技術(shù)和IC卡技術(shù)結(jié)合起來(lái),結(jié)束了無(wú)源(卡中無(wú)電源)和免接觸這一難題,是電子器件領(lǐng)域的一大突破。卡片在一定距離范圍(通常為5—10cm)靠近讀寫(xiě)器表面,通過(guò)無(wú)線電波的傳遞來(lái)完成數(shù)據(jù)的讀寫(xiě)操作。

射頻讀寫(xiě)器向IC卡發(fā)一組固定頻率的電磁波,卡片內(nèi)有一個(gè)LC串聯(lián)諧振電路,其頻率與讀寫(xiě)器發(fā)射的頻率相同,這樣在電磁波激勵(lì)下,LC諧振電路產(chǎn)生共振,從而使電容內(nèi)有了電荷;在這個(gè)電荷的另一端,接有一個(gè)單向?qū)ǖ碾娮颖茫瑢㈦娙輧?nèi)的電荷送到另一個(gè)電容內(nèi)存儲(chǔ),當(dāng)所積累的電荷達(dá)到2V時(shí),此電容可作為電源為其它電路提供工作電壓,將卡內(nèi)數(shù)據(jù)發(fā)射出去或接受讀寫(xiě)器的數(shù)據(jù)。

非接觸性IC卡與讀卡器之間通過(guò)無(wú)線電波來(lái)完成讀寫(xiě)操作。二者之間的通訊頻率為13.56MHZ。非接觸性IC卡本身是無(wú)源卡,當(dāng)讀寫(xiě)器對(duì)卡進(jìn)行讀寫(xiě)操作時(shí),讀寫(xiě)器發(fā)出的信號(hào)由兩部分疊加組成:一部分是電源信號(hào),該信號(hào)由卡接收后,與本身的L/C產(chǎn)生一個(gè)瞬間能量來(lái)供給芯片工作。另一部分則是指令和數(shù)據(jù)信號(hào),指揮芯片完成數(shù)據(jù)的讀取、修改、儲(chǔ)存等,并返回信號(hào)給讀寫(xiě)器,完成一次讀寫(xiě)操作。讀寫(xiě)器則一般由單片機(jī),專(zhuān)用智能模塊和天線組成,并配有與PC的通訊接口,打印口,I/O口等,以便應(yīng)用于不同的領(lǐng)域。

M1卡詳細(xì)指標(biāo)

M1卡是指M1芯片,是指菲利浦下屬子公司恩智浦出品的芯片縮寫(xiě),全稱(chēng)為NXP Mifare1系列,常用的有S50及S70兩種型號(hào)。

M1(S50)卡詳細(xì)規(guī)格:

  1. 芯片類(lèi)型:PhilipsMifare1ICS50
  2. 存儲(chǔ)容量:8Kbit,16個(gè)分區(qū),每分區(qū)兩組密碼;
  3. 工作頻率:13.56?MHz;
  4. 通訊速率:106KBoud;
  5. 讀寫(xiě)距離:2.5~10cm;
  6. 讀寫(xiě)時(shí)間:1~2ms;
  7. 工作溫度:-20℃~55℃;
  8. 擦寫(xiě)壽命:>100,000次;
  9. 數(shù)據(jù)保存:>10年;
  10. 外形尺寸:ISO標(biāo)準(zhǔn)卡85.6x54x0.82;
  11. 封裝材料:PVC、PET、PETG、0.13mm銅線;

Mifare S50和Mifare S70又常被稱(chēng)為Mifare Standard、Mifare Classic、MF1,是遵守ISO14443A標(biāo)準(zhǔn)的卡片中應(yīng)用最為廣、影響力最大的的一員。而Mifare S70的容量是S50的4倍,S50的容量是1K字節(jié),S70的容量為4K字節(jié)。

讀寫(xiě)器對(duì)卡片的操作時(shí)序和操作命令,二者完全一致。??? Mifare S50和Mifare S70的每張卡片都有一個(gè)4字節(jié)的全球唯一序列號(hào),卡上數(shù)據(jù)保存期為10年,可改寫(xiě)10萬(wàn)次,讀無(wú)限次。一般的應(yīng)用中,不用考慮卡片是否會(huì)被讀壞寫(xiě)壞的問(wèn)題,

當(dāng)然暴力硬損壞除外。 Mifare S50和Mifare S70的區(qū)別主要有兩個(gè)方面。一是讀寫(xiě)器對(duì)卡片發(fā)出請(qǐng)求命令,二者應(yīng)答返回的卡類(lèi)型(ATQA)字節(jié)不同。Mifare S50的卡類(lèi)型(ATQA)是0004H,Mifare S70的卡類(lèi)型(ATQA)是0002H。另一個(gè)區(qū)別就是二者的容量和內(nèi)存結(jié)構(gòu)不同。

M1卡分為16個(gè)扇區(qū),每個(gè)扇區(qū)由4塊(0、1、2、3)組成。實(shí)際操作時(shí),將16個(gè)扇區(qū)分為64個(gè)塊,按絕對(duì)地址編號(hào)為0-63。

結(jié)構(gòu)如下:

  1. 第0個(gè)扇區(qū)用于存放廠商代碼,意見(jiàn)固話,不可更改。
  2. 每個(gè)扇區(qū)的塊0、塊1、塊2為數(shù)據(jù)塊,可以用于存儲(chǔ)數(shù)據(jù)。數(shù)據(jù)塊可以進(jìn)行讀寫(xiě)操作。
  3. 每個(gè)扇區(qū)的塊3為控制塊,包括了密碼A、存儲(chǔ)控制、密碼B。具體結(jié)構(gòu)如下:

4. 每個(gè)扇區(qū)的密碼和控制位都是獨(dú)立的,可以根據(jù)實(shí)際需求設(shè)定各自的密碼及存取控制。存取控制為4個(gè)字節(jié),共32位,扇區(qū)中的每個(gè)塊(包括數(shù)據(jù)和控制塊)存取條件是由密碼和存取控制共同決定的,在存取控制中每個(gè)塊都有一個(gè)相應(yīng)的三個(gè)控制位。定義如下:

Mifare 1 S50 白卡讀寫(xiě)時(shí)一般步驟: 尋卡-->下載塊密碼--> 讀寫(xiě)塊數(shù)據(jù)。控制塊也是一樣。

? ? ?數(shù)據(jù)塊的訪問(wèn)權(quán)限設(shè)置表格:(根據(jù)自己需要的權(quán)限,完成上圖字節(jié)6、7、8的填充即可)

控制塊的讀寫(xiě)權(quán)限設(shè)置:(包含了對(duì)密碼A、控制權(quán)限、密碼的讀寫(xiě)權(quán)限)

? ? ? ? ? ?7? 6? 5? 4? 3? 2? 1? 0

字節(jié)6 1? 1? 1? 1? 1? 1? 1? 1

字節(jié)7 0? 0? 0? 0? 1? 1? 1? 1

字節(jié)8 0? 0? 0? 0? 0? 0? 0? 0

字節(jié)9

設(shè)置的控制權(quán)限如下:0xFF 0x0F 0x00 0x00

代表數(shù)據(jù)塊的權(quán)限: 驗(yàn)證密碼A或者密碼B都可以對(duì)數(shù)據(jù)塊進(jìn)行讀寫(xiě)操作或者加值鍵值操作。

2. 代表控制塊的權(quán)限

(1) 驗(yàn)證A密碼之后可以寫(xiě)A/B密碼,不能讀密碼。

可以讀控制字節(jié)(4個(gè)),無(wú)法寫(xiě)控制字節(jié)

可以讀寫(xiě)B(tài)密碼

(2) 驗(yàn)證B密碼之后,可以讀寫(xiě)A/B密碼,也可讀控制字節(jié),但無(wú)法寫(xiě)控制字節(jié)。

五、核心代碼

5.1? rc522.c

#include "sys.h"
#include "RFID_RC522.h"
#include "delay.h"
#include "string.h"
#include "usart.h"

/*
函數(shù)功能:移植接口--SPI時(shí)序讀寫(xiě)一個(gè)字節(jié)
函數(shù)參數(shù):data:要寫(xiě)入的數(shù)據(jù)
返 回 值:讀到的數(shù)據(jù)
*/
u8 RC522_SPI_ReadWriteOneByte(u8 tx_data)
{			  	 
	u8 rx_data=0;				 
  u8 i;
  for(i=0;i<8;i++)
	{
		RC522_SCLK=0;  
		if(tx_data&0x80){RC522_OUTPUT=1;}
		else {RC522_OUTPUT=0;}
		tx_data<<=1;	
		RC522_SCLK=1;
		rx_data<<=1;
		if(RC522_INPUT)rx_data|=0x01;
	}
	return rx_data; 
}


/*
函數(shù)功能:初始化RC522的IO口	 
*/
void RC522_IO_Init(void)
{
	RCC->APB2ENR|=1<<2;     //PA時(shí)鐘使能 
	RCC->APB2ENR|=1<<7;     //PF時(shí)鐘使能
	
	//PA5  時(shí)鐘 RC522_SCLK
	//PA6  輸入 RC522_INPUT
	//PA7  輸出 RC522_OUTPUT 
	GPIOA->CRL&=0x000FFFFF;
	GPIOA->CRL|=0x38300000;
	GPIOA->ODR|=0x3<<5;
	
	//RC522_RST <----->PF1--復(fù)位腳
	//RC522_SDA <----->PF0--片選腳
	GPIOF->CRL&=0xFFFFFF00;
	GPIOF->CRL|=0x00000033;
	GPIOF->ODR|=0x3<<0;
}	


/*
功能描述:選卡讀取卡存儲(chǔ)器容量
輸入?yún)?shù):serNum 傳入卡序列號(hào)
返 回 值:成功返回卡容量
*/
u8 RC522_MFRC522_SelectTag(u8 *serNum) //讀取卡存儲(chǔ)器容量
{     
	u8 i;     
	u8 status;     
	u8 size;     
	u8 recvBits;     
	u8 buffer[9];
	     
	buffer[0]=PICC_ANTICOLL1;	  //防撞碼1     
	buffer[1]=0x70;
	buffer[6]=0x00;						     
	for(i=0;i<4;i++)					
	{
		buffer[i+2]=*(serNum+i);	//buffer[2]-buffer[5]為卡序列號(hào)
		buffer[6]^=*(serNum+i);	  //卡校驗(yàn)碼
	}
	
	RC522_CalulateCRC(buffer,7,&buffer[7]);	//buffer[7]-buffer[8]為RCR校驗(yàn)碼
	RC522_ClearBitMask(Status2Reg,0x08);
	status=RC522_PcdComMF522(PCD_TRANSCEIVE,buffer,9,buffer,&recvBits);
	
	if((status==MI_OK)&&(recvBits==0x18))    
		size=buffer[0];     
	else    
		size=0;
	
	return size; 
}


/*
延時(shí)函數(shù),納秒級(jí)
*/
void RC522_Delay(u32 ns)
{
  u32 i;
  for(i=0;i<ns;i++)
  {
    __nop();
    __nop();
    __nop();
  }
}


/*
函數(shù)功能:RC522芯片初始化
*/
void RC522_Init(void)
{
  RC522_IO_Init();	//RC522初始化
  RC522_PcdReset();  			//復(fù)位RC522 
  RC522_PcdAntennaOff();	//關(guān)閉天線
  DelayMs(2);  		  //延時(shí)2毫秒
  RC522_PcdAntennaOn();		//開(kāi)啟天線
  M500PcdConfigISOType('A'); //設(shè)置RC632的工作方式
}


/*
函數(shù)功能:復(fù)位RC522
*/
void RC522_Reset(void)
{
  RC522_PcdReset();				//復(fù)位RC522
  RC522_PcdAntennaOff();	//關(guān)閉天線
  DelayMs(2);  		  //延時(shí)2毫秒
  RC522_PcdAntennaOn();		//開(kāi)啟天線  	
}     


/*
功    能: 尋卡
參數(shù)說(shuō)明: req_code[IN]:尋卡方式
                0x52   = 尋感應(yīng)區(qū)內(nèi)所有符合14443A標(biāo)準(zhǔn)的卡
                0x26   = 尋未進(jìn)入休眠狀態(tài)的卡
          			pTagType[OUT]:卡片類(lèi)型代碼
                0x4400 = Mifare_UltraLight
                0x0400 = Mifare_One(S50)
                0x0200 = Mifare_One(S70)
                0x0800 = Mifare_Pro(X)
                0x4403 = Mifare_DESFire
返 回 值: 成功返回MI_OK
*/
char RC522_PcdRequest(u8 req_code,u8 *pTagType)
{
	char status;  
	u8 unLen;
	u8 ucComMF522Buf[MAXRLEN];  	   // MAXRLEN  18

	RC522_ClearBitMask(Status2Reg,0x08);	//清RC522寄存器位,/接收數(shù)據(jù)命令
	RC522_WriteRawRC(BitFramingReg,0x07); //寫(xiě)RC632寄存器
	RC522_SetBitMask(TxControlReg,0x03);  //置RC522寄存器位
 
	ucComMF522Buf[0]=req_code; 	    //尋卡方式
	
	status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); //通過(guò)RC522和ISO14443卡通訊
	
	if((status==MI_OK)&&(unLen==0x10))
	{    
		*pTagType=ucComMF522Buf[0];
		*(pTagType+1)=ucComMF522Buf[1];
	}
	else
	{
	  status = MI_ERR;
	}  
	return status;
}


/*
功    能: 防沖撞
參數(shù)說(shuō)明: pSnr[OUT]:卡片序列號(hào),4字節(jié)
返    回: 成功返回MI_OK
*/
char RC522_PcdAnticoll(u8 *pSnr)
{
    char status;
    u8 i,snr_check=0;
    u8 unLen;
    u8 ucComMF522Buf[MAXRLEN]; 
    
    RC522_ClearBitMask(Status2Reg,0x08);  //清RC522寄存器位 
    RC522_WriteRawRC(BitFramingReg,0x00); //寫(xiě)
    RC522_ClearBitMask(CollReg,0x80);     //清
 
    ucComMF522Buf[0]=PICC_ANTICOLL1;   //PICC_ANTICOLL1 = 0x93
    ucComMF522Buf[1]=0x20;
	
    status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); //0x0c,通過(guò)RC522和ISO14443卡通訊
											 //PCD_TRANSCEIVE =發(fā)送并接收數(shù)據(jù)
											 //2:寫(xiě)入卡里的數(shù)據(jù)字節(jié)長(zhǎng)度
											 //ucComMF522Buf:存放數(shù)據(jù)的地址
											 //unLen:從卡里讀出的數(shù)據(jù)長(zhǎng)度
    if(status==MI_OK)
    {
    	 for(i=0;i<4;i++)
			 {   
					 *(pSnr+i)=ucComMF522Buf[i];  //把讀到的卡號(hào)賦值給pSnr
					 snr_check^=ucComMF522Buf[i];
			 }
			 if(snr_check!=ucComMF522Buf[i])
			 {
					status = MI_ERR;
			 }
    }   
    RC522_SetBitMask(CollReg,0x80);
    return status;
}


/*
功    能:選定卡片
參數(shù)說(shuō)明:pSnr[IN]:卡片序列號(hào),4字節(jié)
返    回:成功返回MI_OK
*/
char RC522_PcdSelect(u8 *pSnr)
{
    char status;
    u8 i;
    u8 unLen;
    u8 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);
    }
		
    RC522_CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]); //用MF522計(jì)算CRC16函數(shù),校驗(yàn)數(shù)據(jù)
    RC522_ClearBitMask(Status2Reg,0x08);	                //清RC522寄存器位
    status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    if((status==MI_OK)&&(unLen==0x18))status=MI_OK;
    else status=MI_ERR;
		
    return status;
}


/*
功    能:驗(yàn)證卡片密碼
參數(shù)說(shuō)明:auth_mode[IN]: 密碼驗(yàn)證模式
                 0x60 = 驗(yàn)證A密鑰
                 0x61 = 驗(yàn)證B密鑰 
          addr[IN]:塊地址
          pKey[IN]:扇區(qū)密碼
          pSnr[IN]:卡片序列號(hào),4字節(jié)
返    回:成功返回MI_OK
*/               
char RC522_PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr)
{
    char status;
    u8 unLen;
    u8 ucComMF522Buf[MAXRLEN];  //MAXRLEN  18(數(shù)組的大小)
	  
	  //驗(yàn)證模式+塊地址+扇區(qū)密碼+卡序列號(hào)   
    ucComMF522Buf[0]=auth_mode;		
    ucComMF522Buf[1]=addr;				
    memcpy(&ucComMF522Buf[2],pKey,6); //拷貝,復(fù)制
    memcpy(&ucComMF522Buf[8],pSnr,4); 
	 
    status=RC522_PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if((status!= MI_OK)||(!(RC522_ReadRawRC(Status2Reg)&0x08)))status = MI_ERR;
    return status;
}


/*
功    能:讀取M1卡一塊數(shù)據(jù)
參數(shù)說(shuō)明: 
					addr:塊地址
          p   :讀出的塊數(shù)據(jù),16字節(jié)
返    回:成功返回MI_OK
*/ 
char RC522_PcdRead(u8 addr,u8 *p)
{
    char status;
    u8 unLen;
    u8 i,ucComMF522Buf[MAXRLEN]; //18

    ucComMF522Buf[0]=PICC_READ;
    ucComMF522Buf[1]=addr;
    RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);//通過(guò)RC522和ISO14443卡通訊
    if((status==MI_OK&&(unLen==0x90)))
    {
        for(i=0;i<16;i++)
				{
						*(p +i)=ucComMF522Buf[i];
				}
    }
    else
    {   
			status=MI_ERR;
		}
    return status;
}


/*
功    能:寫(xiě)數(shù)據(jù)到M1卡指定塊
參數(shù)說(shuō)明:addr:塊地址
          p   :向塊寫(xiě)入的數(shù)據(jù),16字節(jié)
返    回:成功返回MI_OK
*/                  
char RC522_PcdWrite(u8 addr,u8 *p)
{
    char status;
    u8 unLen;
    u8 i,ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0]=PICC_WRITE;// 0xA0 //寫(xiě)塊
    ucComMF522Buf[1]=addr;      //塊地址
    RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if((status!= MI_OK)||(unLen != 4)||((ucComMF522Buf[0]&0x0F)!=0x0A))
    {
				status = MI_ERR;
		}
		
    if(status==MI_OK)
    {
        for(i=0;i<16;i++)//向FIFO寫(xiě)16Byte數(shù)據(jù) 
        {    
        	ucComMF522Buf[i]=*(p +i);   
        }
        RC522_CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
        status = RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
        if((status != MI_OK)||(unLen != 4)||((ucComMF522Buf[0]&0x0F)!=0x0A))
        {   
					status = MI_ERR;   
				}
    }
    return status;
}


/*
功    能:命令卡片進(jìn)入休眠狀態(tài)
返    回:成功返回MI_OK
*/
char RC522_PcdHalt(void)
{
    u8 status;
    u8 unLen;
    u8 ucComMF522Buf[MAXRLEN]; //MAXRLEN==18
	  status=status;
    ucComMF522Buf[0]=PICC_HALT;
    ucComMF522Buf[1]=0;
    RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    return MI_OK;
}


/*
功    能:用MF522計(jì)算CRC16函數(shù)
參    數(shù):
				*pIn :要讀數(shù)CRC的數(shù)據(jù)
				len:-數(shù)據(jù)長(zhǎng)度
				*pOut:計(jì)算的CRC結(jié)果
*/
void RC522_CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )
{
    u8 i,n;
    RC522_ClearBitMask(DivIrqReg,0x04);  //CRCIrq = 0  
    RC522_WriteRawRC(CommandReg,PCD_IDLE);
    RC522_SetBitMask(FIFOLevelReg,0x80); //清FIFO指針
    
	  //向FIFO中寫(xiě)入數(shù)據(jù)  
		for(i=0;i<len;i++)
    {  
			RC522_WriteRawRC(FIFODataReg,*(pIn +i));  //開(kāi)始RCR計(jì)算
		}
		
		RC522_WriteRawRC(CommandReg,PCD_CALCCRC);   //等待CRC計(jì)算完成 
		i=0xFF;
    do 
    {
        n=RC522_ReadRawRC(DivIrqReg);
        i--;
    }
    while((i!=0)&&!(n&0x04));//CRCIrq = 1
	  
		//讀取CRC計(jì)算結(jié)果 
		pOut[0]=RC522_ReadRawRC(CRCResultRegL);
    pOut[1]=RC522_ReadRawRC(CRCResultRegM);
}


/*
功    能:復(fù)位RC522
返    回:成功返回MI_OK
*/
char RC522_PcdReset(void)
{
	  RC522_RST=1;   //PF1寫(xiě)1
    RC522_Delay(10);
	  RC522_RST=0;   //PF1清0
    RC522_Delay(10);
	  RC522_RST=1;	 //PF1寫(xiě)1
    RC522_Delay(10);
    RC522_WriteRawRC(CommandReg,PCD_RESETPHASE);  //寫(xiě)RC632寄存器,復(fù)位
	  RC522_WriteRawRC(CommandReg,PCD_RESETPHASE);	//寫(xiě)RC632寄存器,復(fù)位
    RC522_Delay(10);
    
    RC522_WriteRawRC(ModeReg,0x3D);             //和Mifare卡通訊,CRC初始值0x6363
    RC522_WriteRawRC(TReloadRegL,30);           //寫(xiě)RC632寄存器   
    RC522_WriteRawRC(TReloadRegH,0);
    RC522_WriteRawRC(TModeReg,0x8D);
    RC522_WriteRawRC(TPrescalerReg,0x3E);
	
	  RC522_WriteRawRC(TxAutoReg,0x40);//必須要
    return MI_OK;
}


/*
函數(shù)功能:設(shè)置RC632的工作方式 
*/
char M500PcdConfigISOType(u8 type)
{
   if(type=='A')                        //ISO14443_A
   { 
		 RC522_ClearBitMask(Status2Reg,0x08);     //清RC522寄存器位
		 RC522_WriteRawRC(ModeReg,0x3D);          //3F//CRC初始值0x6363
		 RC522_WriteRawRC(RxSelReg,0x86);         //84
		 RC522_WriteRawRC(RFCfgReg,0x7F);         //4F  //調(diào)整卡的感應(yīng)距離//RxGain = 48dB調(diào)節(jié)卡感應(yīng)距離  
		 RC522_WriteRawRC(TReloadRegL,30);        //tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
	   RC522_WriteRawRC(TReloadRegH,0);
		 RC522_WriteRawRC(TModeReg,0x8D);
	   RC522_WriteRawRC(TPrescalerReg,0x3E);
	   RC522_Delay(1000);
     RC522_PcdAntennaOn();		//開(kāi)啟天線 
   }
   else return 1;       //失敗,返回1
   return MI_OK;				//成功返回0
}


/*
功    能:讀RC632寄存器
參數(shù)說(shuō)明:Address[IN]:寄存器地址
返    回:讀出的值
*/
u8 RC522_ReadRawRC(u8 Address)
{
    u8 ucAddr;
    u8 ucResult=0;		
		RC522_CS=0;						//片選選中RC522
    ucAddr=((Address<<1)&0x7E)|0x80;
		RC522_SPI_ReadWriteOneByte(ucAddr);		  //發(fā)送命令
		ucResult=RC522_SPI_ReadWriteOneByte(0); //讀取RC522返回的數(shù)據(jù)
		RC522_CS=1;						   //釋放片選線(PF0)
		return ucResult;         //返回讀到的數(shù)據(jù)
}


/*
功    能:寫(xiě)RC632寄存器
參數(shù)說(shuō)明:Address[IN]:寄存器地址
          value[IN] :寫(xiě)入的值
*/
void RC522_WriteRawRC(u8 Address,u8 value)
{  
  u8 ucAddr;
	RC522_CS=0; //PF0寫(xiě) 0 (SDA)(SPI1片選線,低電平有效)
  ucAddr=((Address<<1)&0x7E); 
	RC522_SPI_ReadWriteOneByte(ucAddr); //SPI1發(fā)送一個(gè)字節(jié)
	RC522_SPI_ReadWriteOneByte(value);  //SPI1發(fā)送一個(gè)字節(jié)
	RC522_CS=1;										      //PF1寫(xiě)1(SDA)(SPI1片選線)
}


/*
功    能:置RC522寄存器位
參數(shù)說(shuō)明:reg[IN]:寄存器地址
          mask[IN]:置位值
*/
void RC522_SetBitMask(u8 reg,u8 mask)  
{
    char tmp=0x0;
    tmp=RC522_ReadRawRC(reg);					//讀RC632寄存器
    RC522_WriteRawRC(reg,tmp|mask);   //寫(xiě)RC632寄存器
}


/*
功    能:清RC522寄存器位
參數(shù)說(shuō)明:reg[IN]:寄存器地址
         mask[IN]:清位值
*/
void RC522_ClearBitMask(u8 reg,u8 mask)  
{
    char tmp=0x0;
    tmp=RC522_ReadRawRC(reg);        //讀RC632寄存器
    RC522_WriteRawRC(reg,tmp&~mask); // clear bit mask
} 


/*
功    能:通過(guò)RC522和ISO14443卡通訊
參數(shù)說(shuō)明:Command[IN]:RC522命令字
          pIn [IN]:通過(guò)RC522發(fā)送到卡片的數(shù)據(jù)
          InLenByte[IN]:發(fā)送數(shù)據(jù)的字節(jié)長(zhǎng)度
          pOut [OUT]:接收到的卡片返回?cái)?shù)據(jù)
          *pOutLenBit[OUT]:返回?cái)?shù)據(jù)的位長(zhǎng)度
*/
char RC522_PcdComMF522(u8 Command,u8 *pIn,u8 InLenByte,u8 *pOut,u8 *pOutLenBit)
{
    char status=MI_ERR;
    u8 irqEn=0x00;
    u8 waitFor=0x00;
    u8 lastBits;
    u8 n;
    u16 i;
	
    switch(Command)
    {
			case PCD_AUTHENT:    //驗(yàn)證密鑰
					 irqEn=0x12;
					 waitFor=0x10;
					 break;
			case PCD_TRANSCEIVE: //發(fā)送并接收數(shù)據(jù)
					 irqEn=0x77;
					 waitFor=0x30;
					 break;
			default:
					 break;
    }
    RC522_WriteRawRC(ComIEnReg,irqEn|0x80);	
    RC522_ClearBitMask(ComIrqReg,0x80);			//清所有中斷位
    RC522_WriteRawRC(CommandReg,PCD_IDLE);	
    RC522_SetBitMask(FIFOLevelReg,0x80);	 	//清FIFO緩存
    
    for(i=0;i<InLenByte;i++)
    {   
				RC522_WriteRawRC(FIFODataReg,pIn[i]);
		}
		
		RC522_WriteRawRC(CommandReg,Command);	 
		if(Command==PCD_TRANSCEIVE)
		{  
			RC522_SetBitMask(BitFramingReg,0x80);	 //開(kāi)始傳送
		}
    
		//有問(wèn)題,下面的循環(huán)
    //i = 600;//根據(jù)時(shí)鐘頻率調(diào)整,操作M1卡最大等待時(shí)間25ms
		  i=2000;
			do 
			{
				n=RC522_ReadRawRC(ComIrqReg);
				i--;
			}
			while((i!=0)&&!(n&0x01)&&!(n&waitFor));
				
			RC522_ClearBitMask(BitFramingReg,0x80);
			if(i!=0)
			{    
        if(!(RC522_ReadRawRC(ErrorReg)&0x1B))
        {
            status=MI_OK;
            if(n&irqEn&0x01)
            {
							status=MI_NOTAGERR;
						}
            if(Command==PCD_TRANSCEIVE)
            {
               	n=RC522_ReadRawRC(FIFOLevelReg);
              	lastBits=RC522_ReadRawRC(ControlReg)&0x07;
                if(lastBits)
                {
									*pOutLenBit=(n-1)*8+lastBits;
								}
                else
                {   
									*pOutLenBit=n*8;   
								}
								
                if(n==0)n=1;
                if(n>MAXRLEN)n=MAXRLEN;
                for(i=0; i<n; i++)
                {   
									pOut[i]=RC522_ReadRawRC(FIFODataReg);    
								}
            }
        }
        else
        {   
					status=MI_ERR;   
				}
    }
    RC522_SetBitMask(ControlReg,0x80);// stop timer now
    RC522_WriteRawRC(CommandReg,PCD_IDLE); 
    return status;
}


/*
函數(shù)功能:開(kāi)啟天線  
參    數(shù):每次啟動(dòng)或關(guān)閉天險(xiǎn)發(fā)射之間應(yīng)至少有1ms的間隔
*/
void RC522_PcdAntennaOn(void)
{
    u8 i;
    i=RC522_ReadRawRC(TxControlReg);
    if(!(i&0x03))
    {
        RC522_SetBitMask(TxControlReg,0x03);
    }
}


/*
函數(shù)功能:關(guān)閉天線  
參    數(shù):每次啟動(dòng)或關(guān)閉天險(xiǎn)發(fā)射之間應(yīng)至少有1ms的間隔
*/
void RC522_PcdAntennaOff(void)
{
	RC522_ClearBitMask(TxControlReg,0x03); //清RC522寄存器位
}

5.2 rc522.h

#ifndef RFID_RC522_H
#define RFID_RC522_H
#include "sys.h"

/*
RC522射頻模塊外部的接口:    
*1--SDA <----->PF0--片選腳
*2--SCK <----->PA5--時(shí)鐘線
*3--MOSI<----->PA7--輸出
*4--MISO<----->PA6--輸入
*5--懸空
*6--GND <----->GND
*7--RST <----->PF1--復(fù)位腳
*8--VCC <----->VCC
*/
#define RC522_OUTPUT PAout(7)
#define RC522_INPUT PAin(6)
#define RC522_SCLK PAout(5)
#define RC522_CS PFout(0)
#define RC522_RST PFout(1)


//MF522命令字
#define PCD_IDLE              0x00               //取消當(dāng)前命令
#define PCD_AUTHENT           0x0E               //驗(yàn)證密鑰
#define PCD_RECEIVE           0x08               //接收數(shù)據(jù)
#define PCD_TRANSMIT          0x04               //發(fā)送數(shù)據(jù)
#define PCD_TRANSCEIVE        0x0C               //發(fā)送并接收數(shù)據(jù)
#define PCD_RESETPHASE        0x0F               //復(fù)位
#define PCD_CALCCRC           0x03               //CRC計(jì)算


//Mifare_One卡片命令字
#define PICC_REQIDL           0x26               //尋天線區(qū)內(nèi)未進(jìn)入休眠狀態(tài),返回的是卡的類(lèi)型
#define PICC_REQALL           0x52               //尋天線區(qū)內(nèi)全部卡,返回的是卡的類(lèi)型
#define PICC_ANTICOLL1        0x93               //防沖撞
#define PICC_ANTICOLL2        0x95               //防沖撞
#define PICC_AUTHENT1A        0x60               //驗(yàn)證A密鑰
#define PICC_AUTHENT1B        0x61               //驗(yàn)證B密鑰   命令認(rèn)證代碼
#define PICC_READ             0x30               //讀塊
#define PICC_WRITE            0xA0               //寫(xiě)塊
#define PICC_DECREMENT        0xC0               //扣款
#define PICC_INCREMENT        0xC1               //充值
#define PICC_RESTORE          0xC2               //調(diào)塊數(shù)據(jù)到緩沖區(qū)
#define PICC_TRANSFER         0xB0               //保存緩沖區(qū)中數(shù)據(jù)
#define PICC_HALT             0x50               //休眠

//MF522 FIFO長(zhǎng)度定義
#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
#define MAXRLEN  18


//MF522寄存器定義
// PAGE 0
#define     RFU00                 0x00    
#define     CommandReg            0x01    
#define     ComIEnReg             0x02    
#define     DivlEnReg             0x03    
#define     ComIrqReg             0x04    
#define     DivIrqReg             0x05
#define     ErrorReg              0x06    
#define     Status1Reg            0x07    
#define     Status2Reg            0x08    
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1     
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2    
#define     RFU20                 0x20  
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F

// PAGE 3      
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39  
#define     TestDAC2Reg           0x3A   
#define     TestADCReg            0x3B   
#define     RFU3C                 0x3C   
#define     RFU3D                 0x3D   
#define     RFU3E                 0x3E   
#define     RFU3F		  		        0x3F


//和MF522通訊時(shí)返回的錯(cuò)誤代碼
#define 	MI_OK                 0
#define 	MI_NOTAGERR           1
#define 	MI_ERR                2

#define	SHAQU1		0X01
#define	KUAI4			0X04
#define	KUAI7			0X07
#define	REGCARD		0xa1
#define	CONSUME		0xa2
#define READCARD	0xa3
#define ADDMONEY	0xa4

/*
    RC522各種驅(qū)動(dòng)函數(shù)
*/
u8 RC522_SPI_ReadWriteOneByte(u8 tx_data);
void RC522_IO_Init(void);
u8 RC522_MFRC522_SelectTag(u8 *serNum);
void RC522_Delay(u32 ns);
void RC522_Init(void);
void RC522_Reset(void);
char RC522_PcdRequest(u8 req_code,u8 *pTagType);
char RC522_PcdAnticoll(u8 *pSnr);
char RC522_PcdSelect(u8 *pSnr);
char RC522_PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr);
char RC522_PcdRead(u8 addr,u8 *p);
char RC522_PcdWrite(u8 addr,u8 *p);
char RC522_PcdHalt(void);
void RC522_CalulateCRC(u8 *pIn ,u8 len,u8 *pOut );
char RC522_PcdReset(void);
char M500PcdConfigISOType(u8 type);
char M500PcdConfigISOType(u8 type);
u8 RC522_ReadRawRC(u8 Address);
void RC522_WriteRawRC(u8 Address,u8 value);
void RC522_SetBitMask(u8 reg,u8 mask) ;
void RC522_ClearBitMask(u8 reg,u8 mask);
char RC522_PcdComMF522(u8 Command,u8 *pIn,u8 InLenByte,u8 *pOut,u8 *pOutLenBit);
void RC522_PcdAntennaOn(void);
void RC522_PcdAntennaOff(void);
#endif

  • 更多詳細(xì)資料請(qǐng)聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱(chēng)改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷(xiāo)售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷(xiāo)售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(chē)(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專(zhuān)用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車(chē)用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱(chēng)改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷(xiāo)售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷(xiāo)售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(chē)(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專(zhuān)用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車(chē)用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦