⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcdutils.c

📁 此程序为13.56MHz的RFID底层读写卡程序
💻 C
字号:
#include <string.h>
#include <stdio.h>
#include <PcdUtils.h>
#include <MfRc500.h>
#include <RcComm.h>
#include <MfErrNo.h>
#include "Hardware.h"
#include "PcdShare.h"
#include "MfReg.h"

static MfCmdInfo     * MpIsrInfo;
static unsigned char * MpIsrOut;
static unsigned char * MpIsrIn;

//unsigned char RxTxBuffer[MAX_RF_BUF_SIZE];

void PcdSetTmo(unsigned char tmoLength);
void ClearBitMask(unsigned char reg,unsigned char mask);
void SetBitMask(unsigned char reg,unsigned char mask);
void FlushFIFO(void);
char  PcdSingleResponseCmd(unsigned char cmd,
               unsigned char * send,
               unsigned char * rcv,
               MfCmdInfo *info);
///////////////////////////////////////////////////////////////////////
//         S e t   T i m e o u t   L E N G T H
///////////////////////////////////////////////////////////////////////
void PcdSetTmo(unsigned char tmoLength)
{
    switch(tmoLength)
   {  // timer clock frequency 13,56 MHz
      case 1:                         // short timeout (1,0 ms)
         WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
         WriteRC(RegTimerReload,0x6a);// TReloadVal = 'h6a =106(dec)
         break;
      case 2:                       // medium timeout (1,5 ms)
         WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
         WriteRC(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
         break;
      case 3:                       // long timeout (6 ms)
         WriteRC(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
         WriteRC(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
         break;
      case 4:                       // long timeout (9.6 ms)
         WriteRC(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
         WriteRC(RegTimerReload,0xff);// TReloadVal = 'ff =255(dec)
         break;
      case 5:
         WriteRC(RegTimerClock,0x0f); // TAutoRestart=0,TPrescale=4*128
         WriteRC(RegTimerReload,0xff);// TReloadVal = 'ff =255(dec)
         break;
    /* case 10:                        // (309.3 ms) FWI=10
         WriteRC(RegTimerClock,0x0F); // TAutoRestart=0,TPrescale=256*128
         WriteRC(RegTimerReload,0x81);// TReloadVal = 'h81 =129(dec)
         break;   */
      default:                       // short timeout (1,0 ms)
         WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
         WriteRC(RegTimerReload,tmoLength);// TReloadVal = tmoLength
         break;
   }
}

//////////////////////////////////////////////////////////////////////
//   S E T   A   B I T   M A S K
///////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask) //
{
   char tmp    = 0x0;

   tmp = ReadRC(reg);
   WriteRC(reg,tmp | mask);  // set bit mask
}

//////////////////////////////////////////////////////////////////////
//   C L E A R   A   B I T   M A S K
///////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)
{
   char tmp = 0x0;

   tmp = ReadRC(reg);
   WriteRC(reg,tmp & ~mask);  // clear bit mask
}

///////////////////////////////////////////////////////////////////////
//                  F L U S H    F I F O
///////////////////////////////////////////////////////////////////////
void FlushFIFO(void)
{
   SetBitMask(RegControl,0x01);
}

//////////////////////////////////////////////////////////////////////
//       W R I T E   A   P C D   C O M M A N D
///////////////////////////////////////////////////////////////////////
char  PcdSingleResponseCmd(unsigned char cmd,
               unsigned char * send,
               unsigned char * rcv,
               MfCmdInfo *info)
{
   char  status    = MI_OK;
   char  tmpStatus;
   unsigned char lastBits;

   unsigned char irqEn     = 0x00;
   unsigned char waitFor   = 0x00;
   unsigned char timerCtl  = 0x00;

   unsigned long TimeOutCount;


   WriteRC(RegInterruptEn,0x7F); // disable all interrupts
   WriteRC(RegInterruptRq,0x7F); // reset interrupt requests
   WriteRC(RegCommand,PCD_IDLE); // terminate probably running command

   FlushFIFO();            // flush FIFO buffer

   // save info structures to module pointers
   MpIsrInfo = info;
   MpIsrOut  = send;
   MpIsrIn   = rcv;

   // initialising the ISR-Function pointer for mifare
   // protocol - do this after initialising the MpXXXX variables
//   PcdIsrFct = SingleResponseIsr;
   //OpenExternInt0();
   info->irqSource = 0x0; // reset interrupt flags
   OpenExternInt0();
//   READER_INT_ENABLE;
   // 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;
         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 = -(ReadRC(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 = -(ReadRC(RegBitFraming) >> 4);
         irqEn = 0x3d;//0x1d//0x3d//////allen 10.23
         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    /////allen 10.23
      waitFor|=0x20;                      // always wait for timeout///delete it

      WriteRC(RegInterruptEn,irqEn | 0x80);  //necessary interrupts are enabled // count up from 1

      WriteRC(RegCommand,cmd);               //start command

      // wait for commmand completion
      // a command is completed, if the corresponding interrupt occurs
      // or a timeout is signaled

      TimeOutCount=14049;                        //change from 4049
      while (!(MpIsrInfo->irqSource & waitFor
               || !TimeOutCount))                // wait for cmd completion or timeout
      {
                TimeOutCount--;
      }

      WriteRC(RegInterruptEn,0x7F);          // disable all interrupts
      WriteRC(RegInterruptRq,0x7F);          // clear all interrupt requests
      SetBitMask(RegControl,0x04);         // stop timer now

      WriteRC(RegCommand,PCD_IDLE);          // reset command register

        //Temp=ReadRC(RegFIFOLength);
        //Temp=ReadRC(RegFIFOData);

     if (!(MpIsrInfo->irqSource & waitFor))   // reader has not terminated
     {                                        // timer 3 expired
        status = MI_ACCESSTIMEOUT;
     }
     else
         status = MpIsrInfo->status;           // set status

      if (status == MI_OK)                     // no timeout error occured
      {
         if ((tmpStatus = (ReadRC(RegErrorFlag) & 0x17))) // error occured
         {
            if (tmpStatus & 0x01)   // collision detected
            {
               info->collPos = ReadRC(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 || cmd == PCD_RECEIVE)
         {
            // number of bits in the last byte
            lastBits = ReadRC(RegSecondaryStatus) & 0x07;
            if (lastBits)
               info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
            else
               info->nBitsReceived += info->nBytesReceived * 8;
         }
      }
      else
      {
         info->collPos = 0x00;
      }
   }

//   READER_INT_DISABLE;

   //PcdIsrFct = EmptyPcdIsrFct; // reset the ISR-Function pointer to
                               // an empty function body
                               // do this before clearing the Mp XXXX variables
	CloseExternInt0();
   MpIsrInfo = 0;         // reset interface variables for ISR
   MpIsrOut  = 0;
   MpIsrIn   = 0;
   return status;
}

///////////////////////////////////////////////////////////////////////////////
//                       Interrupt Handler RIC
///////////////////////////////////////////////////////////////////////////////
void SingleResponseIsr(void)
{
   unsigned char  irqBits;                //static
   unsigned char  irqMask;
   unsigned char  oldPageSelect;
   unsigned char  nbytes;
   unsigned char  cnt;

   if (MpIsrInfo && MpIsrOut && MpIsrIn)  // transfer pointers have to be set
                                          // correctly
   {
      oldPageSelect = ReadRawRC(RegPage); // save old page select
                                          // Attention: ReadRC cannnot be
                                          // used because of the internal
                                          // write sequence to the page
                                          // reg
      WriteRawRC(RegPage,0x80);                   // select page 0 for ISR
      while( (ReadRawRC(RegPrimaryStatus) & 0x08)) // loop while IRQ pending
      {
         irqMask = ReadRawRC(RegInterruptEn); // read enabled interrupts
         // read pending interrupts
         irqBits = ReadRawRC(RegInterruptRq) & irqMask;
         MpIsrInfo->irqSource |= irqBits; // save pending interrupts
         //************ LoAlertIRQ ******************
         if (irqBits & 0x01)    // LoAlert
         {
            nbytes = MFIFOLength - ReadRawRC(RegFIFOLength);
            // less bytes to send, than space in FIFO
            if ((MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent) <= nbytes)
            {
               nbytes = MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent;
             WriteRawRC(RegInterruptEn,0x01); // disable LoAlert IRQ
            }
            // write remaining data to the FIFO
            for ( cnt = 0;cnt < nbytes;cnt++)
            {
               WriteRawRC(RegFIFOData,MpIsrOut[MpIsrInfo->nBytesSent]);
               MpIsrInfo->nBytesSent++;
            }
            WriteRawRC(RegInterruptRq,0x01);  // reset IRQ bit
         }

         //************* TxIRQ Handling **************
         if (irqBits & 0x10)       // TxIRQ
         {
            WriteRawRC(RegInterruptRq,0x10);    // reset IRQ bit
            WriteRawRC(RegInterruptEn,0x82);    // enable HiAlert Irq for
                                                // response
            if (MpIsrInfo->cmd == PICC_ANTICOLL1) // if cmd is anticollision
            {                                     // switch off parity generation
               WriteRC(RegChannelRedundancy,0x02); // RxCRC and TxCRC disable, parity disable
               WriteRawRC(RegPage,0x00);  // reset page address
            }
         }

         //************* HiAlertIRQ or RxIRQ Handling ******************
         if (irqBits & 0x0E) // HiAlert, Idle or RxIRQ
         {
            // read some bytes ( length of FIFO queue)
            // into the receive buffer
            nbytes = ReadRawRC(RegFIFOLength);
            // read date from the FIFO and store them in the receive buffer
            for ( cnt = 0; cnt < nbytes; cnt++)
            {
               MpIsrIn[MpIsrInfo->nBytesReceived] = ReadRawRC(RegFIFOData);
               MpIsrInfo->nBytesReceived++;
            }
            WriteRawRC(RegInterruptRq,0x0A & irqBits);
                                       // reset IRQ bit - idle irq will
                                       // be deleted in a seperate section
         }

         //************** IdleIRQ Handling ***********
         if (irqBits & 0x04)     // Idle IRQ
         {
            WriteRawRC(RegInterruptEn,0x20); // disable Timer IRQ
            WriteRawRC(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
            WriteRawRC(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
         {
            WriteRawRC(RegInterruptRq,0x20); // reset IRQ bit
            MpIsrInfo->status = MI_NOTAGERR; // timeout error
                                             // otherwise ignore the interrupt
         }

      }
      WriteRawRC(RegPage,oldPageSelect | 0x80);
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -