搜索
bottom↓
回复: 2

读RFID为什么要延时384us啊?

[复制链接]

出0入0汤圆

发表于 2010-12-1 09:23:16 | 显示全部楼层 |阅读模式
最近在调试EM4100卡。研究了下“bozai 章其波”的程序。http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=213102&bbs_page_no=1&bbs_id=1000  26楼、版本2。其中,用到了384us的延时。为什么要延时啊?延时后,不是就乱了吗?怎么还能接收到正确的数据呢?弄不明白,那位大虾讲解一下。
程序:

/*                 检测方法
1).确定起始位,首先要正确找到数据1 按规则下跳为1 上跳为0. 可检测高电平并等其变低
        但这会把0错检为1因为0也存在高电平。但是如果检测到一个周期的高电平(数据01)则可
        确定找到了数据1,找到1后就可以同步了,因为EM4100卡最后一位数据就是0正好可以利用
        作为判断的特征。

2).对于数据的确定,由于有了同步则可在同步后延时384us即3/4个码原周期在判断接受段电平如何
        如为高则置数据为1,并一直等到低电平的出现,相反则等高电平的出现,并在此之间插入超时
        判断。这样,一个完整的数据判断就完成了,并确保数据的准确性,另外这种方法的抗干扰性
        会非常好,而如果采用定时同步的话则会因信号的畸变而引起数据出错,整体会导致读卡几率降低
        但是此程序也有其缺点,因为采用纯延时判断的手段,因此其占用单片机的运行时间比较大。

3).同步后开始接受同步数据即9个1,这一部分用一个循环做,如果出错则放弃接收

4).同步数据接收完后,则开始接受数据,数据分11行5列接收以利于校验位的判断
        如有出错则放弃数据

5).如一切正常则返回卡号,如因尝试读卡次数到了则返回0以表示没有卡

6). 作者:章其波
        时间:2006-5-15
        Email:sudazqb@163.com
        Phone:13771767085
        QQ:   272200296
       
心得:
       
此程序真的很烦,花了我近六个小时
其中的循环真的是太绕人了
但这个程序比我之前那个用定时同步写的程序要好多了
由于没有见过别人是怎么写的,这仅是我闭门造车造出来的
相信一定有高人写出更好的程序
                                                                                                                                       
*/



#include"EM4100.h"


//精确的384us延时,此延时可以不严格,但要大于256us小于512us
void Delay384us()
{
        uchar i=DELAY_VAL;
        while(i--);
}


//读取卡号,
ulong Read_Card()
{
        uchar i=0;        //起始位的计数值
        uchar error;  //时间溢出的计数值
        uchar error_flag; //时间溢出标志
        uchar row,col;          //行列寄存器
        uchar row_parity;  //行校验寄存器
        uchar col_parity[5]; //列校验寄存器
        uchar _data;                //数据寄存器
        ulong temp;                        //卡号寄存器
        ulong timeout=0;         //搜索次数寄存器
        while(1)
        {               
                if(timeout==10)return 0;//尝试10次搜索,如没有责返回0
                else timeout++;
                error=0;          //时间溢出计数器清零
                while(Manchester_IN==0)//等高电平
                {
                        if(error==TIME_OF)
                                break;//超时退出
                        else error++;
                }        
                if(error==100)
                        continue;//结束本次主循环
                else error=0;
                       
                Delay384us();          
                if(Manchester_IN)//寻找真正的1起始位,利用01的波形确定1起始位,即最后一位加第一位
                {         
                        for(i=0;i<8;i++)//判断是否是真的起始位
                        {          
                                error=0;                           //限定等待时间
                                while(Manchester_IN)
                                {       
                                        if(error==TIME_OF)
                                        {          
                                                error_flag=1;        //时间溢出
                                                break;                //退出
                                        }
                                        else error++;
                                }         
                                Delay384us();                        //延时至下一码原
                                if(Manchester_IN&&error_flag==0); //判断下一位是否为1 和是否没有时间溢出
                                else break;                        //不是1退出,溢出退出                          
                        }
                        if(error_flag)//因时间溢出造成的本次主循环退出
                        {          
                                error_flag=0;
                                continue;        //退出本次循环
                        }
                        else;
                        if(i==8)  //起始位接受完并且正确后开始接受数据
                        {       
                                error_flag=0;
                                error=0;         //限定等待时间
                                while(Manchester_IN)
                                {  
                                        if(error==TIME_OF)
                                        {       
                                                error_flag=0;
                                                break;                 //时间溢出造成的出错
                                        }
                                        else error++;
                                }          
                                if(error_flag)          
                                {
                                        error_flag=0;
                                        continue;           //因等待待第一个正式数据错误引起的本次主循环退出
                                }
                                else;
                                //所有列校验清零
                                col_parity[0]=col_parity[1]=col_parity[2]=col_parity[3]=col_parity[4]=0;
                                for(row=0;row<11;row++)        //共11行数据
                                {
                                        for(col=0,row_parity=0/*行校验清零*/;col<5;col++)//共5列数据
                                        {
                                                Delay384us();  //延时至下一码原
                                                if(Manchester_IN)_data=1;  //数据为1
                                                else _data=0;                           //数据为0
                                                if(col<4&&row<10)                   //数据区的接受,后四个字节
                                                {
                                                        temp<<=1;                         //左移一位
                                                        temp+=(ulong)_data;         //数据相加
                                                }
                                                else;
                                                row_parity+=_data;                 //行校验加入数据
                                                col_parity[col]+=_data;         //相应列校验加入数据  虽最后一列没有校验但为了方便也加上
                                                error=0;                                 //限定等待时间清零
                                                while(Manchester_IN==(bit)_data)
                                                {
                                                        if(error==TIME_OF)                  //由于时间溢出造成的数据出错
                                                        {       
                                                                error_flag=1;
                                                                break;                          //退出本while循环
                                                        }
                                                        else error++;
                                                }
                                                if(error_flag)break;         //出错退出内层for循环
                                                else;
                                        }
                                        if(row<10)//最后一行没有校验所以要加限制
                                        {
                                                if((row_parity&0x01)||error_flag) //出错退出外for循环
                                                {
                                                        temp=0;
                                                        error_flag=1;
                                                        break;                         //退出
                                                }
                                                else;
                                        }
                                        else;          
                                }

                                //对最后接收的列校验进行判断,及对来自上面数据错误error_flag处理以结束本次主循环
                                if(error_flag||((col_parity[0]&0x01)&&(col_parity[1]&0x01)&&(col_parity[2]&0x01)&&(col_parity[3]&0x01)))
                                {        //最后一列没有校验                                                                                                 
                                        error_flag=0;
                                        temp=0;
                                        continue; //退出本次循环
                                }
                                else return temp;//将正确的数据返回
                        }
                        continue;
                }
                continue;
        }
}

出0入0汤圆

发表于 2012-2-18 11:37:33 | 显示全部楼层
384us即3/4个码原周期,在判断接受段电平如何
如为高则置数据为1,并一直等到低电平的出现,相反则等高电平的出现,并在此之间插入超时
判断。

出0入0汤圆

发表于 2012-2-18 11:40:53 | 显示全部楼层
384us即3/4个码原周期,在判断接受段电平如何
如为高则置数据为1,并一直等到低电平的出现,相反则等高电平的出现,并在此之间插入超时
判断。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-7 19:17

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

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