原创 RFID读卡程序

2007-12-22 17:35 6037 4 7 分类: 通信
RFID读卡程序

关键字 :125k 、读卡程序 、RFID

一、 原理

1、硬件原理

1.1、硬件工作原理

说明 阅读器:基站 ;应答器:非接触ID卡。我们使用的MCU是at89s52(CS—Ⅲ板)。

基站在上电的情况下通过耦合线圈发射频率为125k的正弦波,ID卡的耦合线圈在125k的正弦波的激励下产生感应电动势,它为整个ID卡提供电源。ID卡通过调制电路根据其卡类的数据使ID卡的耦合线圈也发出正弦波,基站的耦合线圈接收到,根据它与125k波的不同来表示不同的数据。并将其通过DATA端以曼切斯特码的形式输出。

1.2、基站的接线端点

                  NC(未用)

                  ACC(+5v)

                 GND(接地)

               DATA(数据端)

             GND(电源管理)

       基站接线的端口

  说明:ACC接+5v的电源

        GND:接地端

        DATA:数据端,一般通过接外部中断以跳变的方式来接收曼切斯特码

        GND:电源管理。高电平:禁止对基站的供电;低电平:允许对基站的供电

 

2、 数据编码

数据编码是将数据表示成某种特殊的信号形式以便于数据的可靠传输。

2.1、 数字信号编码技术

对于传输数字信号来说,最普通且最容易的方法是用两个不同的电压值来表示两个二进制值。用无电压(或负电压)表示0,而正电压表示1。

常用的数字信号编码有不归零(NRZ)编码、曼彻斯特(Manchester)编码和差分曼彻斯特(Differential Manchester)编码。

2.1.1、NRZ编码

它的优点是:一位码元(一串脉冲)一个单位脉冲的亮度,称为全亮码。根据通信理论,每个脉冲亮度越大,信号的能量越大,抗干扰能力强,且脉冲亮度与信道带宽成反比,即全亮码占用信道较小的带宽编码效率高。

它的缺点是:当出现连续0或1时,难以分辨复位的起停点,会产生直流分量的积累,使信号失真。因此,过去大多数数据传输系统都不采用这种编码方式。近年来,随着技术的完善,NRZ编码已成为高速网络的主流技术。

2.1.2、曼彻斯特编码

在曼彻斯特编码中,用电压跳变的相位不同来区分1和0,即用正的电压跳变(0   1)表示0,用负的电压跳变(1   0)表示1。因此,这种编码也称为相应编码。由于跳变都发生在每一个码元的中间,接收端可以方便地利用它作为位同步时钟,因此,这种编码也称为自同步编码。

2.1.3、差分曼彻斯特

差分曼彻斯特编码是曼彻斯特编码的一种修改格式。其不同之处在于:每位的中间跳变只用于同步时钟信号;而0或1的取值判断是用位的起始处有无跳变来表示(若有跳变则为0,若无跳变则为1)。这种编码的特点是每一位均用不同电平的两个半位来表示,因而始终能保持直流的平衡。这种编码也是一种自同步编码。

3、RFID的数据处理

3.1、ID卡内的数据存储结构

下图是ID卡内存储空间的数据结构:

请注意:图中的一个数据表示的是一个位bite,即;图中共有8个字节

9个‘1’作为开头; 紧接着是10组数据: 4个有效数据位(Dxx ) 和一个行偶校验位(Px); 其后是4个列偶校验位的数据(PC0—PC3);最后以0结束。

3.2、基站将ID卡内数据转化为曼切斯特码输出

基站接收处理ID卡的数据后以曼切斯特码的形式通过DATA端输出,即将卡类的64位数据转化为了128位的曼切斯特码。

将ID卡内数据转化为曼切斯特码原理如图:

                                     

3.3、MCU从基站DATA端接收曼切斯特码

采集曼码如图:

 

 

 

 

 

 

二 、RFID读卡程序设计

1、RFID读卡程序原理流程

(1)将正确接收的128位曼码存于16个字节的数组中。(2)找到9个“1  0 ”的标志头。(3) 将128位转化为ID卡内原始的 除去9个“1”的55位数据形式,并暂存于16字节的数组中。 (4)对55位数据 先进行 列偶校验。 (5) 再进行 行偶校验 ,每校验正确一组(4个有效数据位 和 1个行偶校验位) 就将 4位有效数据 放于我们一个特定的5字节有效数组中。

2、代码如下:

说明:以下程序是读取基站DATA端数据,并加以校验正确后,将卡内正确数据存放于effectdata[5]中,而没有直接给出main函数,故可根据需要编写main调用effectdata[5](内存有正确的卡内数据)。

/////////////////////////////////////////////////////////////////////////////////////////

                                 文件名:IC_Read.h

/////////////////////////////////////////////////////////////////////////////////////////

#ifndef _IC_Read_h

#define _IC_Read_h

 

typedef unsigned char uint8 ;

 

//宏定义

#define RFID_DATA  P3_2       //外部中断口 接收数据

#define OpenRFID   P3_7 = 0   //打开RFID电源

#define OffRFID    P3_7 = 1   //关闭RFID电源

 

/******变量申明********/

extern uint8 InitRFID   ; // 0: 未初始化RFID模块   1: 已经初始化RFID模块

extern uint8 RFIDdataOk ; // 0: RFID接收数据失败   1: RFID成功接收数据

 

extern uint8 temp_buf[16]  ;

extern uint8 effectdata[5] ;

extern uint8 count         ;

extern uint8 t_count       ;

 

 

//函数申明

void IC_Read() ;

void Data_reveice() ;

void Lmove_bite() ;

uint8 find_head() ;

uint8 Data_L_check() ;

uint8 Data_R_check() ;

uint8 Data_Sever() ;

void Get_EffectData(uint8 edata) ;

 

#endif

/////////////////////////////////////////////////////////////////////////////////////////

                                 文件名:IC_Read.C

/////////////////////////////////////////////////////////////////////////////////////////

#include"at89x52.h"

#include"Timer.h"

#include"EX0.h"

#include"IC_Read.h"

#include"ES.h"

 

/******变量申明*********/

uint8 tcount        ;

uint8 count         ;

uint8 t_count       ;

uint8 temp          ;

uint8 temp_buf[16]  ;

uint8 effectdata[5] ;

 

uint8 RFIDdataOk    ; // 0: RFID接收数据失败   1: RFID成功接收数据

uint8 InitRFID      ; // 0: 未初始化RFID模块   1: 已经初始化RFID模块

 

/*********************************************

函数名:IC_Read

功能:  初始化RFID模块

参数:  无

*********************************************/

void IC_Read()

{  

         OpenRFID       ;  //开RFID

 

         count = 0 ;

        

         Init_RFIDEX0() ;  //开外部中断0 处理RFID中断

}

 

/*********************************************

函数名:EX0_Serve

功能:  外部中断0 初始化定时器1 定时128us

参数:  无

*********************************************/

void EX0_Serve() interrupt 0    //外部中断0

{

         Init_Timer1() ;             //初始化定时器1

         tcount = 0 ;         

}

 

/*********************************************

函数名:Timer1_Serve

功能:  定时器1中断

参数:  无

*********************************************/

void Timer1_Serve() interrupt 3  //定时1中断

{

         Data_reveice() ;

 

         tcount ++ ;

         if( tcount == 5 )

         {

                   InitRFID = 0   ;     //允许RFID重新初始化

                 RFIDdataOk = 0 ;     //允许RFID重新接收数据

         }

 

         TH1  = 0xfe ;                // 再定时 128X2=256us

         TL1  = 0x95 ;

}

 

/*********************************************

函数名:Data_reveice

功能:  定时器1中断接收RFID数据

参数:  无

*********************************************/

/*void deplay(uint8 time)

{

         uint8 t;

         while(time--)

         {

                   while(t--);

         }

}*/

 

 

void Data_reveice()

{P2=0x00;

         if(RFID_DATA==1)

         {

                   temp_buf[count/8] = (temp_buf[count/8]|(0x01<<(count%8)) ) ;

         }

 

          if(RFID_DATA==0)

          {

                   temp_buf[count/8] = (temp_buf[count/8]&(~(0x01<<(count%8))) ) ;

          }

        

         count ++ ;

         if(count==128)                           //0x80)

         {

                   count=0 ;

            

                   TR1=0;                       //TCON = ( TCON & 0xbf ) ; //TR1= 0  关定时器1

                EA=0;                   //IE = ( IE & 0x7f ) ;     //EA = 0  关外部中断0

                  

                   OffRFID ;                //关RFID

 

                   if( Data_Sever() )       //RFID数据处理成功 等待usb发送

                   {

                            RFIDdataOk = 1 ;     //禁止RFID接收数据                           

             }

                   else                     //RFID数据处理失败

                   {

                   //      P3_4=0;///////////////////////////////////////////////////////////////////////////////////

                   //      deplay(0x1f);

                   //      P3_4=1;

                            InitRFID = 0   ;     //允许RFID重新初始化

                          RFIDdataOk = 0 ;     //允许RFID重新接收数据

                 }

         }

         P2=0xff;

}

 

/*********************************************

函数名:Lmove_bite

功能:  128位左移一位。

参数:  无

*********************************************/

void Lmove_bite()

{       

         uint8 tempData0=0 ;

         for(temp=0 ; temp<0x10 ; temp++ )         //循环16次

         {

                   if( temp == 0 )

                   { tempData0 = ( (temp_buf[0]&0x01) <<7 ) ;} //保存数组0 的1位

 

                   if( temp == 0x0f )

                   { temp_buf[temp] =( (temp_buf[temp]>>1) | tempData0 ) ; }

                   else

                   {

                            temp_buf[temp] = ( (temp_buf[temp]>>1) |  ( (temp_buf[temp+1]&0x01) <<7 ) ) ;

                   }

         }

 

}

 

/*******************************************

函数名:find_head

功能:  循环移位 查找128位数据的9个1 :

             1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0

参数:       无

*********************************************/

uint8 find_head()

{

         for(count=0;count<128;count++)

         {

                   if( (temp_buf[0]==0x55) && (temp_buf[1]==0x55) && ((temp_buf[2]&0x03)==0x01) )

                   {return 1;}

                   else

                   {Lmove_bite();}

         }

         return 0 ;

}

 

/*******************************************

函数名:get_data

功能:  将128位 除9个1 0 的位转化为55位

参数:  无

********************************************/

void get_data()

{

         for( count=0 ,t_count=0 ; count <= 126 ; )//0x6c ;  )

         {

                   if(( temp_buf[((count+18)/8)]&(0x01<<((count+18)%8)))>\         

                   ( temp_buf[((count+19)/8)]&(0x01<<((count+19)%8))))                 //1

                   { temp_buf[t_count/8] = ( temp_buf[t_count/8] | ( 0x01 << (t_count%8) ) ) ; }

 

                   if(( temp_buf[((count+18)/8)]&(0x01<<((count+18)%8)))<\        

                   ( temp_buf[((count+19)/8)]&(0x01<<((count+19)%8))))                  //0

                   { temp_buf[t_count/8] = ( temp_buf[t_count/8] & ( ~ ( 0x01 << (t_count%8) ) ) ) ; }

 

                   t_count++;

                   count=count+2;

         }

}

 

/*********************************************

函数名:Data_L_check

功能: 列校验

返回值: 列校验成功返回1   列校验失败返回0

********************************************/

uint8 Data_L_check()

{

         for(count=0 ; count < 0x04 ; count++)

         {

                   temp = 0 ;

                   t_count = count ;

    for(  ; t_count <= 53 ; )//0x37 ; )

                   {       

                            if( ( temp_buf[(t_count/8)] & (0x01<<(t_count%8)) ) )//>> (t_count%8) )

                            {

                                     temp ++ ;

                            }

                            t_count = t_count + 5 ;

                   }

 

                   if((temp%2)!= 0)

                   {

                           return 0 ;  //列校验失败

                   }

         }

         return 1 ;

}

 

/*********************************************

函数名:Data_R_check

功能:  行校验  [7]

参数:  行校验成功返回1   行校验失败返回0

********************************************/

uint8  Data_R_check()

{

         uint8 t_buf[5] ;

         count=0 ;

 

         for(t_count=0 ; t_count<= 45 ; )//0x32 ; )

         {

                   t_buf[0] = ( ( temp_buf[(t_count/8)]     & (0x01<<(t_count%8))     ) >> (t_count%8)     ) ;

                   t_buf[1] = ( ( temp_buf[((t_count+1)/8)] & (0x01<<((t_count+1)%8)) ) >> ((t_count+1)%8) ) ;

                   t_buf[2] = ( ( temp_buf[((t_count+2)/8)] & (0x01<<((t_count+2)%8)) ) >> ((t_count+2)%8) ) ;

                   t_buf[3] = ( ( temp_buf[((t_count+3)/8)] & (0x01<<((t_count+3)%8)) ) >> ((t_count+3)%8) ) ;

                   t_buf[4] = ( ( temp_buf[((t_count+4)/8)] & (0x01<<((t_count+4)%8)) ) >> ((t_count+4)%8) ) ;

                  

 

                   if( (( t_buf[0]+t_buf[1]+t_buf[2]+t_buf[3]+t_buf[4] )%2) == 0)

                   {t_count = t_count + 5 ;}

                   else

                   {return 0 ;}    //行校验失败               

 

                   for(temp=0 ; temp<0x04 ; temp++ )

                   {

                            Get_EffectData( t_buf[temp] ) ;

                            count ++ ;

                   }

         }

         return 1 ;

}

 

/*********************************************

函数名:Get_EffectData

功能:  将一位数据依次放入数组effectdata【5】

参数:  edata 要放入数组的数据

*********************************************/

void Get_EffectData(uint8 edata)

{

         switch(edata)

         {

                   case 1:

                   effectdata[count/8] = (effectdata[count/8]|(0x01<<(count%8)) ) ;

                            break ;       

                   case 0:

                   effectdata[count/8] = (effectdata[count/8]&(~(0x01<<(count%8))) ) ;

                            break ;

         }

}

/*********************************************

函数名:Data_Sever

功能:  处理RFID数据

返回值:0 处理是失败  1 处理成功  

*********************************************/

uint8 Data_Sever()

{

         if(find_head() == 0 )         //寻找128位中 9个1 0  的曼切斯特码的头

         { return 0 ; }

 

         get_data() ;                  //将128位转化为除去 9个1 0 的55位       

 

         if(Data_L_check() == 0 )       //列校验

         { return 0 ; }

 

         if(Data_R_check() == 0 )          //行校验  如果成功将其放入特定的有效数组

         { return 0 ; }                          

 

         return 1 ;

}

/////////////////////////////////////////////////////////////////////////////////////////

                            文件名:Timer.h

/////////////////////////////////////////////////////////////////////////////////////////

#ifndef _Timer_h

#define _Timer_h

 

/*********************************************

函数名:Init_Timer1

功能:设定定时器1 定时128us

参数:无

*********************************************/

void Init_Timer1() ;

 

 

 

#endif

 

/////////////////////////////////////////////////////////////////////////////////////////

                            文件名:Timer.c

/////////////////////////////////////////////////////////////////////////////////////////

#include"at89x52.h"

 

/*********************************************

函数名:Init_Timer1

功能:  设定定时器1 定时128us

参数:  无

*********************************************/

void Init_Timer1()

{

         TH1  = 0xff ;//fe                //定时 128us

         TL1  = 0xa0 ;//fe

 

         TMOD = 0x10 ;                     //设置定时器1

         //TCON = ( TCON | 0x40 ) ;     //启动定时器1

         TCON =0x41 ;

         IE = 0x89;

         //IE = ( IE | 0x08 ) ;         //ET1= 1;  在 IE中 开 定时器1中断 ET1       

}

 

/////////////////////////////////////////////////////////////////////////////////////////

                            文件名:ES.h

/////////////////////////////////////////////////////////////////////////////////////////

#include"at89x52.h"

#ifndef _EX0_h

#define _EX0_h

 

/*********************************************

函数名:Init_EX0

功能:  启动外部中断0 为跳变中断

参数:  无

*********************************************/

void Init_RFIDEX0() ;

 

#endif

 

/////////////////////////////////////////////////////////////////////////////////////////

                            文件名:ES.c

/////////////////////////////////////////////////////////////////////////////////////////

/*********************************************

函数名:Init_RFIDEX0

功能:  启动外部中断0 为跳变中断

参数:  无

*********************************************/

void Init_RFIDEX0()

{

         TCON = 0x01 ;    //IT0 = 0x01 ;      设置外部中断触发方式:跳变触发 同时 关定时器1

 

         IE   = 0x81 ;    //EA  = 0x01 ;      开总中断 和 外部中断0

                          //EX0 = 0x01 ;

        

//      IP   = 0x01 ;    //PX0 = 0x01 ;      设置优先级:外部中断高

}
PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户193181 2009-4-2 23:24

你好,我想问一下什么叫行偶校验位和列偶校验位?

用户98132 2008-1-15 09:56

请问你的晶振选择多少呢?

用户741296 2007-12-24 20:11

不错。

好东东!

学习!

相关推荐阅读
用户115270 2008-10-20 20:52
ARM7控制液晶显示程序
//////////////////////////////////////////////////////////////////////////////////////  文件名 :LCDscre...
用户115270 2008-10-14 09:17
ARM7驱动步进电机的程序
/////////////////////////////////////////////////////////////////////////////////////文件名:motor.c////...
用户115270 2008-10-14 09:08
转载:C语言嵌入式系统编程修炼之道
C语言嵌入式系统编程修炼之道 C语言嵌入式系统编程修炼之道——背景篇... 1C语言嵌入式系统编程修炼之道——软件架构篇... 41.模块划分...42.多任务还是单任务...53.单任务程序典型架构...
用户115270 2008-05-04 10:23
大秦
凡我大秦大军铁骑能到达之处,皆必须予以征讨,毫不例外;凡大秦大军所到之处结为我大秦国土,其子民也皆为我大秦子民,也毫不例外。...
用户115270 2008-04-22 19:36
USB传输协议分析
USB传输协议分析关键字: 一 、数据格式【包】总体的格式如下: 同步序列【SYNC】包ID【PID】包特定信息CRC校验位包结束标志【EOP】                        信息包1...
EE直播间
更多
我要评论
3
4
关闭 站长推荐上一条 /3 下一条