|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2011-10-26 09:55:34
|
显示全部楼层
代码如下,基本上是按照飞利浦的改过来的,用中断法,
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#include"12864.h"
#include"RC5002.h"
#include<string.h>
#include<stdio.h>
#define RC500RST PE2
#define RC500RST_L() PORTE&=~(1<<RC500RST)
#define RC500RST_H() PORTE|=(1<<RC500RST)
#define LED PE3
#define LED_ON() PORTE|=(1<<LED)
#define LED_OFF() PORTE&=~(1<<LED)
#define ResetInfo(info) \
info.cmd = 0; \
info.status = MI_OK;\
info.irqSource = 0; \
info.nBytesSent = 0; \
info.nBytesToSend = 0; \
info.nBytesReceived = 0; \
info.nBitsReceived = 0; \
info.collPos = 0;
// struct definition for a communication channel between function and ISR
typedef struct
{
unsigned char cmd; //!< command code
char status; // communication status
unsigned char nBytesSent; // how many bytes already sent
unsigned char nBytesToSend; // how many bytes to send
unsigned char nBytesReceived;// how many bytes received
unsigned short nBitsReceived; // how many bits received
unsigned char irqSource; // which interrupts have occured
unsigned char collPos; // at which position occured a
// collision
} MfCmdInfo;
static unsigned char MFIFOLength = DEF_FIFO_LENGTH;
static volatile unsigned char MSndBuffer[SND_BUF_LEN];
static volatile unsigned char MRcvBuffer[RCV_BUF_LEN];
static volatile MfCmdInfo MInfo;
static volatile MfCmdInfo *MpIsrInfo = 0;
static volatile unsigned char *MpIsrOut = 0;
static volatile unsigned char *MpIsrIn = 0;
unsigned char MLastSelectedSnr[5];
uchar Snr_RC500[5];
static uchar MKeys[16][12];
#define WriteRawIO(addr,value) (* (volatile unsigned char *)(0x2000 + addr)) = value;
#define ReadRawIO(addr) (* (volatile unsigned char *)(0x2000 + addr))
void WriteIO(unsigned char Address, unsigned char value)
{
WriteRawIO(Address,value); // write value at the specified
// address
}
unsigned char ReadIO(unsigned char Address)
{
uchar c;
c = ReadRawIO(Address); // read value at the specified
return c; // address
}
void Device_Init(void)
{
MCUCR |= (1<<SRE); //使能总线
XMCRA = 0x00;
XMCRB = 0x07;
DDRE|=(1<<RC500RST);
DDRE|=(1<<LED);
LED_OFF();
}
char M500PcdReset(void)
{
char status = MI_OK;
unsigned int tcnt=1000;
RC500RST_L(); // clear reset pin
_delay_ms(25); // wait for 25ms
RC500RST_H(); // reset RC500
_delay_ms(20); // wait for 2.5ms
RC500RST_L(); // clear reset pin
_delay_ms(25);
while (((ReadRawIO(RegCommand) & 0x3F) != 0x3F) && (tcnt--)); // wait until reset command recognized
// while reset sequence in progress
while ((ReadRawIO(RegCommand) & 0x3F) && (tcnt--));
// stop_timeout(); // stop timeout counter
if (!tcnt) // If reader timeout occurs
{
status = MI_RESETERR; // respose of reader IC is not correct
}
else
{
WriteRawIO(RegPage,0x80); // Dummy access in order to determine the bus configuration
if (ReadRawIO(RegCommand) != 0x00)
{
status = MI_INTERFACEERR;
}
WriteRawIO(RegPage,0x00); // configure to linear address mode
}
return status;
}
char SetBitMask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0;
tmp = ReadIO(reg);
WriteIO(reg,tmp | mask); // set bit mask
return 0x0;
}
char ClearBitMask(unsigned char reg,unsigned char mask) //
{
char tmp = 0x0;
tmp = ReadIO(reg);
WriteIO(reg,tmp & ~mask); // clear bit mask
return 0x0;
}
void FlushFIFO(void)
{
SetBitMask(RegControl,0x01);
}
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;
default: //
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
break;
}
}
char M500PcdRfReset(unsigned char ms)
{
char status = MI_OK;
if(ms)
{
ClearBitMask(RegTxControl,0x03); // Tx2RF-En, Tx1RF-En disablen
_delay_ms(ms); // Delay for 1 ms
SetBitMask(RegTxControl,0x03); // Tx2RF-En, Tx1RF-En enable
}
else
ClearBitMask(RegTxControl,0x03); // Tx2RF-En, Tx1RF-En disablen
return status;
}
char M500PcdConfig(void)
{
char status;
uchar i;
uchar j;
if ((status = M500PcdReset()) == MI_OK)
{
WriteIO(RegClockQControl,0x0);
WriteIO(RegClockQControl,0x40);
_delay_us(110);
ClearBitMask(RegClockQControl,0x40); // clear bit ClkQCalib for
WriteIO(RegBitPhase,0xAD);
WriteIO(RegRxThreshold,0xFF);
WriteIO(RegRxControl2,0x01);
WriteIO(RegFIFOLevel,0x04);
WriteIO(RegTimerControl,0x02); // TStopRxEnd=0,TStopRxBeg=0,
// TStartTxEnd=1,TStartTxBeg=0
M500PcdSetTmo(1); // short timeout
WriteIO(RegIRqPinConfig,0x03); // interrupt active low enable
M500PcdRfReset(1); // Rf - reset and enable output driver
// initialize internal key memory
for (i = 0; i < 16; i++)
for (j = 0; j < 12; j++)
MKeys[j] = 0xff;
}
return status;
}
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;
uint tcount=1000;
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
// 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
case PCD_LOADKEYE2: // IdleIRq
case PCD_AUTHENT1: // IdleIRq
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;
waitFor = 0x04;
break;
default:
status = MI_UNKNOWN_COMMAND;
}
if (status == MI_OK)
{
// Initialize uC Timer for global Timeout management
irqEn |= 0x20; // always enable timout irq
waitFor |= 0x20; // always wait for timeout
WriteIO(RegInterruptEn,irqEn | 0x80); //necessary interrupts are enabled
WriteIO(RegCommand,cmd); //start command
// wait for commmand completion
// a command is completed, if the corresponding interrupt occurs
// or a timeout is signaled
while (!(MpIsrInfo->irqSource & waitFor||(!(tcount--))));
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
{ // timer 2 expired
status = MI_ACCESSTIMEOUT;
}
else
status = MpIsrInfo->status; // set status
if (status == MI_OK) // no timeout error occured
{
if (tmpStatus = (ReadIO(RegErrorFlag) & 0x17)) // 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 (cmd == PCD_TRANSCEIVE)
{
// 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;
}
}
MpIsrInfo = 0; // reset interface variables for ISR
MpIsrOut = 0;
MpIsrIn = 0;
return status;
}
void int_init(void)
{
EICRA|=(1<<ISC11);
EIMSK|=(1<<INT1);
EIFR=0xff;
DDRD&=~(1<<PD1);
PORTD|=(1<<PD1);
sei();
}
char PcdReadE2(unsigned short startaddr,
unsigned char length,
unsigned char* _data)
{
char status = MI_OK;
uchar i;
// ************* Cmd Sequence **********************************
ResetInfo(MInfo);
MSndBuffer[0] = startaddr & 0xFF;
MSndBuffer[1] = (startaddr >> 8) & 0xFF;
MSndBuffer[2] = length;
MInfo.nBytesToSend = 3;
status = M500PcdCmd(PCD_READE2,
MSndBuffer,
MRcvBuffer,
&MInfo);
if (status == MI_OK)
{
for(i=0;i<length;i++)
_data=MRcvBuffer;
}
else // Response Processing
{
_data[0] = 0;
}
return status ;
}
///////////////////////////////////////////////////////////////////////
// M I F A R E C O M M O N R E Q U E S T
///////////////////////////////////////////////////////////////////////
char M500PiccRequest(unsigned char req_code,unsigned char *atq)
{
char status = MI_OK;
//************* initialize ******************************
WriteIO(RegChannelRedundancy,0x03); // RxCRC and TxCRC disable, parity enable
ClearBitMask(RegControl,0x08); // disable crypto 1 unit
WriteIO(RegBitFraming,0x07); // set TxLastBits to 7
SetBitMask(RegTxControl,0x03); // Tx2RF-En, Tx1RF-En enable
ResetInfo(MInfo);
MSndBuffer[0] = req_code;
MInfo.nBytesToSend = 1;
status = M500PcdCmd(PCD_TRANSCEIVE,
MSndBuffer,
MRcvBuffer,
&MInfo);
if (status) // error occured
{
*atq = 0;
}
else
{
if (MInfo.nBitsReceived != 16) // 2 bytes expected
{
*atq = 0;
status = MI_BITCOUNTERR;
}
else
{
status = MI_OK;
memcpy(atq,MRcvBuffer,2);
}
}
return status;
}
int main(void)
{
char z;
unsigned char tt1[2];
Init_12864();
int_init();
Device_Init();
if(M500PcdConfig()==MI_OK)
{
Write_com(0x80);
Write_data(0x35);
z=ReadIO(RegFIFOLevel);
Write_com(0x90);
Write_data(0x30+z/16);
Write_data(0x30+z%16);
z=PcdReadE2(0,4,Snr_RC500);
if(z==MI_OK)
{
Write_com(0x91);
Write_data(0x30+(Snr_RC500[0]/16));
Write_data(0x30+(Snr_RC500[0]%16));
Write_data(0x30+(Snr_RC500[1]/16));
Write_data(0x30+(Snr_RC500[1]%16));
Write_data(0x30+(Snr_RC500[2]/16));
Write_data(0x30+(Snr_RC500[2]%16));
Write_data(0x30+(Snr_RC500[3]/16));
Write_data(0x30+(Snr_RC500[3]%16));
}
else
{
z=-z;
Write_com(0x91);
Write_data(0x30+z/16);
Write_data(0x30+z%16);
}
// z=M500PiccRequest(PICC_REQALL,tt1);
// if(z==MI_OK)
// LED_ON();
}
while(1)
{
z=M500PiccRequest(PICC_REQALL,tt1);
if(z==MI_OK)
LED_ON();
else
LED_OFF();
}
}
SIGNAL(SIG_INTERRUPT1)
{
static unsigned char irqBits;
static unsigned char irqMask;
static unsigned char nbytes;
static unsigned char cnt;
EIFR|=(1<<INT1); // Clear interrupt request flag
if (MpIsrInfo && MpIsrOut && MpIsrIn) // transfer pointers have to be set correctly
{
while( ReadRawIO(RegPrimaryStatus) & 0x08) // loop while IRQ pending
// Attention: IRQ bit is
// inverted when used with
// low activ IRQ
{
irqMask = ReadRawIO(RegInterruptEn); // read enabled interrupts
// read pending interrupts
irqBits = ReadRawIO(RegInterruptRq) & irqMask;
MpIsrInfo->irqSource |= irqBits; // save pending interrupts
//************ LoAlertIRQ ******************
if (irqBits & 0x01) // LoAlert
{
nbytes = MFIFOLength - ReadRawIO(RegFIFOLength);
// less bytes to send, than space in FIFO
if ((MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent) <= nbytes)
{
nbytes = MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent;
WriteRawIO(RegInterruptEn,0x01); // disable LoAlert IRQ
}
// write remaining data to the FIFO
for ( cnt = 0;cnt < nbytes;cnt++)
{
WriteRawIO(RegFIFOData,MpIsrOut[MpIsrInfo->nBytesSent]);
MpIsrInfo->nBytesSent++;
}
WriteRawIO(RegInterruptRq,0x01); // reset IRQ bit
}
//************* TxIRQ Handling **************
if (irqBits & 0x10) // TxIRQ
{
WriteRawIO(RegInterruptRq,0x10); // reset IRQ bit
WriteRawIO(RegInterruptEn,0x82); // enable HiAlert Irq for
// response
if (MpIsrInfo->cmd == PICC_ANTICOLL1) // if cmd is anticollision
{ // switch off parity generation
WriteRawIO(RegChannelRedundancy,0x02); // RXCRC and TXCRC disable, parity disable
}
}
//************* HiAlertIRQ or RxIRQ Handling ******************
if (irqBits & 0x0E) // HiAlert, Idle or RxIRQ
{
// read some bytes ( length of FIFO queue)
// into the receive buffer
nbytes = ReadRawIO(RegFIFOLength);
// read date from the FIFO and store them in the receive buffer
for ( cnt = 0; cnt < nbytes; cnt++)
{
MpIsrIn[MpIsrInfo->nBytesReceived] = ReadRawIO(RegFIFOData);
MpIsrInfo->nBytesReceived++;
}
WriteRawIO(RegInterruptRq,0x0A & irqBits);
// reset IRQ bit - idle irq will
// be deleted in a seperate section
}
//************** IdleIRQ Handling ***********
if (irqBits & 0x04) // Idle IRQ
{
WriteRawIO(RegInterruptEn,0x20); // disable Timer IRQ
WriteRawIO(RegInterruptRq,0x20); // disable Timer IRQ request
irqBits &= ~0x20; // clear Timer IRQ in local var
MpIsrInfo->irqSource &= ~0x20; // clear Timer IRQ in info var
// when idle received, then cancel
// timeout
WriteRawIO(RegInterruptRq,0x04); // reset IRQ bit
// status should still be MI_OK
// no error - only used for wake up
}
//************* TimerIRQ Handling ***********
if (irqBits & 0x20) // timer IRQ
{
WriteRawIO(RegInterruptRq,0x20); // reset IRQ bit
MpIsrInfo->status = MI_NOTAGERR; // timeout error
// otherwise ignore the interrupt
}
}
}
} |
|