相关的程序: <br />void Device_Init(void) <br />{ <br /> MCUCR |= (1<<SRE); //使能总线 <br /> XMCRA = 0x00; <br /> XMCRB = 0x07; <br /> DDR_RC500RST(); <br /> DDR_RC500IRQ(); <br /> DDRD &= ~(1<<PD0); <br /> PORTD |= (1<<PD0); <br />} <br />void WriteRawIO(uint addr,uchar value) <br />{ <br /> addr = 0x7f00 + addr; <br /> (*(volatile unsigned char *)addr) = value; <br />} <br />uchar ReadRawIO(uint addr) <br />{ <br /> addr = 0x7f00 + addr; <br /> return (*(volatile unsigned char *)addr); <br />} <br />char M500PcdCmd(uchar cmd,volatile uchar* send,volatile uchar* rcv,volatile MfCmdInfo *info) <br />{ <br /> char status = MI_OK; <br /> char tmpStatus ; <br /> uchar lastBits; <br /><br /> uchar irqEn = 0x00; <br /> uchar waitFor = 0x00; <br /> uchar timerCtl = 0x00; <br /><br /> WriteIO(RegInterruptEn,0x7F); // disable all interrupts <br /> WriteIO(RegInterruptRq,0x7F); // reset interrupt requests <br /> WriteIO(RegCommand,PCD_IDLE); // terminate probably running command <br /><br /> FlushFIFO(); // flush FIFO buffer <br /><br /> // save info structures to module pointers <br /> MpIsrInfo = info; <br /> MpIsrOut = send; <br /> MpIsrIn = rcv; <br /><br /> info->irqSource = 0x0; // reset interrupt flags <br /> // depending on the command code, appropriate interrupts are enabled (irqEn) <br /> // and the commit interrupt is choosen (waitFor). <br /> switch(cmd) <br /> { <br /> case PCD_IDLE: // nothing else required <br /> irqEn = 0x00; <br /> waitFor = 0x00; <br /> break; <br /> case PCD_WRITEE2: // LoAlert and TxIRq <br /> irqEn = 0x11; <br /> waitFor = 0x10; <br /> break; <br /> case PCD_READE2: // HiAlert, LoAlert and IdleIRq <br /> irqEn = 0x07; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_LOADCONFIG: // IdleIRq <br /> case PCD_LOADKEYE2: // IdleIRq <br /> case PCD_AUTHENT1: // IdleIRq <br /> irqEn = 0x05; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_CALCCRC: // LoAlert and TxIRq <br /> irqEn = 0x11; <br /> waitFor = 0x10; <br /> break; <br /> case PCD_AUTHENT2: // IdleIRq <br /> irqEn = 0x04; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_RECEIVE: // HiAlert and IdleIRq <br /> info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4); <br /> irqEn = 0x06; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_LOADKEY: // IdleIRq <br /> irqEn = 0x05; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_TRANSMIT: // LoAlert and IdleIRq <br /> irqEn = 0x05; <br /> waitFor = 0x04; <br /> break; <br /> case PCD_TRANSCEIVE: // TxIrq, RxIrq, IdleIRq and LoAlert <br /> info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4); <br /> irqEn = 0x3D; <br /> waitFor = 0x04; <br /> break; <br /> default: <br /> status = MI_UNKNOWN_COMMAND; <br /> } <br /> if (status == MI_OK) <br /> { <br /> // Initialize uC Timer for global Timeout management <br /> irqEn |= 0x20; // always enable timout irq <br /> waitFor |= 0x20; // always wait for timeout <br /><br /> start_timeout(4000); // initialise and start guard timer for reader <br /> // 50us resolution, 200ms <br /> <br /> WriteIO(RegInterruptEn,irqEn | 0x80); //necessary interrupts are enabled <br /> WriteIO(RegCommand,cmd); //start command <br /><br /> // wait for commmand completion <br /> // a command is completed, if the corresponding interrupt occurs <br /> // or a timeout is signaled <br /><br /> while (!(MpIsrInfo->irqSource & waitFor|| T2IR)); // wait for cmd completion or timeout <br /><br /> WriteIO(RegInterruptEn,0x7F); // disable all interrupts <br /> WriteIO(RegInterruptRq,0x7F); // clear all interrupt requests <br /> SetBitMask(RegControl,0x04); // stop timer now <br /><br /> stop_timeout(); // stop timeout for reader <br /> WriteIO(RegCommand,PCD_IDLE); // reset command register <br /><br /><br /> if (!(MpIsrInfo->irqSource & waitFor)) // reader has not terminated <br /> { // timer 2 expired <br /> status = MI_ACCESSTIMEOUT; <br /> } <br /> else <br /> status = MpIsrInfo->status; // set status <br /><br /> if (status == MI_OK) // no timeout error occured <br /> { <br /> if (tmpStatus = (ReadIO(RegErrorFlag) & 0x17)) // error occured <br /> { <br /> if (tmpStatus & 0x01) // collision detected <br /> { <br /> info->collPos = ReadIO(RegCollpos); // read collision position <br /> status = MI_COLLERR; <br /> } <br /> else <br /> { <br /> info->collPos = 0; <br /> if (tmpStatus & 0x02) // parity error <br /> { <br /> status = MI_PARITYERR; <br /> } <br /> } <br /> if (tmpStatus & 0x04) // framing error <br /> { <br /> status = MI_FRAMINGERR; <br /> } <br /> if (tmpStatus & 0x10) // FIFO overflow <br /> { <br /> FlushFIFO(); <br /> status = MI_OVFLERR; <br /> } <br /> if (tmpStatus & 0x08) //CRC error <br /> { <br /> status = MI_CRCERR; <br /> } <br /> if (status == MI_OK) <br /> status = MI_NY_IMPLEMENTED; <br /> } <br /> // if the last command was TRANSCEIVE, the number of <br /> // received bits must be calculated - even if an error occured <br /> if (cmd == PCD_TRANSCEIVE) <br /> { <br /> // number of bits in the last byte <br /> lastBits = ReadIO(RegSecondaryStatus) & 0x07; <br /> if (lastBits) <br /> info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits; <br /> else <br /> info->nBitsReceived += info->nBytesReceived * 8; <br /> } <br /> } <br /> else <br /> { <br /> info->collPos = 0x00; <br /> } <br /> } <br /> MpIsrInfo = 0; // reset interface variables for ISR <br /> MpIsrOut = 0; <br /> MpIsrIn = 0; <br /> return status; <br />} <br />char M500PiccCommonRequest(uchar req_code,uchar *atq) <br />{ <br /> char status = MI_OK; <br /><br /> //************* initialize ****************************** <br /> WriteIO(RegChannelRedundancy,0x03); // RxCRC and TxCRC disable, parity enable <br /> ClearBitMask(RegControl,0x08); // disable crypto 1 unit <br /> WriteIO(RegBitFraming,0x07); // set TxLastBits to 7 <br /> SetBitMask(RegTxControl,0x03); // Tx2RF-En, Tx1RF-En enable <br /> <br /> ResetInfo(MInfo); <br /> MSndBuffer[0] = req_code; <br /> MInfo.nBytesToSend = 1; <br /> status = M500PcdCmd(PCD_TRANSCEIVE,MSndBuffer,MRcvBuffer,&MInfo); <br /> <br /> if (status) // error occured <br /> { <br /> *atq = 0; <br /> } <br /> else <br /> { <br /> if (MInfo.nBitsReceived != 16) // 2 bytes expected <br /> { <br /> *atq = 0; <br /> status = MI_BITCOUNTERR; <br /> } <br /> else <br /> { <br /> status = MI_OK; <br /> memcpy(atq,MRcvBuffer,2); <br /> } <br /> } <br /> return status; <br />} <br />char PcdReadE2(uchar startaddr,uchar length,uchar* _data) <br />{ <br /> char status = MI_OK; <br /><br /> // ************* Cmd Sequence ********************************** <br /> ResetInfo(MInfo); <br /> MSndBuffer[0] = startaddr & 0xFF; <br /> MSndBuffer[1] = (startaddr >> 8) & 0xFF; <br /> MSndBuffer[2] = length; <br /> MInfo.nBytesToSend = 3; <br /> status = M500PcdCmd(PCD_READE2,MSndBuffer,MRcvBuffer,&MInfo); <br /> if (status == MI_OK) <br /> { <br /> memcpy(_data,MRcvBuffer,length); <br /> } <br /> else // Response Processing <br /> { <br /> _data[0] = 0; <br /> } <br /> return status ; <br />} <br />SIGNAL(SIG_INTERRUPT0) //Ext0 interrupt <br />{ <br /> static uchar irqBits; <br /> static uchar irqMask; <br /> static uchar nbytes; <br /> static uchar cnt; <br /><br /> EIFR |= (1<<INT0); // Clear interrupt request flag <br /> //WriteRawIO(0,0x80);//?????????????????? <br /> if (MpIsrInfo && MpIsrOut && MpIsrIn) // transfer pointers have to be set correctly <br /> { <br /> while( ReadRawIO(RegPrimaryStatus) & 0x08) // loop while IRQ pending <br /> //Attention: IRQ bit is <br /> // inverted when used with <br /> // low activ IRQ <br /> { <br /> irqMask = ReadRawIO(RegInterruptEn); // read enabled interrupts 读取激活的中断 <br /> // read pending interrupts <br /> irqBits = ReadRawIO(RegInterruptRq) & irqMask;//读取未激活的中断 <br /> MpIsrInfo->irqSource |= irqBits; // save pending interrupts 保存未激活的中断 <br /> //************ LoAlertIRQ ****************** <br /> if (irqBits & 0x01) // LoAlert 数据发送 <br /> { <br /> nbytes = MFIFOLength - ReadRawIO(RegFIFOLength); <br /> // less bytes to send, than space in FIFO <br /> if ((MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent) <= nbytes) <br /> { <br /> nbytes = MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent; <br /> WriteRawIO(RegInterruptEn,0x01); // disable LoAlert IRQ <br /> } <br /> // write remaining data to the FIFO <br /> for ( cnt = 0;cnt < nbytes;cnt++) <br /> { <br /> WriteRawIO(RegFIFOData,MpIsrOut[MpIsrInfo->nBytesSent]);//写数据到FIFO <br /> MpIsrInfo->nBytesSent++; <br /> } <br /> WriteRawIO(RegInterruptRq,0x01); // reset IRQ bit <br /> } <br /> //************* TxIRQ Handling **************发送结束中断处理 <br /> if (irqBits & 0x10) // TxIRQ <br /> { <br /> WriteRawIO(RegInterruptRq,0x10); // reset IRQ bit <br /> WriteRawIO(RegInterruptEn,0x82); // enable HiAlert Irq for response <br /> if (MpIsrInfo->cmd == PICC_ANTICOLL1) // if cmd is anticollision <br /> { // switch off parity generation <br /> WriteRawIO(RegChannelRedundancy,0x02); // RXCRC and TXCRC disable, parity disable <br /> } <br /> } <br /><br /> //************* HiAlertIRQ or RxIRQ Handling ******************接收数据中断处理 <br /> if (irqBits & 0x0E) // HiAlert, Idle or RxIRQ <br /> { <br /> // read some bytes ( length of FIFO queue) into the receive buffer <br /> // 读FIFO队列中的数据到 receive buffer <br /> nbytes = ReadRawIO(RegFIFOLength); <br /> // read date from the FIFO and store them in the receive buffer <br /> for ( cnt = 0; cnt < nbytes; cnt++) <br /> { <br /> MpIsrIn[MpIsrInfo->nBytesReceived] = ReadRawIO(RegFIFOData); <br /> MpIsrInfo->nBytesReceived++; <br /> } <br /> WriteRawIO(RegInterruptRq,0x0A & irqBits); <br /> // reset IRQ bit - idle irq will be deleted in a seperate section <br /> } <br /> <br /> //************** IdleIRQ Handling ***********指令寄存器清零 中断处理 <br /> if (irqBits & 0x04) // Idle IRQ <br /> { <br /> WriteRawIO(RegInterruptEn,0x20); // disable Timer IRQ <br /> WriteRawIO(RegInterruptRq,0x20); // disable Timer IRQ request <br /> irqBits &= ~0x20; // clear Timer IRQ in local var <br /> MpIsrInfo->irqSource &= ~0x20; <br /> // clear Timer IRQ in info var when idle received, then cancel timeout <br /> WriteRawIO(RegInterruptRq,0x04); <br /> // reset IRQ bit status should still be MI_OK no error - only used for wake up <br /> } <br /> <br /> //************* TimerIRQ Handling ***********超时中断处理 <br /> if (irqBits & 0x20) // timer IRQ <br /> { <br /> WriteRawIO(RegInterruptRq,0x20); // reset IRQ bit <br /> MpIsrInfo->status = MI_NOTAGERR; // timeout error <br /> // otherwise ignore the interrupt <br /> } <br /> <br /> } <br /> } <br />}
|