?? rc522.c
字號:
//#include <intrins.h>
#include <intrins.h>
#include "lpcreg.h"
#include "main.h"
#include "mfrc522.h"
#define MAXRLEN 18
#define nop _nop_()
sbit SDA=P1^1;
sbit SCL=P1^0;
//SDA BIT P1.1 ;SERIEL BYTE OF DS1302/IC I/O
//SCL BIT P1.0 ;CLOCK OF DS1302/IC O
/*----------------------------------------------------------------------------*/
// 內(nèi)部函數(shù)----啟動I2C通信
/*----------------------------------------------------------------------------*/
void I2CStart(void)
{
SDA=1; /*發(fā)送起始條件的數(shù)據(jù)信號*/
// nop;nop;nop;nop;nop;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1; /*發(fā)送起始條件的時鐘信號*/
//Delay(3);
// nop;nop;nop;nop;nop; //起始條件建立時間大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
// nop;nop;nop;nop;nop; //起始條件建立時間大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
// nop;nop; //起始條件建立時間大于4.7us
_nop_();
_nop_();
SDA=0; /*發(fā)送起始信號*/
//Delay(3);
// nop;nop;nop;nop;nop; //起始條件鎖定時間大于4us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
// nop;nop;nop;nop;nop; //起始條件鎖定時間大于4us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
//nop;nop;nop;nop;nop; //起始條件鎖定時間大于4us
SCL=0; /*鉗住I2C總線,準備發(fā)送或接收*/
// nop;nop;nop;nop;nop;nop;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*----------------------------------------------------------------------------*/
// 內(nèi)部函數(shù)----停止I2C通信
/*----------------------------------------------------------------------------*/
void I2CStop(void) //釋放I2C總線*/
{
SDA=0; /*發(fā)送停止條件的數(shù)據(jù)信號*/
nop;nop;nop;nop;nop;
SCL=1; //發(fā)送停止條件的時鐘信號
//Delay(3);
nop;nop;nop;nop;nop; //起始條件建立時間大于4us
nop;nop;nop;nop;nop; //起始條件建立時間大于4us
//nop;nop;nop;nop;nop; //起始條件建立時間大于4us
SDA=1; /*發(fā)送I2C總線停止信號*/
//Delay(3);
nop;nop;nop;nop;nop;/*停止條件鎖定時間大于4us*/
nop;nop;nop;nop;nop;/*停止條件鎖定時間大于4us*/
}
/*-------------------------------------------------
內(nèi)部函數(shù)--------SendAck(unsigned AckBit) 輸出ACK
AckBit=0 為發(fā)送應(yīng)答信號
AckBit=1 為發(fā)送非應(yīng)答信號
---------------------------------------------------*/
void SendAck(bit AckBit)
{
SDA=AckBit; /*發(fā)送的應(yīng)答或非應(yīng)答信號*/
nop;nop;nop;nop;nop;
// Delay(1);
SCL=1; /*置時鐘線為高使應(yīng)答位有效*/
//Delay(3);
nop;nop;nop;nop;nop; /*時鐘高周期大于4us*/
nop;nop;nop;nop;nop; /*時鐘高周期大于4us*/
SCL=0; /*清時鐘線鉗住I2C 總線以便繼續(xù)接收字接數(shù)據(jù)或發(fā)送停止條件*/
nop;nop;nop;nop;nop;
}
/*------------------------------------------
內(nèi)部函數(shù)---------發(fā)送一個字節(jié)到I2C總線上
入口:待寫入的數(shù)據(jù)ucdata ;無返回值
-------------------------------------------*/
bit I2CSendByte(unsigned char ucdata)
{
bit bACK;
unsigned char data i;
i=8;
while(i--) /*8 位沒發(fā)送完繼續(xù)發(fā)送*/
{
if((ucdata & 0x80)==0x80)
SDA=1; /*發(fā)送是1*/
else
SDA=0; /*發(fā)送的是0*/
nop;nop;nop;nop;nop;
SCL=1; /*置時鐘線為高通知被控器開始接收數(shù)據(jù)位*/
//Delay(3);
nop;nop;nop;nop;nop; /*保證時鐘高周期大于4us*/
nop;nop;nop;nop;nop; /*保證時鐘高周期大于4us*/
SCL=0; /*鉗住總線準備接收下一個數(shù)據(jù)位*/
ucdata=ucdata<<1; /*發(fā)送下一位數(shù)據(jù)*/
}
nop;nop;nop;nop;nop;
SDA=1; /*8位數(shù)據(jù)發(fā)送完,釋放I2C總線,準備接收應(yīng)答位*/
nop;nop;nop;nop;nop;
SCL=1; /*開始接收應(yīng)答信號*/
// Delay(1);
nop;nop;nop;nop;nop;
if(SDA) /*等待應(yīng)答,SDA=0為應(yīng)答*/
bACK=0;
else
bACK=1;
SCL=0; /*發(fā)送結(jié)束鉗住總線準備下一步發(fā)送或接收數(shù)據(jù)或進行其它處理*/
nop;nop;nop;nop;nop;
return(bACK); /*正確應(yīng)答返回0*/
}
/*------------------------------------------
內(nèi)部函數(shù)------從I2C接收一個字節(jié)
無入口參數(shù);返回接收到的字節(jié).
--------------------------------------------*/
unsigned char I2CReadByte(void)
{
unsigned char data i=0,ByteData=0;
SDA=1; /*置數(shù)據(jù)線為輸入方式*/
i=8;
while(i--)
{
nop;nop;nop;nop;nop;
SCL=0; //置鐘線為零準備接收數(shù)據(jù)
// Delay(3);
nop;nop;nop;nop;nop; /*時鐘低周期大于4.7us*/
nop;nop;nop;nop;nop; /*時鐘低周期大于4.7us*/
SCL=1; /*置時鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
nop;nop;nop;nop;nop;
ByteData=ByteData<<1;
if(SDA)
ByteData++;
nop;nop;nop;nop;nop;
}
SCL=0; /*8 位接收完置時鐘線和數(shù)據(jù)線為低準備發(fā)送應(yīng)答或非應(yīng)答信號*/
nop;nop;nop;nop;nop;
return(ByteData);
}
bit I2CRdStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucBuf,unsigned char ucCount)
{ //從有子地址的器件讀取數(shù)據(jù)
// PCF8563的地址為0xa2,
unsigned char idata i=0;
I2CStart();
if(!I2CSendByte(ucSla))
{
I2CStop();
return 0; /*選從器件的地此*/
}
if(!I2CSendByte(ucAddress))
{
I2CStop();
return 0; /*選第一個寄存器地此*/
}
I2CStart();
if(!I2CSendByte(ucSla+1))
{
I2CStop();
return 0; /*發(fā)送讀器件命令*/
}
i=ucCount;
while(i--)
{
*ucBuf=I2CReadByte();/*讀從器件寄存器*/
if(i)
SendAck(0); /*未接收完所有字節(jié),發(fā)送應(yīng)答信號*/
ucBuf++;
}
SendAck(1); /*接收完所有字節(jié),發(fā)送非應(yīng)答信號*/
I2CStop();
return 1;
}
bit I2CWrStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucData,unsigned char ucNo)
{ //8563的地址為0xa2
unsigned char data i;
I2CStart();
if(!I2CSendByte(ucSla))
{
I2CStop();
return 0; /*write command*/
}
if(!I2CSendByte(ucAddress))
{
I2CStop();
return 0; /*write register Address*/
}
i=ucNo;
while(i--)
{
if(!I2CSendByte(*ucData))
{
I2CStop();
return 0; /*write Data*/
}
ucData++;
}
I2CStop();
return 1;
}
/////////////////////////////////////////////////////////////////////
//功 能:讀RC632寄存器
//參數(shù)說明:Address[IN]:寄存器地址
//返 回:讀出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
unsigned char data tmp;
//I2CRdStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucBuf,unsigned char ucCount)
I2CRdStr(0x50,Address,&tmp,0x01);
return tmp;
}
/////////////////////////////////////////////////////////////////////
//功 能:寫RC632寄存器
//參數(shù)說明:Address[IN]:寄存器地址
// value[IN]:寫入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
I2CWrStr(0x50,Address,&value,0x01);
}
/////////////////////////////////////////////////////////////////////
//功 能:尋卡
//參數(shù)說明: req_code[IN]:尋卡方式
// 0x52 = 尋感應(yīng)區(qū)內(nèi)所有符合14443A標準的卡
// 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
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
// unsigned char xTest ;
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
// xTest = ReadRawRC(BitFramingReg);
// if(xTest == 0x07 )
// { LED_GREEN =0 ;}
// else {LED_GREEN =1 ;while(1){}}
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
// if(status == MI_OK )
// { LED_GREEN =0 ;}
// else {LED_GREEN =1 ;}
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)
{
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];
snr_check ^= ucComMF522Buf[i];
}
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)
{
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); }
// memcpy(&ucComMF522Buf[2], pKey, 6);
// memcpy(&ucComMF522Buf[8], pSnr, 4);
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)
{
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);
if ((status == MI_OK) && (unLen == 0x90))
// { memcpy(pData, ucComMF522Buf, 16); }
{
for (i=0; i<16; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
/////////////////////////////////////////////////////////////////////
//功 能:寫數(shù)據(jù)到M1卡一塊
//參數(shù)說明: addr[IN]:塊地址
// pData[IN]:寫入的數(shù)據(jù),16字節(jié)
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdWrite(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
{ status = MI_ERR; }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -