📄 mfrc500.c
字号:
//#include <reg51rx2.h>
#include <reg52.h>
#include <intrins.h>
#include "string.h"
#include "stimer.h"
#include "ucio.h"
#include "mfrc500.h"
#include "uart.h"
#include "v51rx2.h"
#include "intrsc.h"
#include "MifarePro.h"
#include "global.h"
#define DEBUGRC500
#define enableme() EX0 = 1
#define disableme() EX0 = 0
//static volatile bit fSameCard;
static volatile MfCmdInfo MInfo;
// Variable in order to exchange data between function and ISR
static volatile MfCmdInfo *MpIsrInfo = 0;
// ISR send buffer
static volatile unsigned char *MpIsrOut = 0;
// ISR receive buffer
static volatile unsigned char *MpIsrIn = 0;
static unsigned char RxGain = 0x71;//73:42db, 72:38, 71:30, 70:27///////////////////
#define MFIFOLength 64
uchar xdata SndBuffer[64];
uchar xdata RcvBuffer[64];
// storage of the last selected serial number including check byte.
// For multi level serial numbers, only the first 4 bytes are stored.
unsigned char MLastSelectedSnr[5];
void ResetInfo(MfCmdInfo *info)
{
info->cmd= 0;
info->status = MI_OK;
info->irqSource= 0;
info->nBytesToSend = 0;
info->nBytesSent = 0;
info->nBytesReceived = 0;
info->nBitsReceived = 0;
info->collPos = 0;
}
void SetBitMask(uchar reg,uchar mask)
{
uchar data tmp = 0x0;
tmp = ReadIO(reg);
WriteIO(reg,tmp | mask);
}
void ClearBitMask(uchar reg,uchar mask)
{
uchar tmp = 0x0;
tmp = ReadIO(reg);
WriteIO(reg,tmp & ~mask);
}
// clear fifo
void FlushFIFO(void)
{
SetBitMask(RegControl,0x01);
}
/************************************
* set timeout length *
* tmolength: timeout length *
************************************/
/*
void M500PcdSetTmo(uchar tmoLength)
{
switch(tmoLength)
{
case 1:
WriteIO(RegTimerClock,0x07);
WriteIO(RegTimerReload,0x6a);
break;
case 2:
WriteIO(RegTimerClock,0x07);
WriteIO(RegTimerReload,0xa0);
break;
case 3:
WriteIO(RegTimerClock,0x09);
WriteIO(RegTimerReload,0xa0);
break;
case 4:
WriteIO(RegTimerClock,0x09);
WriteIO(RegTimerReload,0xff);
break;
case 5:
WriteIO(RegTimerClock,0x0b);
WriteIO(RegTimerReload,0xff);
break;
case 6:
WriteIO(RegTimerClock,0x0d);
WriteIO(RegTimerReload,0xff);
break;
case 7:
WriteIO(RegTimerClock,0x0f);
WriteIO(RegTimerReload,0xff);
break;
default:
WriteIO(RegTimerClock,0x07);
WriteIO(RegTimerReload,tmoLength);
break;
}
} */
void M500PcdSetTmo(unsigned char tmoLength)
{
switch(tmoLength)
{ // timer clock frequency 13,56 MHz
case 1: // short timeout (1,0 ms)
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,0x6a);// TReloadVal = 'h6a =106(dec)
break;
case 2: // medium timeout (1,5 ms)
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 3: // medium timeout (6 ms)
WriteIO(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteIO(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 4: // long timeout (9.6 ms)
WriteIO(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 5: // long timeout (38.5 ms)
WriteIO(RegTimerClock,0x0b); // TAutoRestart=0,TPrescale=16*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 6: // long timeout (154 ms)
WriteIO(RegTimerClock,0x0d); // TAutoRestart=0,TPrescale=64*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 7: // long timeout (616.2 ms)
WriteIO(RegTimerClock,0x0f); // TAutoRestart=0,TPrescale=256*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 8:
WriteIO(RegTimerClock,0x0f);
WriteIO(RegTimerReload,0xB6); //e1
break;
case 9:
WriteIO(RegTimerClock,0x11);
WriteIO(RegTimerReload,0xff);
case 10:
WriteIO(RegTimerClock,0x12);
WriteIO(RegTimerReload,0xff);
break;
case 11:
WriteIO(RegTimerClock,0x13);
WriteIO(RegTimerReload,0xff);
break;
case 12:
WriteIO(RegTimerClock,0x14);
WriteIO(RegTimerReload,0xff);
break;
case 13:
WriteIO(RegTimerClock,0x10);
WriteIO(RegTimerReload,0xE1);
break;
case 14:
WriteIO(RegTimerClock,0x0F);
WriteIO(RegTimerReload,0xB0); //E1
break;
case 15:
WriteIO(RegTimerClock,0x0F);
WriteIO(RegTimerReload,0xB1); //Process the cmmand .setting the time in the MFRC500 timer.
break;
case 16:
WriteIO(RegTimerClock,0x0C);
WriteIO(RegTimerReload,0xFF);
break;
default: //
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,tmoLength); // TReloadVal = 'h6a =tmoLength(dec)
break;
}
}
/****************************
* excute mfrc500 command *
****************************/
#if 1
uchar M500PcdCmd(unsigned char cmdcode, unsigned char* send, unsigned char* rcv, MfCmdInfo *info)
{
uchar data tmpStatus;
uchar data lastBits;
uchar data status = MI_OK;
uchar data irqEn = 0x00;
uchar data waitFor = 0x00;
uint data starttime;
uchar data i;
WriteIO(RegInterruptEn,0x7F); // disable all interrupts
WriteIO(RegInterruptRq,0x7F); // reset interrupt requests
WriteIO(RegCommand,PCD_IDLE); // terminate probably running command
FlushFIFO(); // flush FIFO buffer
// save info structures to module pointers
MpIsrInfo = info;
MpIsrOut = send;
MpIsrIn = rcv;
info->irqSource = 0x0; // reset interrupt flags
enableme();
// depending on the command code, appropriate interrupts are enabled (irqEn)
// and the commit interrupt is choosen (waitFor).
switch(cmdcode)
{
case PCD_IDLE: // nothing else required
irqEn = 0x00;
waitFor = 0x00;
break;
case PCD_WRITEE2: // LoAlert and TxIRq
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_READE2: // HiAlert, LoAlert and IdleIRq
irqEn = 0x07;
waitFor = 0x04;
break;
case PCD_LOADCONFIG: // IdleIRq and LoAlert
case PCD_LOADKEYE2: // IdleIRq and LoAlert
case PCD_AUTHENT1: // IdleIRq and LoAlert
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_CALCCRC: // LoAlert and TxIRq
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_AUTHENT2: // IdleIRq
irqEn = 0x04;
waitFor = 0x04;
break;
case PCD_RECEIVE: // HiAlert and IdleIRq
info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4); ////////////////
irqEn = 0x06;
waitFor = 0x04;
break;
case PCD_LOADKEY: // IdleIRq
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSMIT: // LoAlert and IdleIRq
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSCEIVE: // TxIrq, RxIrq, IdleIRq and LoAlert
info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4); //////////////
irqEn = 0x3D; //0x1D;
waitFor = 0x04;
break;
default:
status = MI_UNKNOWN_COMMAND;
break;
}
if (status == MI_OK)
{
irqEn |= 0x20;
waitFor |= 0x20;
for(i=0;i<253;i++)
{
_nop_();
}
WriteIO(RegInterruptEn,irqEn | 0x80); // enable interrupt
WriteIO(RegCommand,cmdcode); // send command
starttime = GetTickCount();
while (!((MpIsrInfo->irqSource & waitFor)
|| (GetTickCount() - starttime > 420))); // wait for cmd completion or timeout
//while(!MpIsrInfo->irqSource & waitFor);
// disableme(); // disable interrupt just when cmd complete, 050517
WriteIO(RegInterruptEn,0x7F); // disable all interrupts
WriteIO(RegInterruptRq,0x7F); // clear all interrupt requests
SetBitMask(RegControl,0x04); // stop timer now
WriteIO(RegCommand,PCD_IDLE); // reset command register
if (!(MpIsrInfo->irqSource & waitFor)) // reader has not terminated This logic has a problem about the timeout!!
{ // timer 3 expired
status = MI_ACCESSTIMEOUT; // This code do not support the MiarePro. freqence timeout!!!
}
else
status = MpIsrInfo->status; // set status The real timeout occured ,then will the NO_TAGERR!
if (status == MI_OK) // no timeout error occured
{
if (tmpStatus = (ReadIO(RegErrorFlag) & 0x17/*0x1f*/)) // error occured
{
if (tmpStatus & 0x01) // collision detected
{
info->collPos = ReadIO(RegCollpos); // read collision position
status = MI_COLLERR;
}
else
{
info->collPos = 0;
if (tmpStatus & 0x02) // parity error
{
status = MI_PARITYERR;
}
}
if (tmpStatus & 0x04) // framing error
{
status = MI_FRAMINGERR;
}
if (tmpStatus & 0x10) // FIFO overflow
{
FlushFIFO();
status = MI_OVFLERR;
}
if (tmpStatus & 0x08) //CRC error
{
status = MI_CRCERR;
}
if (status == MI_OK)
status = MI_NY_IMPLEMENTED;
// key error occures always, because of
// missing crypto 1 keys loaded
}
// if the last command was TRANSCEIVE, the number of
// received bits must be calculated - even if an error occured
if (cmdcode == PCD_TRANSCEIVE || cmdcode == PCD_RECEIVE) ////////////////////
{
// number of bits in the last byte
lastBits = ReadIO(RegSecondaryStatus) & 0x07;
if (lastBits)
info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
else
info->nBitsReceived += info->nBytesReceived * 8;
}
}
else
{
info->collPos = 0x00;
}
}
disableme();
MpIsrInfo = 0; // reset interface variables for ISR
MpIsrOut = 0;
MpIsrIn = 0;
return status;
}
#else
//////////////////////////////////////////////////////////////////////
// W R I T E A P C D C O M M A N D
///////////////////////////////////////////////////////////////////////
char M500PcdCmd(unsigned char cmd,
volatile unsigned char* send,
volatile unsigned char* rcv,
volatile MfCmdInfo *info)
{
char status = MI_OK;
char tmpStatus ;
unsigned char lastBits;
unsigned char irqEn = 0x00;
unsigned char waitFor = 0x00;
unsigned char timerCtl = 0x00;
WriteIO(RegInterruptEn,0x7F); // disable all interrupts
WriteIO(RegInterruptRq,0x7F); // reset interrupt requests
WriteIO(RegCommand,PCD_IDLE); // terminate probably running command
FlushFIFO(); // flush FIFO buffer
// save info structures to module pointers
MpIsrInfo = info;
MpIsrOut = send;
MpIsrIn = rcv;
info->irqSource = 0x0; // reset interrupt flags
enableme();
// depending on the command code, appropriate interrupts are enabled (irqEn)
// and the commit interrupt is choosen (waitFor).
switch(cmd)
{
case PCD_IDLE: // nothing else required
irqEn = 0x00;
waitFor = 0x00;
break;
case PCD_WRITEE2: // LoAlert and TxIRq
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_READE2: // HiAlert, LoAlert and IdleIRq
irqEn = 0x07;
waitFor = 0x04;
break;
case PCD_LOADCONFIG: // IdleIRq and LoAlert
case PCD_LOADKEYE2: // IdleIRq and LoAlert
case PCD_AUTHENT1: // IdleIRq and LoAlert
irqEn = 0x05;
waitFor = 0x04;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -