Chinaunix首页 | 论坛 | 博客
  • 博客访问: 391926
  • 博文数量: 80
  • 博客积分: 1982
  • 博客等级: 上尉
  • 技术积分: 1737
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-26 22:41
文章存档

2013年(9)

2012年(71)

分类: LINUX

2013-01-02 18:06:58

    14443 TypeA 密耦合射频卡标准广泛应用在门禁、身份识别和电子钱包等领域,而 RC522 作为 Philips 基站芯片产品系列的新成员,不仅兼容 14443A/MIFARF 标准,还具备低电压(3.3V)、低功耗、低成本、小尺寸等优点,适用于智能仪表和手持设备的数据采集和处理。RC522 对外提供多种标准的数字接口(如并行接口、SPI、I2C等),通过对芯片内部的 4 页 64 个寄存器进行读、写来控制
    RC522 芯片在使用前必须复位,除了在复位引脚 NRSTPD 输入从低电平至高电平的跳变沿外,还必须向 RC522 的命令寄存器 CommandReg 写人软复位命令代码 0x0F 进行软复位。
CommandReg: Starts and stops command execution.
MFRC522 Command Set:   
   
  
/* RC522 命令字 */
#define PCD_IDLE              0x00               //取消当前命令
#define PCD_AUTHENT           0x0E               //验证密钥
#define PCD_RECEIVE           0x08               //接收数据
#define PCD_TRANSMIT          0x04               //发送数据
#define PCD_TRANSCEIVE        0x0C               //发送并接收数据
#define PCD_RESETPHASE        0x0F               //复位
#define PCD_CALCCRC           0x03               //CRC计算


RC522 复位函数:
void PcdReset(void)
{
    SET_RC522RST;
    delay_ns(10);
    CLR_RC522RST;
    delay_ns(10);
    SET_RC522RST;
    delay_ns(10);
    WriteRawRC(CommandReg, PCD_RESETPHASE);    //复位命令

}
RC522 初始化函数:
void MFRC522_Init(void)
{
   
PcdReset();    //RC522复位
    PcdConfigISOType('A');    //协议配置为
ISO14443_A
}

char PcdConfigISOType(unsigned char type)
{   
    if (type == 'A')    //ISO14443_A
    {    
         ClearBitMask(Status2Reg, 0x08);  //清MFCrypto1On
        
WriteRawRC(ModeReg, 0x3D);       //CRC初始值0x6363
         /* Modulation signal from the internal analog part, default. */
         WriteRawRC(RxSelReg,0x86);
         WriteRawRC(RFCfgReg,0x7F);    //RxGain=48dB

         WriteRawRC(TReloadRegL, 30);  //定时器重装值          
         WriteRawRC(TReloadRegH, 0);
         WriteRawRC(TModeReg, 0x8D);   //
TAuto=1,及定时器预分频高4位
         WriteRawRC(TPrescalerReg, 0x3E);  //定时器预分频低8位

         WriteRawRC(TxAutoReg, 0x40);      //Force100ASK(必须要)
        
PcdAntennaOn();    //打开天线
    }   
    else
    {
         return MI_ERR;
    }
    return MI_OK;
}
    TAuto 位设置为 1,则定时器在数据发送结束时自动启动,如果 RxModeReg 寄存器中的 RxMultiple 位未被设置,则当接收到第一个数据位时,定时器停止。定时器的作用主要是防止通信过程中出错,而设置一个超时时间。上述设置的超时时间为 30 * 0xD3E * 6.78MHz = 15000us = 1.5ms。

    RC522 对卡的操作分成五个步骤:寻卡->防冲突->选卡->验证->读/写卡。
/******************************************************************
 *功    能:通过 RC522 和 ISO14443 卡通讯
 *参数说明:Command[IN]:RC522 命令字
 *          pInData[IN]:通过 RC522 发送到卡片的数据
 *          InLenByte[IN]:发送数据的字节长度
 *          pOutData[OUT]:接收到的卡片返回数据
 *          *pOutLenBit[OUT]:返回数据的位长度
******************************************************************/
char PcdComMF522(unsigned char Command, unsigned char *pInData,
                 unsigned char InLenByte, unsigned char *pOutData,
                 unsigned int *pOutLenBit)
{
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    char status;
    switch(Command)
    {
        case PCD_AUTHENT:
            irqEn   = 0x12;  //使能IdleIEn和ErrIEn
            waitFor = 0x10;  //等待IdleIRq
            break;
        case PCD_TRANSCEIVE:
           
/* 使能TxIEn、RxIEn、IdleIEn、LoAlertIEn、ErrIEn和TimerIEn */
            irqEn   = 0x77;
            waitFor = 0x30;  //等待IdleIRq和RxIRq
            break;
        default:
            break;
    }
    WriteRawRC(CommIEnReg, irqEn|0x80);  //
使能中断
    ClearBitMask(CommIrqReg, 0x80);      //清所有的中断标志
    WriteRawRC(CommandReg,PCD_IDLE);     /*必须要,结束先前的命令*/
    SetBitMask(FIFOLevelReg, 0x80);      //清FIFO
    for (i=0; i    {  
        WriteRawRC(FIFODataReg, pInData[i]);   
    }
    WriteRawRC(CommandReg, Command);    //写入命令
    if (Command == PCD_TRANSCEIVE)
    {   
        SetBitMask(BitFramingReg, 0x80);    //开始传输 
    }
    /* 操作M1卡最大等待时间25ms */
    i = 2000;        //主要针对“认证卡密”
    do
    {
        status = ReadRawRC(CommIrqReg);
        i--;
    }
    while ((i!=0) && !(status & 0x01) && !(status & waitFor));
    ClearBitMask(BitFramingReg, 0x80);
    if (i!=0)
    {
        if(!(ReadRawRC(ErrorReg) & 0x1B))    //判断是否出错
        {
            if(status & irqEn & 0x01)
            {  
                return MI_NOTAGERR;  
            }
            if(Command == PCD_TRANSCEIVE)
            {
                n = ReadRawRC(FIFOLevelReg);
                lastBits = ReadRawRC(ControlReg) & 0x07;
                if(lastBits)
                {  
                    *pOutLenBit = (n-1)*8 + lastBits;  
                }
                else
                {  
                    *pOutLenBit = n*8;  
                }
                if (n == 0)
                {  
                    n = 1;   
                }
                if (n > MAXRLEN)
                {  
                    n = MAXRLEN;  
                }
                for (i=0; i                {  
                    pOutData[i] = ReadRawRC(FIFODataReg);   
                }
            }   
        }       
        else
            return MI_ERR;  
    }
    else
    {  
        return MI_ERR;  
    }
   
    return MI_OK;
}
/******************************************************************
 *功    能:寻卡
 *参数说明: req_code[IN]:寻卡方式
 *                0x52 = 寻感应区内所有符合14443A标准的卡
 *                0x26 = 寻未进入休眠状态的卡
 *          pTagType[OUT]:卡片类型代码
 *                0x4400 = Mifare_UltraLight
 *                0x0400 = Mifare_One(S50)
 *                0x0200 = Mifare_One(S70)
 *                0x0800 = Mifare_Pro(X)
 *                0x4403 = Mifare_DESFire
 *返    回: 成功返回 MI_OK
******************************************************************/
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
    char ret; 
    unsigned int len;
    unsigned char buf[MAXRLEN];
    ClearBitMask(Status2Reg, 0x08);   
//清MFCrypto1On
    WriteRawRC(BitFramingReg, 0x07);
    buf[0] = req_code;
    ret = PcdComMF522(PCD_TRANSCEIVE, buf, 1, buf, &len);
    if ((ret == MI_OK) && (len == 0x10))
    {   
        *pTagType     = buf[0];
        *(pTagType+1) = buf[1];
    }
    else
    {  
        ret = MI_ERR;  
    }
    return ret ;
}
/******************************************************************
 *功    能:防冲突
 *参数说明: pSnr[OUT]:卡片序列号,4字节
 *返    回: 成功返回MI_OK
******************************************************************/
char PcdAnticoll(unsigned char *pSnr)
{
    char ret;
    unsigned char i,snr_check=0;
    unsigned int len;
    unsigned char buf[MAXRLEN];   
    ClearBitMask(Status2Reg, 0x08);   
//清MFCrypto1On
    WriteRawRC(BitFramingReg, 0x00);
    ClearBitMask(CollReg, 0x80);
    buf[0] = PICC_ANTICOLL1;
    buf[1] = 0x20;
    ret = PcdComMF522(PCD_TRANSCEIVE, buf, 2, buf, &len);
    if (ret == MI_OK)
    {
        for (i=0; i<4; i++)
        {  
            *(pSnr+i)  = buf[i];
            snr_check ^= buf[i];
        }
        if (snr_check != buf[i])
        {  
            ret = MI_ERR;   
        }
    }
    SetBitMask(CollReg, 0x80);
    return ret;
}
/******************************************************************
 *功    能:选定卡片
 *参数说明: pSnr[IN]:卡片序列号,4字节
 *返    回: 成功返回MI_OK
******************************************************************/
char PcdSelect(unsigned char *pSnr)
{
   
char ret;
    unsigned char i;
    unsigned int len;
    unsigned char buf[MAXRLEN]; 
    buf[0] = PICC_ANTICOLL1;
    buf[1] = 0x70;
    buf[6] = 0;
    for (i=0; i<4; i++)
    {
        buf[i+2] = *(pSnr+i);
        buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(buf, 7, &buf[7]);
    ClearBitMask(Status2Reg, 0x08);
    ret= PcdComMF522(PCD_TRANSCEIVE, buf, 9, buf, &len);
    if ((ret == MI_OK) && (len == 0x18))
       
return MI_OK; 
    else
       
return MI_ERR;   
}
/******************************************************************
 *功    能:验证卡片密码
 *参数说明: auth_mode[IN]: 密码验证模式
 *                 0x60 = 验证A密钥
 *                 0x61 = 验证B密钥
 *          addr[IN]:块地址
 *          pKey[IN]:密码
 *          pSnr[IN]:卡片序列号,4字节
 *返    回: 成功返回MI_OK
******************************************************************/      
char PcdAuthState(unsigned char auth_mode,unsigned char addr,
                  unsigned char *pKey,unsigned char *pSnr)
{
    char ret;
    unsigned int len;
    unsigned char buf[MAXRLEN];
    buf[0] = auth_mode;
    buf[1] = addr;
    memcpy(&buf[2], pKey, 6);
    memcpy(&buf[8], pSnr, 6);   
    ret = PcdComMF522(PCD_AUTHENT, buf, 12, buf, &len);
    if ((ret != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    {  
       
return MI_ERR;  
    }
    return
MI_OK;
}
   

    注意:只有正确验证卡密的情况下 MFCrypto1On 才会被置 1,并且用于后续的读写操作,这也说明成功验证卡密后所有的数据传输都是加密的。在“寻卡”和“选卡”过程中,该位应被软件清零。
/******************************************************************

 *功    能:读取M1卡一块数据
 *参数说明: addr[IN]:块地址
 *          pData[OUT]:读出的数据,16字节
 *返    回: 成功返回MI_OK
******************************************************************/
char PcdRead(unsigned char addr,unsigned char *pData)
{
    char ret;
    unsigned int len;
    unsigned char buf[MAXRLEN];
    buf[0] = PICC_READ;
    buf[1] = addr;
    CalulateCRC(buf, 2, &buf[2]);
    ret = PcdComMF522(PCD_TRANSCEIVE, buf, 4, buf, &len);
    if ((ret == MI_OK) && (len == 0x90))  //18个字节,其中有2个是CRC校验
    {   
        memcpy(pData, buf, 16);   
    }
    else
    {  
       
return MI_ERR;   
    }   
    return
MI_OK;
}  
/******************************************************************
 *功    能:写数据到M1卡一块
 *参数说明: addr[IN]:块地址
 *          pData[IN]:写入的数据,16字节
 *返    回: 成功返回MI_OK
******************************************************************/      
char PcdWrite(unsigned char addr,unsigned char *pData)
{
    char ret;
    unsigned int len;
    unsigned char buf[MAXRLEN];
    buf[0] = PICC_WRITE;
    buf[1] = addr;
    CalulateCRC(buf, 2, &buf[2]);
    ret = PcdComMF522(PCD_TRANSCEIVE, buf, 4, buf, &len);
    if ((ret != MI_OK) || (len != 4) || ((buf[0] & 0x0F) != 0x0A))
    {  
        ret = MI_ERR;  
    }       
    if (ret == MI_OK)
    {
        memcpy(buf, pData, 16);
        CalulateCRC(buf, 16, &buf[16]);
        ret = PcdComMF522(PCD_TRANSCEIVE, buf,18, buf, &len);
        if ((ret != MI_OK) || (len != 4) || ((buf[0] & 0x0F) != 0x0A))
        {  
            ret = MI_ERR;  
        }
    }
    return ret;
}

例子:门禁系统:读块4处16字节 如果前8个字符为“fourmily”则通过
   
  
    
  
相关资料下载:

       ——Be loyal to dream. Be brave to try!    linux_xpj@opencores.org
阅读(4280) | 评论(2) | 转发(2) |
给主人留下些什么吧!~~

skyfox_lai2013-01-06 09:59:33

skyfox_lai2013-01-06 09:59:20

请问能否弄成像酒店的那种门吗?或者弄成指纹的 更高级一点的呢?