標題:
金龍STM32F107 RFID MFRC522源代碼
[打印本頁]
作者:
樂觀的知覺
時間:
2019-1-25 12:03
標題:
金龍STM32F107 RFID MFRC522源代碼
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通信
*
*
**************************************/
/********************************************************************************
*函數(shù)功能:SPI發(fā)送數(shù)據(jù)
*參數(shù):待發(fā)送的數(shù)據(jù)
*返回值:無
*
**********************************************************************************/
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;
}
}
/*******************************************************************************************
*函數(shù)功能:SPI讀函數(shù)
*參數(shù):無
*返回值:讀到的數(shù)據(jù)
*
********************************************************************************************/
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;
}
/******************************************************************************************
*函數(shù)功能:讀RC522寄存器
*參數(shù):address 寄存器的地址
*返回值:寄存器的當前值
*
******************************************************************************************/
//用SPI讀RC522的數(shù)據(jù)格式是 0x msb(控制位 1位) 地址(6位) 日志(1位),
//舉個例子 讀地址 0x0000 0110 的數(shù)據(jù)就要把他轉(zhuǎn)換成 0x1000 1100,首位1代表讀,0是寫,最后一位0是日志是規(guī)定。
//隨意左移一位是確定地址,& 0x0111 1110(7e)的作用是保證此操作只有地址沒有變成奇奇怪怪的東西。然后 | 0x1000 0000 (80)就是確定第一位是1,也就是讀數(shù)據(jù)。
//具體內(nèi)容看官方的 《MFCR522數(shù)據(jù)手冊》 10.2 章節(jié),中文文檔可能不太一樣
u8 ReadRC(u8 address )
{
u8 Addr, Return;
Addr=((address<<1)&0x7E)|0x80;//變化成有效的地址形式,最低位為0,最高位為1時候是,從MFRC522讀出數(shù)據(jù)。
RC522_CS_Enable();
RC522_Send(Addr);
Return=RC522_Read();
RC522_CS_Disable();
return Return;
}
/*******************************************************************************************
*函數(shù)功能:寫RC522寄存器
*參數(shù):Addresss 寄存器的地址
Value 寫入寄存器的值
*返回值:無
*******************************************************************************************/
void WriteRawRC(u8 Address,u8 Value)
{
u8 Addr;
Addr =(Address<<1)&0x7E;//變化成有效的地址形式,最低位為0,最高位為0時候是,從MFRC522寫入數(shù)據(jù)。
RC522_CS_Enable();
RC522_Send(Addr);
RC522_Send(Value);
RC522_CS_Disable();
}
/*******************************************************************************************
*函數(shù)功能:對RC522寄存器置位
*參數(shù):Reg 寄存器的紙質(zhì)
mask 置位的值
*返回值:無
*******************************************************************************************/
void SetBitMask(u8 Reg,u8 Mask )
{
u8 Temp;
Temp=ReadRC(Reg);
WriteRawRC(Reg,Temp|Mask); // set bit mask
}
/*******************************************************************************************
*函數(shù)功能:對RC522寄存器清零
*參數(shù):Reg RC522的地址
Mask 清零的數(shù)據(jù)
*返回值:無
*******************************************************************************************/
//讀取寄存器reg,保存在temp中;
//將mask取反后與temp的內(nèi)容作與運算,運算結(jié)果寫回寄存器reg中;
//mask取反后原先為1的位變0,為0的位變1,所以、與運算后temp中對應(yīng)mask中最初為1的位就被清零。
void ClearBitMask(u8 Reg,u8 Mask )
{
u8 Temp;
Temp=ReadRC(Reg);
WriteRawRC(Reg,Temp&(~Mask)); // clear bit mask
}
/*******************************************************************************************
*函數(shù)功能:開天線
*參數(shù):無
*返回值:無
*
********************************************************************************************/
void PcdAntennaOn(void)
{
u8 temp;
temp=ReadRC(TxControlReg);
if (!(temp&0x03))
SetBitMask(TxControlReg,0x03);
}
/*******************************************************************************************
*函數(shù)功能:關(guān)閉天線
*參數(shù):無
*返回值:
*
*******************************************************************************************/
void PcdAntennaOff ( void )
{
ClearBitMask(TxControlReg,0x03 );
}
/*******************************************************************************************
*函數(shù)功能:復(fù)位RC522
*參數(shù):無
*返回值:無
*
*******************************************************************************************/
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 ); //定義發(fā)送和接收常用模式 和Mifare卡通訊,CRC初始值0x6363
WriteRawRC(TReloadRegL,30); //16位定時器低位
WriteRawRC(TReloadRegH,0); //16位定時器高位
WriteRawRC(TModeReg,0x8D); //定義內(nèi)部定時器的設(shè)置
WriteRawRC(TPrescalerReg,0x3E); //設(shè)置定時器分頻系數(shù)
WriteRawRC(TxAutoReg,0x40); //調(diào)制發(fā)送信號為100%ASK
}
/*******************************************************************************************
*函數(shù)功能:設(shè)置RC522的工作方式
*參數(shù):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();//開天線
}
}
/*******************************************************************************************
*函數(shù)功能:通過RC522和ISO14443卡通訊
*參數(shù): Command,RC522的命令
* intData,RC522發(fā)送到卡片的數(shù)據(jù)
* intLen,發(fā)送數(shù)據(jù)的字節(jié)長度
* outData,接收到的卡片返回數(shù)據(jù)
* outLen,返回數(shù)據(jù)的長度
*返回值:
********************************************************************************************/
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: //接收發(fā)送 發(fā)送接收
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清除內(nèi)部FIFO的讀和寫指針以及ErrReg的BufferOvfl標志位被清除
for (L= 0; L<intLen;L++ )
WriteRawRC(FIFODataReg,Data [L]); //寫數(shù)據(jù)進FIFOdata
WriteRawRC(CommandReg,Command); //寫命令
if (Command==PCD_TRANSCEIVE )
SetBitMask(BitFramingReg,0x80); //StartSend置位啟動數(shù)據(jù)發(fā)送 該位與收發(fā)命令使用時才有效
L= 1000;//根據(jù)時鐘頻率調(diào)整,操作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 ) //是否發(fā)生定時器中斷
Status =Irq_falg ;
if (Command ==PCD_TRANSCEIVE )
{
N = ReadRC ( FIFOLevelReg ); //讀FIFO中保存的字節(jié)數(shù)
LastBits = ReadRC(ControlReg ) & 0x07; //最后接收到得字節(jié)的有效位數(shù)
if(LastBits )
* outLen=(N - 1 )*8+LastBits; //N個字節(jié)數(shù)減去1(最后一個字節(jié))+最后一位的位數(shù) 讀取到的數(shù)據(jù)總位數(shù)
else
*outLen=N * 8; //最后接收到的字節(jié)整個字節(jié)有效
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;
}
/*******************************************************************************************
*函數(shù)功能:尋卡
*參數(shù):Card_code,尋卡方式
* = 0x52,尋感應(yīng)區(qū)內(nèi)所有符合14443A標準的卡
* = 0x26,尋未進入休眠狀態(tài)的卡
* 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單元接通以及所有卡的數(shù)據(jù)通信被加密的情況
WriteRawRC ( BitFramingReg, 0x07 ); // 發(fā)送的最后一個字節(jié)的 七位
SetBitMask ( TxControlReg, 0x03 ); //TX1,TX2管腳的輸出信號傳遞經(jīng)發(fā)送調(diào)制的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;
}
/*******************************************************************************************
*函數(shù)功能:防沖撞
*參數(shù):接收ID號緩沖區(qū)
*返回值:1,成功,0,失敗
*
********************************************************************************************/
char PcdAnticoll ( u8 * Snr )
{
char Status;
u8 uc, Snr_check = 0;
u8 buffer[max];
u32 Len;
ClearBitMask ( Status2Reg, 0x08 ); //清MFCryptol On位 只有成功執(zhí)行MFAuthent命令后,該位才能置位
WriteRawRC ( BitFramingReg, 0x00); //清理寄存器 停止收發(fā)
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;
}
/*******************************************************************************************
函數(shù)功能:用RC522計算CRC16
參數(shù):intdata,計算CRC16的數(shù)組
Len,計算CRC16的數(shù)組字節(jié)長度
0utData,存放計算結(jié)果存放的首地址
*返回值:無
*******************************************************************************************/
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);
}
/*******************************************************************************************
函數(shù)功能:選定卡片
參數(shù):pSnr,卡片序列號,4字節(jié)
*返回值: 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;
}
/*******************************************************************************************
*函數(shù)功能:驗證卡片密碼
*參數(shù):mode,密碼驗證模式
* 0x60,驗證A密鑰
* 0x61,驗證B密鑰
* u8 Addr,塊地址
* Key,密碼
* Str,卡片序列號,4字節(jié)
*返回值: 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;
}
/*******************************************************************************************
*函數(shù)功能:寫數(shù)據(jù)到M1卡一塊
*參數(shù):u8 addr,塊地址
* Data,寫入的數(shù)據(jù),16字節(jié)
*返回值: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;
}
/*******************************************************************************************
*函數(shù)功能:讀取M1卡一塊數(shù)據(jù)
*參數(shù):u8 Aaddr,塊地址
* Data,讀出的數(shù)據(jù),16字節(jié)
*返回值: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;
}
/*******************************************************************************************
*函數(shù)功能:命令卡片進入休眠狀態(tài)
*參數(shù):無
*返回值: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 ;
}
/****************************************************************************************************************
*函數(shù)功能:RC522測試
*參數(shù):無
*返回值:無
******************************************************************************************************************/
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);
}
}
}
復(fù)制代碼
所有資料51hei提供下載:
金龍107RFID例程(20160721).7z
(349.26 KB, 下載次數(shù): 27)
2019-1-25 15:28 上傳
點擊文件名下載附件
RFID MFRC522
下載積分: 黑幣 -5
作者:
admin
時間:
2019-1-25 15:29
本帖需要重新編輯補全電路原理圖,源碼,詳細說明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1