|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-8-7 17:34:25
|
显示全部楼层
相关的程序:
void Device_Init(void)
{
MCUCR |= (1<<SRE); //使能总线
XMCRA = 0x00;
XMCRB = 0x07;
DDR_RC500RST();
DDR_RC500IRQ();
DDRD &= ~(1<<PD0);
PORTD |= (1<<PD0);
}
void WriteRawIO(uint addr,uchar value)
{
addr = 0x7f00 + addr;
(*(volatile unsigned char *)addr) = value;
}
uchar ReadRawIO(uint addr)
{
addr = 0x7f00 + addr;
return (*(volatile unsigned char *)addr);
}
char M500PcdCmd(uchar cmd,volatile uchar* send,volatile uchar* rcv,volatile MfCmdInfo *info)
{
char status = MI_OK;
char tmpStatus ;
uchar lastBits;
uchar irqEn = 0x00;
uchar waitFor = 0x00;
uchar 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
// 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
start_timeout(4000); // initialise and start guard timer for reader
// 50us resolution, 200ms
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|| T2IR)); // wait for cmd completion or timeout
WriteIO(RegInterruptEn,0x7F); // disable all interrupts
WriteIO(RegInterruptRq,0x7F); // clear all interrupt requests
SetBitMask(RegControl,0x04); // stop timer now
stop_timeout(); // stop timeout for reader
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;
}
// 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;
}
char M500PiccCommonRequest(uchar req_code,uchar *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;
}
char PcdReadE2(uchar startaddr,uchar length,uchar* _data)
{
char status = MI_OK;
// ************* 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)
{
memcpy(_data,MRcvBuffer,length);
}
else // Response Processing
{
_data[0] = 0;
}
return status ;
}
SIGNAL(SIG_INTERRUPT0) //Ext0 interrupt
{
static uchar irqBits;
static uchar irqMask;
static uchar nbytes;
static uchar cnt;
EIFR |= (1<<INT0); // Clear interrupt request flag
//WriteRawIO(0,0x80);//??????????????????
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]);//写数据到FIFO
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
// 读FIFO队列中的数据到 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
}
}
}
} |
|