打印

RC500寻卡程序超时 求助 真心求助

[复制链接]
6679|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
er357951|  楼主 | 2012-5-15 17:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
RC500, TE, se, ST, pi
RT,直接切入正题目前在做一个RC500 IC卡读写器
本人很水,看到64个寄存器和来回嵌套的程序调用就萎了
后面在网上DOWN了一个程序,改了一下后测试,发现能用
RC500能起振,TX1和TX2也有波形。
初始化通过。
可是在给寻卡命令的时候,却卡在超时那一块了。
以本人有限水平Debug到了问题出在这里:
do
      {
sond=0;
         n = ReadRawRC(RegInterruptRq);//当定时器TimerValue 寄存器值减为0 时置位
         i--; sond=1;
      }
      while ((i!=0) && !(n&irqEn&0x20) && !(n&waitFor));

这里RegInterruptRq貌似定时器没有减为0,所以没有置位,所以一直超时
找了2天也没找到这个定时器是在什么情况下才递减。
无奈,所以特地来万能的坛求助,希望各位做过的大神帮帮小弟,度过这个难关,小弟不胜感激。
下面贴出那段程序,如果有必要我也可以贴出全部程序,就是不知道怎么贴。。。。
/////////////////////////////////////////////////////////////////////
//通过RC500和ISO14443卡通讯
//input: pi->MfCommand = RC500命令字
//       pi->MfLength  = 发送的数据长度
//       pi->MfData[]  = 发送数据
//output:status        = 错误字
//       pi->MfLength  = 接收的数据BIT长度
//       pi->MfData[]  = 接收数据
/////////////////////////////////////////////////////////////////////
char PcdComTransceive(struct TranSciveBuffer *pi)
{
   bit recebyte = 0;
   char status;
   unsigned char irqEn   = 0x00;
   unsigned char waitFor = 0x00;
   unsigned char lastBits;
   unsigned char n;
   unsigned int i;
   switch (pi->MfCommand)
   {
      case PCD_IDLE:
         irqEn   = 0x00;
         waitFor = 0x00;
         break;
      case PCD_WRITEE2:
         irqEn   = 0x11;
         waitFor = 0x10;
         break;
      case PCD_READE2:
         irqEn   = 0x07;
         waitFor = 0x04;
         recebyte=1;
         break;
      case PCD_LOADCONFIG:
      case PCD_LOADKEYE2:
      case PCD_AUTHENT1:
         irqEn   = 0x05;
         waitFor = 0x04;
         break;
      case PCD_CALCCRC:
         irqEn   = 0x11;
         waitFor = 0x10;
         break;
      case PCD_AUTHENT2:
         irqEn   = 0x04;
         waitFor = 0x04;
         break;
      case PCD_RECEIVE:
         irqEn   = 0x06;
         waitFor = 0x04;
         recebyte=1;
         break;
      case PCD_LOADKEY:
         irqEn   = 0x05;
         waitFor = 0x04;
         break;
      case PCD_TRANSMIT:
         irqEn   = 0x05;
         waitFor = 0x04;
         break;
      case PCD_TRANSCEIVE:
         irqEn   = 0x3D;
         waitFor = 0x04;
         recebyte=1;
         break;
      default:
         pi->MfCommand = MI_UNKNOWN_COMMAND;
         break;
   }
  

   if (pi->MfCommand != MI_UNKNOWN_COMMAND)
   {
      WriteRawRC(RegPage,0x00);
      WriteRawRC(RegInterruptEn,0x7F);
//清除中断使能
      WriteRawRC(RegInterruptRq,0x7F);
//清除中断标志
      WriteRawRC(RegCommand,PCD_IDLE);
//清除Command寄存器
      SetBitMask(RegControl,0x01);
//清除FIFO指针
      WriteRawRC(RegInterruptEn,irqEn|0x80);   
      for (i=0; i<pi->MfLength; i++)
      {
         WriteRawRC(RegFIFOData, pi->MfData[i]);//将数据写入FIFO
      }
      WriteRawRC(RegCommand, pi->MfCommand);//将指令写入Command寄存器
      i = 0x8500;
      do
      {
sond=0;
         n = ReadRawRC(RegInterruptRq);//当定时器TimerValue 寄存器值减为0 时置位
         i--; sond=1;
      }
      while ((i!=0) && !(n&irqEn&0x20) && !(n&waitFor));
      status = MI_COM_ERR;
//sond=0; AAA=0x01;
      if ((i!=0) && !(n&irqEn&0x20))
      {
  
         if (!(ReadRawRC(RegErrorFlag)&0x17))
         {
            status = MI_OK;
            if (recebyte) //从PICC读数据
            {
              
n = ReadRawRC(RegFIFOLength);//指示保存在FIFO 缓冲区的字节数

//写入FIFOData寄存器增加,读减少FIFOLength
              
lastBits = ReadRawRC(RegSecondaryStatus) & 0x07;
                if (lastBits)//显示最后接收字节的有效位个数如果为0 整个字节有效
                {
                   pi->MfLength = (n-1)*8 + lastBits;
                }
                else
                {
                   pi->MfLength = n*8;//计算比特数长度
                }
                if (n == 0)
                {
                   n = 1;
                }
                for (i=0; i<n; i++)
                {
                    pi->MfData[i] = ReadRawRC(RegFIFOData);//读出FIFO的数据
                }
            }
         }

else if (ReadRawRC(RegErrorFlag)&0x01)//如果检测到一个位冲突该位置位该位在PrepareRx


   //状态中接收器的启动阶段自动清零
         {

    status = MI_COLLERR;
            if (recebyte)
            {
              
n = ReadRawRC(RegFIFOLength);
              
lastBits = ReadRawRC(RegSecondaryStatus) & 0x07;
                if (lastBits)
                {
                   pi->MfLength = (n-1)*8 + lastBits;
                }
                else
                {
                   pi->MfLength = n*8;
                }
                if (n == 0)
                {
                   n = 1;
                }
                for (i=0; i<n; i++)
                {
                    pi->MfData[i+1] = ReadRawRC(RegFIFOData);
                }
            }

pi->MfData[0]=ReadRawRC(0x0B);
         }

      }
      else if (n & irqEn & 0x20)
      {   status = MI_NOTAGERR;   }
      else if (!(ReadRawRC(RegErrorFlag)&0x17))
      {   status = MI_ACCESSTIMEOUT;   }
      else
      {   status = MI_COM_ERR;    }

      WriteRawRC(RegInterruptEn,0x7F);
      WriteRawRC(RegInterruptRq,0x7F);
      SetBitMask(RegControl,0x04);           // stop timer now
      WriteRawRC(RegCommand,PCD_IDLE);
   }
   return status;
}

相关帖子

沙发
er357951|  楼主 | 2012-5-16 17:28 | 只看该作者
昨天把手册打印了看了几遍,发现触发定时器是在TimerReload被载入以后触发的,而且中途允许被重装和停止。原文如下:

定时器单元的主要部分是一个倒计数器 只要倒计数器不等于零 它就在每个定时器时钟减一 如果
TAutoRestart 使能 定时器不会减到零 减到 1 时 定时器在下个时钟将 TimerReload 值重新装入  
定时器通过将 TimerReload 寄存器值装入计数器模块立即启动 可由下列的事件之一触发  
y 第一个位发送到卡 TxBegin 事件 且 TStartTxBegin 为 1
y 最后一个位发送到卡 TxEnd 事件 且 TStartTxEnd 为 1
y 位 TStartNow设置为 1 通过微处理器  
注 每个启动事件都将 TimerReload 寄存器的值重装入定时器 因此 定时器是重复触发的 定时器
可配置为下列事件之一停止  
y 来自卡第一个有效位的接收 RxBegin 事件 且 TStopRxBegin 设置为 1
y 来自卡最后一个有效位的接收 RxEnd 事件 且 TStopRxEnd 设置为 1
y 计数器模块减到 0 且 TAutoResetstart 设置为 1
y 位 TStopNow设置为 1 通过微处理器  
装入新值 例如 将 0 装入 TimerReload 寄存器不会立即影响计数器 它只有到下次启动事件才会影
响计数器 因此 TimerReload 寄存器即使在定时器单元计数当中也可改变 改变 TimerReload 寄存器的结
果将在下次启动事件后显现出来  
如果置位 TStopNow将计数器停止 TimerIRq 不会发出信号  。

但是我检查了一遍程序,发现以上事件似乎都没有被触发。
由于51不能仿真(STC除外,也没钱。)
于是我就用一个LED灯低电平点亮的语句(sond=0)一条一条的加在每一条程序语句后来试
结果一直进入这条语句:
   else if (n & irqEn & 0x20)
      {   status = MI_NOTAGERR;   }

目前还在找原因,继续期望大虾解答。。。

使用特权

评论回复
板凳
er357951|  楼主 | 2012-5-17 21:49 | 只看该作者
郁闷怎么会没有人回答?。。。。

继续搞了一整天,渐渐找到眉目了。
问题还是在这个循环语句上:

do
      {         
         n = ReadRawRC(RegInterruptRq);//µ±¶¨Ê±Æ÷TimerValue ¼Ä´æÆ÷Öµ¼õΪ0 ʱÖÃλ
         i--;
      }
      while ((i!=0) && !(n&irqEn&0x20) && !(n&waitFor));

这一段后紧接着的是一个IF语句:
if ((i!=0) && !(n&irqEn&0x20)){...};

也就是说,第一个循环体要退出,满足的条件是最后一个条件,也就是这个:“!(n&waitFor))”要为零,
去掉逻辑非,也就是(n&waitFor)要为真。
经手册查得,此语句要为真,需要触发一个关于命令寄存器的中断位置位才行。
问题就出在这里了,这个程序用的是查询法,整篇没有一个中断函数,命令寄存器在上面那个循环体中貌似是改变不了的,这样就不能置位,最后一个条件就不能满足,也就无**常执行了。
我用一个全局变量采集Command寄存器的值,前后一直是0x1e,没变,这样就一直没法进入正轨了。

小弟很郁闷啊这几天,网上这方面资料也不多。希望各位大侠不丽赐教,帮帮我一把,我帮一个朋友做的毕业设计,快截止了。很郁闷啊。。。

使用特权

评论回复
地板
zjk103| | 2012-8-28 23:16 | 只看该作者
LZ这个程序跟我在网上找的貌似是同一个啊

使用特权

评论回复
5
heyuezhou| | 2012-10-11 10:31 | 只看该作者
楼主,那个RC500的寄存器是怎么读写的? 能让我看一下吗?

使用特权

评论回复
6
fengsth| | 2014-5-9 18:31 | 只看该作者
我也是卡到这里了
      else if (n & irqEn & 0x20)                        //(n & irqEn & 0x20)表示数据超限//为什么数据超限???
      {  
             send_s("MI_NOTAGERR!!!\r\n");  
             status = MI_NOTAGERR;  
          }

程序就跑到这里了  请问 楼主后来怎么解决的啊 我的  qq:843079356  求指教啊

使用特权

评论回复
7
ucos1986| | 2015-7-27 15:29 | 只看该作者
我这几天也在弄  我也卡这里的   麻烦大侠指点下  QQ574285920  

使用特权

评论回复
8
zhaoyu2005| | 2015-7-27 16:45 | 只看该作者
如果有条件,先弄个可以正常用的板子,测试程序,以免硬件问题,在软件里找,因为有几个电阻、电容需要匹配,弄不好的话,会出现寻不到卡。
如果没可用的硬件,那用示波器检测将 发射信号调到最强,然后在调程序

使用特权

评论回复
9
ucos1986| | 2015-7-28 15:17 | 只看该作者
我这个应该是寄存器配置问题
有卡和没卡打印出来的结果是不一样的
可是很奇怪的问题就是不管是否有卡在读卡器上   始终会答应MI_NOTAGERR这个标志   郁闷  头疼   明显的是卡寻到了

使用特权

评论回复
10
ljy335877679| | 2017-1-21 11:56 | 只看该作者
while ((i!=0) && !(n&irqEn&0x20) && !(n&waitFor));

你用串口输出一下是哪个条件退出的,如果 !(n&irqEn&0x20) 退出,表示内部定时器中断触发了,超时了,如果是这个退出,一般是定时设置太小了;如果是  !(n&waitFor) 就是你需要执行的已经成功执行了;(i!=0)退出,就是有其他问题了,可能是i的初始值设置太小或操作不对或配置有问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

57

帖子

1

粉丝