RFID MFRC522資料
單片機源程序如下:
- #include "rc522.h"
- #include "SPI.h"
- #include "stm32f10x.h"
- #include "delay.h"
- #include <string.h>
- #include <stdio.h> //sprintf頭文件
- #include "hw_config.h"
- /*************************************
- * 使用SPI與RC522通信
- *
- *
- **************************************/
- /********************************************************************************
- *函數功能:SPI發送數據
- *參數:待發送的數據
- *返回值:無
- *
- **********************************************************************************/
- void RC522_Send(u8 byte)
- {
- u8 counter;
- for(counter=0;counter<8;counter++)
- {
- if ( byte & 0x80 )
- RC522_MOSI_H();
- else
- RC522_MOSI_L();
- Delay_us(200);
- RC522_SCK_L();
- Delay_us(200);
- RC522_SCK_H();
- Delay_us(200);
- byte <<= 1;
- }
- }
- /*******************************************************************************************
- *函數功能:SPI讀函數
- *參數:無
- *返回值:讀到的數據
- *
- ********************************************************************************************/
- u8 RC522_Read( void )
- {
- u8 counter;
- u8 Data;
- for(counter=0;counter<8;counter++)
- {
- Data <<= 1;
- RC522_SCK_L();
- Delay_us(200);
- if (RC522_MISO_int() == 1)
- Data |= 0x01;
- Delay_us(200);
- RC522_SCK_H();
- Delay_us(200);
- }
- return Data;
-
- }
- /******************************************************************************************
- *函數功能:讀RC522寄存器
- *參數:address 寄存器的地址
- *返回值:寄存器的當前值
- *
- ******************************************************************************************/
- //用SPI讀RC522的數據格式是 0x msb(控制位 1位) 地址(6位) 日志(1位),
- //舉個例子 讀地址 0x0000 0110 的數據就要把他轉換成 0x1000 1100,首位1代表讀,0是寫,最后一位0是日志是規定。
- //隨意左移一位是確定地址,& 0x0111 1110(7e)的作用是保證此操作只有地址沒有變成奇奇怪怪的東西。然后 | 0x1000 0000 (80)就是確定第一位是1,也就是讀數據。
- //具體內容看官方的 《MFCR522數據手冊》 10.2 章節,中文文檔可能不太一樣
- u8 ReadRC(u8 address )
- {
- u8 Addr, Return;
- Addr=((address<<1)&0x7E)|0x80;//變化成有效的地址形式,最低位為0,最高位為1時候是,從MFRC522讀出數據。
- RC522_CS_Enable();
- RC522_Send(Addr);
- Return=RC522_Read();
- RC522_CS_Disable();
- return Return;
- }
- /*******************************************************************************************
- *函數功能:寫RC522寄存器
- *參數:Addresss 寄存器的地址
- Value 寫入寄存器的值
- *返回值:無
- *******************************************************************************************/
- void WriteRawRC(u8 Address,u8 Value)
- {
- u8 Addr;
-
- Addr =(Address<<1)&0x7E;//變化成有效的地址形式,最低位為0,最高位為0時候是,從MFRC522寫入數據。
-
- RC522_CS_Enable();
-
- RC522_Send(Addr);
-
- RC522_Send(Value);
-
- RC522_CS_Disable();
- }
- /*******************************************************************************************
- *函數功能:對RC522寄存器置位
- *參數:Reg 寄存器的紙質
- mask 置位的值
- *返回值:無
- *******************************************************************************************/
- void SetBitMask(u8 Reg,u8 Mask )
- {
- u8 Temp;
- Temp=ReadRC(Reg);
- WriteRawRC(Reg,Temp|Mask); // set bit mask
- }
- /*******************************************************************************************
- *函數功能:對RC522寄存器清零
- *參數:Reg RC522的地址
- Mask 清零的數據
- *返回值:無
- *******************************************************************************************/
- //讀取寄存器reg,保存在temp中;
- //將mask取反后與temp的內容作與運算,運算結果寫回寄存器reg中;
- //mask取反后原先為1的位變0,為0的位變1,所以、與運算后temp中對應mask中最初為1的位就被清零。
- void ClearBitMask(u8 Reg,u8 Mask )
- {
- u8 Temp;
- Temp=ReadRC(Reg);
- WriteRawRC(Reg,Temp&(~Mask)); // clear bit mask
-
- }
- /*******************************************************************************************
- *函數功能:開天線
- *參數:無
- *返回值:無
- *
- ********************************************************************************************/
- void PcdAntennaOn(void)
- {
- u8 temp;
-
- temp=ReadRC(TxControlReg);
-
- if (!(temp&0x03))
- SetBitMask(TxControlReg,0x03);
- }
- /*******************************************************************************************
- *函數功能:關閉天線
- *參數:無
- *返回值:
- *
- *******************************************************************************************/
- void PcdAntennaOff ( void )
- {
- ClearBitMask(TxControlReg,0x03 );
- }
- /*******************************************************************************************
- *函數功能:復位RC522
- *參數:無
- *返回值:無
- *
- *******************************************************************************************/
- void PcdReset(void)
- {
- RC522_Reset_Disable();
-
- Delay_us(1);
-
- RC522_Reset_Enable();
-
- Delay_us(1);
-
- RC522_Reset_Disable();
-
- Delay_us(1);
-
- WriteRawRC(CommandReg,0x0f);
-
- while(ReadRC(CommandReg)&0x10);
-
- Delay_us(1);
-
- WriteRawRC(ModeReg, 0x3D ); //定義發送和接收常用模式 和Mifare卡通訊,CRC初始值0x6363
-
- WriteRawRC(TReloadRegL,30); //16位定時器低位
- WriteRawRC(TReloadRegH,0); //16位定時器高位
-
- WriteRawRC(TModeReg,0x8D); //定義內部定時器的設置
-
- WriteRawRC(TPrescalerReg,0x3E); //設置定時器分頻系數
-
- WriteRawRC(TxAutoReg,0x40); //調制發送信號為100%ASK
-
- }
- /*******************************************************************************************
- *函數功能:設置RC522的工作方式
- *參數:CardType:工作方式
- *返回值:無
- *
- *******************************************************************************************/
- void M500PcdConfigISOType(u8 CardType)
- {
- if (CardType== 'A') //ISO14443_A
- {
- ClearBitMask(Status2Reg,0x08);
-
- WriteRawRC(ModeReg,0x3D);//3F
-
- WriteRawRC(RxSelReg,0x86);//84
-
- WriteRawRC(RFCfgReg,0x7F); //4F
-
- WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
-
- WriteRawRC(TReloadRegH,0);
-
- WriteRawRC(TModeReg,0x8D);
-
- WriteRawRC(TPrescalerReg,0x3E);
-
- Delay_us(2);
- PcdAntennaOn();//開天線
-
- }
-
- }
- /*******************************************************************************************
- *函數功能:通過RC522和ISO14443卡通訊
- *參數: Command,RC522的命令
- * intData,RC522發送到卡片的數據
- * intLen,發送數據的字節長度
- * outData,接收到的卡片返回數據
- * outLen,返回數據的長度
- *返回值:
- ********************************************************************************************/
- char PcdComMF522(u8 Command,u8 *intData,u8 intLen,u8 * Data,u32 * outLen )
- {
- char Status =Fault;
- u8 IrqEn = 0x00;
- u8 WaitFor = 0x00;
- u8 LastBits;
- u8 N;
- u32 L;
- switch (Command)
- {
- case PCD_AUTHENT: //Mifare認證
- IrqEn=0x12; //允許錯誤中斷請求ErrIEn 允許空閑中斷IdleIEn
- WaitFor=0x10; //認證尋卡等待時候 查詢空閑中斷標志位
- break;
-
- case PCD_TRANSCEIVE: //接收發送 發送接收
- IrqEn = 0x77; //允許TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
- WaitFor = 0x30; //尋卡等待時候 查詢接收中斷標志位與 空閑中斷標志位
- break;
-
- default:
- break;
-
- }
-
- WriteRawRC( ComIEnReg,IrqEn|0x80); //IRqInv置位管腳IRQ與Status1Reg的IRq位的值相反
- ClearBitMask( ComIrqReg,0x80 ); //Set1該位清零時,CommIRqReg的屏蔽位清零
- WriteRawRC( CommandReg,PCD_IDLE ); //寫空閑命令
- SetBitMask( FIFOLevelReg,0x80); //置位FlushBuffer清除內部FIFO的讀和寫指針以及ErrReg的BufferOvfl標志位被清除
-
- for (L= 0; L<intLen;L++ )
- WriteRawRC(FIFODataReg,Data [L]); //寫數據進FIFOdata
-
- WriteRawRC(CommandReg,Command); //寫命令
-
-
- if (Command==PCD_TRANSCEIVE )
- SetBitMask(BitFramingReg,0x80); //StartSend置位啟動數據發送 該位與收發命令使用時才有效
-
- L= 1000;//根據時鐘頻率調整,操作M1卡最大等待時間25ms
-
- do //認證 與尋卡等待時間
- {
- N = ReadRC ( ComIrqReg ); //查詢事件中斷
- L--;
- } while ((L!=0)&&(!(N&0x01))&&(!(N&WaitFor ) ) ); //退出條件i=0,定時器中斷,與寫空閑命令
-
- ClearBitMask ( BitFramingReg, 0x80 ); //清理允許StartSend位
-
- if (L!= 0 )
- {
- if ( ! ( ReadRC ( ErrorReg ) & 0x1B ) ) //讀錯誤標志寄存器BufferOfI CollErr ParityErr ProtocolErr
- {
- Status =True ;
-
- if ( N & IrqEn & 0x01 ) //是否發生定時器中斷
- Status =Irq_falg ;
-
- if (Command ==PCD_TRANSCEIVE )
- {
- N = ReadRC ( FIFOLevelReg ); //讀FIFO中保存的字節數
-
- LastBits = ReadRC(ControlReg ) & 0x07; //最后接收到得字節的有效位數
-
- if(LastBits )
- * outLen=(N - 1 )*8+LastBits; //N個字節數減去1(最后一個字節)+最后一位的位數 讀取到的數據總位數
- else
- *outLen=N * 8; //最后接收到的字節整個字節有效
-
- if (N ==0)
- N = 1;
-
- if (N >max)
- N =max;
-
- for (L=0;L<N;L ++ )
- Data[L] =ReadRC(FIFODataReg );
-
- }
-
- }
-
- else
- Status =Fault;
-
- }
-
- SetBitMask ( ControlReg, 0x80 ); // stop timer now
- WriteRawRC ( CommandReg, PCD_IDLE );
-
-
- return Status;
-
-
- }
- /*******************************************************************************************
- *函數功能:尋卡
- *參數:Card_code,尋卡方式
- * = 0x52,尋感應區內所有符合14443A標準的卡
- * = 0x26,尋未進入休眠狀態的卡
- * CardType,卡片類型代碼
- * = 0x4400,Mifare_UltraLight
- * = 0x0400,Mifare_One(S50)
- * = 0x0200,Mifare_One(S70)
- * = 0x0800,Mifare_Pro(X))
- * = 0x4403,Mifare_DESFire
- * 返回值:1 ,成功 0,失敗
- *******************************************************************************************/
- char PcdRequest ( u8 Req_code, u8 * CardType )
- {
- char Status;
- u8 buffer[max];
- u32 Len;
-
- ClearBitMask ( Status2Reg, 0x08 ); //清理指示MIFARECyptol單元接通以及所有卡的數據通信被加密的情況
- WriteRawRC ( BitFramingReg, 0x07 ); // 發送的最后一個字節的 七位
- SetBitMask ( TxControlReg, 0x03 ); //TX1,TX2管腳的輸出信號傳遞經發送調制的13.56的能量載波信號
- buffer[0] =Req_code; //存入 卡片命令字
- Status = PcdComMF522(PCD_TRANSCEIVE,buffer,1,buffer,&Len ); //尋卡
-
- if ((Status ==True)&&(Len == 0x10 ) ) //尋卡成功返回卡類型
- {
- * CardType=buffer[0];
- * (CardType+1)=buffer[1];
- }
-
- else
- Status =Fault;
- return Status;
-
- }
- /*******************************************************************************************
- *函數功能:防沖撞
- *參數:接收ID號緩沖區
- *返回值:1,成功,0,失敗
- *
- ********************************************************************************************/
- char PcdAnticoll ( u8 * Snr )
- {
- char Status;
- u8 uc, Snr_check = 0;
- u8 buffer[max];
- u32 Len;
-
- ClearBitMask ( Status2Reg, 0x08 ); //清MFCryptol On位 只有成功執行MFAuthent命令后,該位才能置位
- WriteRawRC ( BitFramingReg, 0x00); //清理寄存器 停止收發
- ClearBitMask ( CollReg, 0x80 ); //清ValuesAfterColl所有接收的位在沖突后被清除
-
- buffer[ 0 ] = 0x93; //卡片防沖突命令
- buffer[ 1 ] = 0x20;
-
- Status =PcdComMF522(PCD_TRANSCEIVE,buffer, 2,buffer,&Len);//與卡片通信
-
- if (Status==True ) //通信成功
- {
- for ( uc = 0; uc < 4; uc ++ )
- {
- * ( Snr + uc ) = buffer[ uc ]; //讀出UID
- Snr_check ^= buffer[ uc ];
- }
-
- if ( Snr_check !=buffer[ uc ] )
- Status =Fault;
-
- }
-
- SetBitMask ( CollReg, 0x80 );
-
-
- return Status;
-
-
- }
- /*******************************************************************************************
- 函數功能:用RC522計算CRC16
- 參數:intdata,計算CRC16的數組
- Len,計算CRC16的數組字節長度
- 0utData,存放計算結果存放的首地址
- *返回值:無
- *******************************************************************************************/
- void CalulateCRC ( u8 * intData, u8 Len, u8 * outData )
- {
- u8 k,j;
-
-
- ClearBitMask(DivIrqReg,0x04);
-
- WriteRawRC(CommandReg,PCD_IDLE);
-
- SetBitMask(FIFOLevelReg,0x80);
-
- for (k= 0;k<Len;k++)
- WriteRawRC ( FIFODataReg, * (intData +k) );
- WriteRawRC ( CommandReg, PCD_CALCCRC );
-
- k= 0xFF;
-
- do
- {
- j= ReadRC(DivIrqReg );
- k--;
- } while ( (k!= 0) && ! (j& 0x04 ) );
-
- outData[0] = ReadRC(CRCResultRegL);
- outData[1] = ReadRC(CRCResultRegM);
-
-
- }
- /*******************************************************************************************
- 函數功能:選定卡片
- 參數:pSnr,卡片序列號,4字節
- *返回值: 1,成功,0,失敗
- *
- ********************************************************************************************/
- char PcdSelect ( u8 * pSnr )
- {
- char ucN;
- u8 uc;
- u8 buffer[max];
- u32 ulLen;
-
-
- buffer[0] = PICC_ANTICOLL1;
- buffer[1] = 0x70;
- buffer[6] = 0;
-
- for ( uc = 0; uc < 4; uc ++ )
- {
- buffer[ uc + 2 ] = * ( pSnr + uc );
- buffer[ 6 ] ^= * ( pSnr + uc );
- }
-
- CalulateCRC (buffer, 7, &buffer[ 7 ] );
-
- ClearBitMask ( Status2Reg, 0x08 );
- ucN = PcdComMF522 ( PCD_TRANSCEIVE,buffer, 9,buffer, & ulLen );
-
- if ( ( ucN ==True ) && ( ulLen == 0x18 ) )
- ucN =True ;
- else
- ucN =Fault;
-
- return ucN;
-
-
- }
- /*******************************************************************************************
- *函數功能:驗證卡片密碼
- *參數:mode,密碼驗證模式
- * 0x60,驗證A密鑰
- * 0x61,驗證B密鑰
- * u8 Addr,塊地址
- * Key,密碼
- * Str,卡片序列號,4字節
- *返回值: 1,成功,0,失敗
- *******************************************************************************************/
- char PcdAuthState ( u8 mode, u8 Addr, u8 * Key, u8 * str )
- {
- char Status;
- u8 uc, buffer[max];
- u32 Len;
-
-
- buffer[ 0 ] =mode;
- buffer[ 1 ] = Addr;
-
- for ( uc = 0; uc < 6; uc ++ )
- buffer[uc + 2 ] = * ( Key + uc );
-
- for ( uc = 0; uc < 6; uc ++ )
- buffer[ uc + 8 ] = * (str + uc );
- Status = PcdComMF522 ( PCD_AUTHENT,buffer, 12,buffer, &Len );
-
- if ( ( Status !=True ) || ( ! ( ReadRC ( Status2Reg ) & 0x08 ) ) )
- Status =Fault;
-
-
- return Status;
-
-
- }
- /*******************************************************************************************
- *函數功能:寫數據到M1卡一塊
- *參數:u8 addr,塊地址
- * Data,寫入的數據,16字節
- *返回值:1,成功,0,失敗
- *******************************************************************************************/
- char PcdWrite ( u8 addr, u8 * Data )
- {
- char Status;
- u8 uc,buffer[max];
- u32 Len;
-
-
- buffer[ 0 ] = PICC_WRITE;
- buffer [ 1 ] =addr;
-
- CalulateCRC (buffer, 2, &buffer[ 2 ] );
-
- Status = PcdComMF522 ( PCD_TRANSCEIVE,buffer, 4,buffer, & Len );
- if ((Status != True )||(Len!=4)||((buffer[ 0 ] & 0x0F ) != 0x0A ) )
- Status =Fault;
-
- if (Status==True )
- {
- //memcpy(ucComMF522Buf, pData, 16);
- for ( uc = 0; uc < 16; uc ++ )
- buffer[uc] = * ( Data + uc );
-
- CalulateCRC ( buffer, 16, &buffer[ 16 ] );
- Status = PcdComMF522 ( PCD_TRANSCEIVE,buffer, 18,buffer,&Len );
-
- if ( ( Status != True )||(Len !=4)||((buffer[0]&0x0F)!=0x0A))
- Status =Fault;
-
- }
-
-
- return Status;
-
-
- }
- /*******************************************************************************************
- *函數功能:讀取M1卡一塊數據
- *參數:u8 Aaddr,塊地址
- * Data,讀出的數據,16字節
- *返回值:1,成功,0,失敗
- *
- ********************************************************************************************/
- char PcdRead (u8 addr,u8 *Data )
- {
- char Status;
- u8 L, buffer[max];
- u32 Len;
-
- buffer[0]=PICC_READ;
- buffer[1]=addr;
-
- CalulateCRC (buffer, 2, &buffer[ 2 ] );
-
- Status = PcdComMF522 ( PCD_TRANSCEIVE,buffer, 4,buffer,&Len );
-
- if ((Status==True ) && (Len == 0x90 ) )
- {
- for (L= 0; L< 16;L++ )
- * (Data+L) = buffer[L];
- }
-
- else
- Status =Fault;
-
-
- return Status;
-
- }
- /*******************************************************************************************
- *函數功能:命令卡片進入休眠狀態
- *參數:無
- *返回值:1,成功,0,失敗
- *
- ********************************************************************************************/
- char PcdHalt(void)
- {
- u8 buffer[max];
- u32 Len;
-
- buffer[0]=PICC_HALT;
- buffer[1]=0;
-
- CalulateCRC (buffer, 2, &buffer[ 2 ] );
- PcdComMF522(PCD_TRANSCEIVE,buffer, 4,buffer, &Len);
- return True ;
-
- }
- /****************************************************************************************************************
- *函數功能:RC522測試
- *參數:無
- *返回值:無
- ******************************************************************************************************************/
- void RC522_test(void)
- {
- char Str[30];
- u8 Card_ID[4];
-
- while (1)
- {
-
- PcdRequest (PICC_REQALL, Card_ID); //尋卡 //若失敗再次尋卡
- if (PcdAnticoll(Card_ID)==True ) //防沖撞(當有多張卡進入讀寫器操作范圍時,防沖突機制會從其中選擇一張進行操作)
- {
- sprintf(Str,"\r\n門禁卡的ID號: %02X%02X%02X%02X",Card_ID[0],Card_ID[1],Card_ID[2],Card_ID[3]);
-
- printf ("%s\r\n",Str);
-
- }
-
-
- }
-
- }
復制代碼
所有資料51hei提供下載:
金龍107RFID例程(20160721).7z
(349.26 KB, 下載次數: 27)
2019-1-25 15:28 上傳
點擊文件名下載附件
RFID MFRC522 下載積分: 黑幣 -5
|