⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m500auc.c

📁 51单片机进行mifare1射频卡开发
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////
char M500PcdMfOutSelect(unsigned char type)   /* TYPE为MFOUT输出的信号是什么类型 */
{
    WriteIO(RegMfOutSelect,type&0x7);   /* MFOUTSELECT寄存器(26H)=TYPE--低三位有效 */
    return MI_OK;
}

///////////////////////////////////////////////////////////////////////
// Request Command defined in ISO14443(MIFARE)
// Request,Anticoll,Select,return CardType(2 bytes)+CardSerialNo(4 bytes)
// 寻卡,防冲突,选择卡    返回卡类型(2 bytes)+ 卡系列号(4 bytes)
///////////////////////////////////////////////////////////////////////
char M500PiccCommonRequest(unsigned char req_code,unsigned char *atq)
{ /* ATQ=ANSWER TO REQUEST:响应信息,两个字节  */
    char idata status = MI_OK;

    M500PcdSetTmo(3);                      /* 计数器工作于模式3 */
    WriteIO(RegChannelRedundancy,0x03);    /* 通道冗余寄存器置3--奇校验,每个字节后附加一个校验位,无CRC校验 */
    ClearBitMask(RegControl,0x08);         /* 清加密算法位(09H) */
    WriteIO(RegBitFraming,0x07);           /* 最后三位为111,表示最后一字节须传送的位数为1(0FH) */
    SetBitMask(RegTxControl,0x03);         /* TX脚发送被数据调制好的能量载波信号(11H) */

    ResetInfo(MInfo);                      /* 信息接口 */
    SerBuffer[0] = req_code;               /* REQ_CODE=26H:REQUESTALL,  REQ_CODE=52H:REQUESTIDLE, */
    MInfo.nBytesToSend = 1;
     /* 上面是REQUEST指令相关信息 */
    status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo);    /* 执行TRANSCEIVE指令(寻卡--REQUEST)  */

    if (status)                            /* 返回标志为1  */
    {
        *atq = 0;                          /* 则响应值置0 */
    }
    else                                   /* 返回标志为0--成功了一半  */
    {
        if (MInfo.nBitsReceived != 16)     /* 如果收到的比特数不是16,则命令执行失败 */
        {
            *atq = 0;                      /* 则响应值置0 */
            status = MI_BITCOUNTERR;       /* 置状态寄存器为比特计数器错 */
        }
        else
        {
            status = MI_OK;                /* 是16,命令执行成功 */
            memcpy(atq,SerBuffer,2);       /* 从单片机数据缓冲区中读取响应信号(ATQ) */
        }
    }
    return status;                         /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////
// Cascaded Anti-Collision Command defined in ISO14443(MIFARE)
 /* 防冲突 读卡的系列号 MLastSelectedSnr四位的序列号 */
///////////////////////////////////////////////////////////////////
char M500PiccCascAnticoll (unsigned char bcnt,unsigned char *snr)
{    /* BCNT=0--32,比特计数器;SNR=序列号存储缓冲区4个字节; */
    char idata status = MI_OK;
    char idata snr_in[4];
    char idata nbytes = 0;
    char idata nbits = 0;
    char idata complete = 0;
    char idata i        = 0;
    char idata byteOffset = 0;
    unsigned char dummyShift1;
    unsigned char dummyShift2;

    M500PcdSetTmo(106);                    /* 初始化计时器--方式106 */
    memcpy(snr_in,snr,4);                  /* 序列号复制 */

    WriteIO(RegDecoderControl,0x28);       /* 任何在比特碰撞出现之后接收到的信号位进被屏蔽为0,大大简化ISO14443A标准 */
    ClearBitMask(RegControl,0x08);         /* 清加密算法位(09H) */
    complete = 0;
    while (!complete && (status == MI_OK) )   /* 如果这两个条件都成立则在此循环 */
    {
        ResetInfo(MInfo);
        WriteIO(RegChannelRedundancy,0x03);   /* 通道冗余寄存器置3--奇校验,每个字节后附加一个校验位,无CRC校验 */
        nbits = bcnt % 8;                     /* NBIT=BCNT除以8的余数 */
        if(nbits)                             /* 如果不为0 */
        {
            WriteIO(RegBitFraming,nbits << 4 | nbits);    /* 如果不为0 */
            nbytes = bcnt / 8 + 1;         /* NBYTES为收到的序列号字节数,要加一 */
            if (nbits == 7)
            {
                MInfo.cmd = PICC_ANTICOLL1;
                WriteIO(RegBitFraming,nbits);   /*  */
            }
        }
        else          /* 余数为0 */
        {
            nbytes = bcnt / 8;       /* NBYTES为收到的序列号字节数 */
        }
        SerBuffer[0] = 0x93;         /* 标准选卡命令 */
        SerBuffer[1] = 0x20 + ((bcnt/8) << 4) + nbits;

        for (i = 0; i < nbytes; i++)
        {
            SerBuffer[i + 2] = snr_in[i];       /* 序列号输入接口 */
        }
        MInfo.nBytesToSend   = 2 + nbytes;      /* 输入字节个数 */

        status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo);
        if (nbits == 7)
        {                                                            /* 反碰撞处理过程? */
            dummyShift1 = 0x00;
            for (i = 0; i < MInfo.nBytesReceived; i++)
            {
                dummyShift2 = SerBuffer[i];
                SerBuffer[i] = (dummyShift1 >> (i+1)) | (SerBuffer[i] << (7-i));
                dummyShift1 = dummyShift2;
            }
            MInfo.nBitsReceived -= MInfo.nBytesReceived;
            if ( MInfo.collPos ) MInfo.collPos += 7 - (MInfo.collPos + 6) / 9;
        }
        if ( status == MI_OK || status == MI_COLLERR)
        {
            if ( MInfo.nBitsReceived != (40 - bcnt) )
            {
                status = MI_BITCOUNTERR;
            }
            else
            {
                byteOffset = 0;
                if( nbits != 0 )
                {
                    snr_in[nbytes - 1] = snr_in[nbytes - 1] | SerBuffer[0];
                    byteOffset = 1;
                }

                for ( i =0; i < (4 - nbytes); i++)
                {
                    snr_in[nbytes + i] = SerBuffer[i + byteOffset];
                }

                if (status != MI_COLLERR )
                {
                    dummyShift2 = snr_in[0] ^ snr_in[1] ^ snr_in[2] ^ snr_in[3];
                    dummyShift1 = SerBuffer[MInfo.nBytesReceived - 1];
                    if (dummyShift2 != dummyShift1)
                    {
                        status = MI_SERNRERR;
                    }
                    else
                    {
                        complete = 1;
                    }
                }
                else
                {
                    bcnt = bcnt + MInfo.collPos - nbits;
                    status = MI_OK;
                }
            }
        }
    }
    if (status == MI_OK)                      /* 如果状态标志成功 */
    {
        memcpy(snr,snr_in,4);                 /* 保存序列号 */
    }
    else
    {
        memcpy(snr,"0000",4);                 /* 不成功,则返回0000 */
    }
    ClearBitMask(RegDecoderControl,0x20);      /* 清掉反碰撞位 */

    return status;                             /* 返回状态值 */
}

//////////////////////////////////////////////////////////////////
// Cascaded Select command defined in ISO14443(MIFARE)
 /* 选择卡,确定序列号是否大于4字节 */
//////////////////////////////////////////////////////////////////
char M500PiccCascSelect(unsigned char *snr,unsigned char *sak)
{                      /* snr为序列号首址, sak为一字节选卡回应值*/
    char idata status = MI_OK;

    M500PcdSetTmo(106);                    /* 计时器初始化 */

    WriteIO(RegChannelRedundancy,0x0F);    /* 通道冗余寄存器置f--16bit crc校验,确定数据帧最后两个字节为crc字节,奇校验,每个字节后附加一个校验位 */
    ClearBitMask(RegControl,0x08);         /* 清加密算法位(09H) */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* 送rc500FIFO的相关信息,与命令函数m500pcdcmd()配合 */
    ResetInfo(MInfo);                      /* 给rc500的相关信息,与指令相配合 */
    SerBuffer[0] = 0x93;                   /* 给rc500的相关信息,写入指令(选卡)数据 */
    SerBuffer[1] = 0x70;                   /* 给rc500的相关信息,写入数据 */
    memcpy(SerBuffer + 2,snr,4);    /* 将原指针snr对应的序列号拷贝到发送缓冲区serbuffer中去 */
    SerBuffer[6] = SerBuffer[2] ^ SerBuffer[3] ^ SerBuffer[4] ^ SerBuffer[5];  /* 序号中四字节按位异或得到crc校验字节 */
    MInfo.nBytesToSend   = 7;       /* 给rc500的相关信息,与指令相配合,须发送的字节数 */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo);     /* 执行命令函数m500pcdcmd(),返回STATUS */

    *sak = 0;                    /* sak选卡回应值先置0 */
    if (status == MI_OK)         /* 返回值为执行成功标志MI_OK */
    {
        if (MInfo.nBitsReceived != 8)  /* 如果接收到的不是一个字节 */
        {
            status = MI_BITCOUNTERR;   /* 则置标志位为MI_BITCOUNTERR */
        }
        else                           /* 如果接收到的是一个字节 */
        {
	        *sak = SerBuffer[0];   /* 则将该值存于SAK中 */
        }
    }
    return status;                     /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Key loading into the MF RC500's EEPROM
// 将RC500的EEROM中的密钥载入密钥缓冲区,校验卡密码(E2)
///////////////////////////////////////////////////////////////////////
char M500PiccAuthE2( unsigned char auth_mode,unsigned char *snr,
                     unsigned char keynr,unsigned char block)
    /* 入口参数:AUTH_MODE:A/B卡型号,SNR:卡序列号,KEYNR:密钥所在扇区数,BLOCK:密钥所在数据块*/
{
    char idata status = MI_OK;
    unsigned int e2addr = 0x80 + keynr * 0x18;    /* 得出密钥在EEROM中的位置 */
    //unsigned char *e2addrbuf = (unsigned char*)&e2addr;
    unsigned char *e2addrbuf;

    e2addrbuf = (unsigned char *)&e2addr;
    if (auth_mode == PICC_AUTHENT1B)      /* 如果是B类卡 */
    {
        e2addr += 12;       /* 密钥地址加12 */
    }
    FlushFIFO();
    ResetInfo(MInfo);

    memcpy(SerBuffer,e2addrbuf,2);  /* 从E2ADDRBUF中取出存密钥的EEROM地址(两个字节) */
    SerBuffer[2] = SerBuffer[0];
    SerBuffer[0] = SerBuffer[1];
    SerBuffer[1] = SerBuffer[2];
    MInfo.nBytesToSend   = 2;
    if ((status=M500PcdCmd(PCD_LOADKEYE2,SerBuffer,&MInfo)) == MI_OK)
    {  /* 下载密钥成功  */
        status = M500PiccAuthState(auth_mode,snr,block);
    }  /* 三轮认证 */
    return status;     /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Authentication key coding
 /* 将密钥换成标准密钥形式 */
///////////////////////////////////////////////////////////////////////
char M500HostCodeKey(  unsigned char *uncoded, unsigned char *coded)
{
    char idata status = MI_OK;
    unsigned char idata cnt = 0;
    unsigned char idata ln  = 0;
    unsigned char idata hn  = 0;
    for (cnt = 0; cnt < 6; cnt++)   /* 密钥由6字节转成12字节 */
    {
        ln = uncoded[cnt] & 0x0F;   /* 密钥一字节的低四位 */
        hn = uncoded[cnt] >> 4;     /* 密钥一字节的高四位 */
        coded[cnt * 2 + 1] = (~ln << 4) | ln;
        coded[cnt * 2 ] = (~hn << 4) | hn;
    }
    return MI_OK;
}

///////////////////////////////////////////////////////////////////
// Authentication with direct key loading from the uC
             /*直接校验从单片机载入的密码,针对卡中的某一块数据来说(16块,每块64字节) */
//////////////////////////////////////////////////////////////////
char M500PiccAuthKey(  unsigned char auth_mode,
                       unsigned char *snr,
                       unsigned char *keys,
                       unsigned char block)
{
    char idata status = MI_OK;
    //PcdSetTmo(2);
    FlushFIFO();
    ResetInfo(MInfo);
    memcpy(SerBuffer,keys,12);
    MInfo.nBytesToSend = 12;
    if ((status=M500PcdCmd(PCD_LOADKEY,SerBuffer,&MInfo)) == MI_OK)
    {   /* 直接从单片机载入密码到FIFO,然后再载入密钥缓冲区 */
        status = M500PiccAuthState(auth_mode,snr,block);
    }   /* 三轮认证 */
    return status;
}       /* 返回状态值 */

///////////////////////////////////////////////////////////////////////
  /* 三轮认证函数 */
///////////////////////////////////////////////////////////////////////
char M500PiccAuthState( unsigned char auth_mode,unsigned char *snr,unsigned char block)
{  /* 入口参数:AUTH_MODE:A/B卡型号,SNR:卡序列号,BLOCK:要访问所在数据块*/
    char idata status = MI_OK;
    unsigned char idata i = 0;

    status = ReadIO(RegErrorFlag);  /* 读RC500中的错误标志寄存器 */
    if (status != MI_OK)            /* 载入密钥不成功 */
    {
        if (status & 0x40)
        {
            status = MI_KEYERR;     /* 密钥出错标志 */
        }
        else
        {
            status = MI_AUTHERR;    /* 认证出错标志 */
        }
    }
    else                            /* 载入密钥成功 */
    {   /* 三轮认证开始 */

        SerBuffer[0] = auth_mode;
        SerBuffer[1] = block;
        memcpy(SerBuffer + 2,snr,4);
        ResetInfo(MInfo);
        MInfo.nBytesToSend = 6;
        /* 上面为认证命令1的入口参数:卡型,要访问的数据块,序列号,相关流动信息,要发送的字节数 */
        if ((status = M500PcdCmd(PCD_AUTHENT1,SerBuffer,&MInfo)) == MI_OK)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -