相关的程序: 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 } } } } |