搜索
bottom↓
回复: 5

mega64+MFRC500读取芯片EEPROM问题

[复制链接]

出0入0汤圆

发表于 2011-10-26 09:53:09 | 显示全部楼层 |阅读模式
我最近用AVR的mega64来驱动MFRC500,本来是用STC12C5A60S2来驱动的,用STC驱动的时候读取芯片位于EEPROM内的序列号,发现每次读出来都会变,就是没复位一次就变,一开始怀疑是在使用STC系列单片机的内部集成的外扩RAM时和总线冲突了,但换成AVR后,使用的是内部RAM的数据变量,足够用了,发现这个问题还是存在。

按理说EEPROM第一到第五字节是芯片的序列号,为:0x30 0x88 0xf8,0x00,xx。但我每复位一次就不一样,情况是如下:
xx,0x88,xx,xx
xx,xx,0xf8,0x00
0x30,xx,xx,xx
.......
.......
.......
就是每次复位有一两个值是对的,但不能都正确读出,现在怀疑是我电路是不是有问题,数字部分的电路,我的电路如下:
  
RC500电路图 (原文件名:}H@NSQFO6[6[ARR2AN$SN5C.jpg)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 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
         }
         
      }
   }               
}

出0入0汤圆

 楼主| 发表于 2011-10-26 09:57:17 | 显示全部楼层
能帮我看下哪里出问题了吗

出0入0汤圆

发表于 2012-12-26 10:48:34 | 显示全部楼层
你好,你的问题找到原因了吗?
我现在读EEPROM也有问题,具体表现在对RC500发下命令之后,得不到命令执行完成之后的中断,比如IDLE中断也不能产生,并且示波器上看RC500的IRQ脚没有任何触发信号。比较疑惑~

出0入0汤圆

发表于 2012-12-26 11:17:59 | 显示全部楼层
我已经找到我问题的原因了,IRQ硬件设置默认是开漏,我没有接上拉电阻,接一个就好了。

出0入0汤圆

发表于 2013-4-10 15:36:35 来自手机 | 显示全部楼层
学习一下....
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 03:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表