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

📄 m500auc.c

📁 51单片机进行mifare1射频卡开发
💻 C
📖 第 1 页 / 共 5 页
字号:
            {
                lastBits = ReadIO(RegSecondaryStatus) & 0x07;    /* 取出最后三位 */
                if (lastBits)                                    /* 最后三位为1-7,不全有效 */
                    info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
                else                                             /* 最后三位为0,全有效 */
                    info->nBitsReceived += info->nBytesReceived * 8;
            }
        }
        else
        {
            info->collPos = 0x00;           /* 无碰撞 */
        }
    }
    MpIsrInfo = 0;
    MpIsrOut  = 0;
    return status;
}

///////////////////////////////////////////////////////////////////////
// 置RC500寄存器bit
///////////////////////////////////////////////////////////////////////
char SetBitMask(unsigned char reg,unsigned char mask)
{    /* 相应的寄存器(REG),相应的屏蔽位(MASK) */
    char idata tmp = 0x00;

    tmp = ReadIO(reg);
    WriteIO(reg,tmp | mask);              /* 写入 */
    return 0x00;
}

///////////////////////////////////////////////////////////////////////
// 清RC500寄存器bit
///////////////////////////////////////////////////////////////////////
char ClearBitMask(unsigned char reg,unsigned char mask)
{   /* 相应的寄存器(REG),相应的屏蔽位(MASK) */
    char idata tmp = 0x00;

    tmp = ReadIO(reg);
    WriteIO(reg,tmp & ~mask);             /* 写入 */
    return 0x00;
}

///////////////////////////////////////////////////////////////////////
   /* 清缓冲区标志,这样RC500的FIFO取就可供单片机或RC500状态机使用  */
///////////////////////////////////////////////////////////////////////
void FlushFIFO(void)
{
    SetBitMask(RegControl,0x01);  /* 控制寄存器地址:09H------置1(FIFOFLUSH=1) */
}

///////////////////////////////////////////////////////////////////////
// Value format operations for Mifare Standard card ICs
 /* 改变MIFARE1卡内部EEROM的内容(单调增加,单调减少,数据检验操作) */
///////////////////////////////////////////////////////////////////////
char M500PiccValue(unsigned char dd_mode,
                   unsigned char addr,
                   unsigned char *value,
                   unsigned char trans_addr)
{ /* VALUE:连续写入的四字节指针,TRANS_ADDR:指向的改变后的数据要存入的地址 */
    char status = MI_OK;                         /* SATUS:置初值 */
    /* DD_MODE:三种命令模式,ADDR:指向的要改变数据单元的地址 */
    M500PcdSetTmo(1);                            /* 初始化计时器--方式1 */
    ResetInfo(MInfo);                            /* Minfo=INFO */
    SerBuffer[0] = dd_mode;                      /* 93h,95h,97h三种命令模式 */
    SerBuffer[1] = addr;                         /* ADDR:指向的要改变数据单元的地址 */
    MInfo.nBytesToSend = 2;                      /* 要发送的字节数 */
    status = M500PcdCmd(PCD_TRANSCEIVE,
                       SerBuffer,
                       &MInfo);
     /* 执行先送后接指令后返回STATUS */
    if (status != MI_NOTAGERR)                   /* MI_NOTAGERR=没有卡在此场里  */
    {                                            /* 有卡在此场里 */
        if (MInfo.nBitsReceived != 4)            /* 收到的数据不是4比特 */
        {
            status = MI_BITCOUNTERR;             /* 置收到错误的比特数目标志位 */
        }
        else                                     /* 收到的数据是4比特 */
        {
            SerBuffer[0] &= 0x0f;                /* 取出低四位 */
            switch(SerBuffer[0])
            {
                case 0x00:
                    status = MI_NOTAUTHERR;      /* 0000=置收到错误的比特数目标志位 */
                    break;
                case 0x0a:                       /* 1010=置命令正确执行位 */
                    status = MI_OK;
                    break;
                case 0x01:                       /* 0001=置数据结构错误位 */
                    status = MI_VALERR;
                    break;
                default:
                    status = MI_CODEERR;         /* 收到NACK,发送的数据出错(CRC,PARITY) */
                    break;
            }
        }
    }

    if ( status == MI_OK)
    {    /* TRANSCEIVE命令执行成功 */
        M500PcdSetTmo(3);                       /* 初始化计时器--方式3 */
        ResetInfo(MInfo);                       /* Minfo=INFO */
        memcpy(SerBuffer,value,4);              /* 将缓冲区里放入要改变的数据 */
        MInfo.nBytesToSend   = 4;               /* 要发送的字节数4 */
        status = M500PcdCmd(PCD_TRANSCEIVE,     /* 执行先送后接指令后返回STATUS */
                            SerBuffer,
                            &MInfo);

        if (status == MI_OK)                    /* 上条TRANSCEIVE命令执行成功 */
        {
            if (MInfo.nBitsReceived != 4)       /* 收到的数据不是4比特 */
            {
                status = MI_BITCOUNTERR;        /* MI_NOTAGERR=没有卡在此场里  */
            }
            else                                /* 收到的数据是4比特 */
            {
                SerBuffer[0] &= 0x0f;           /* 取出低四位 */
                switch(SerBuffer[0])
                {
                    case 0x00:                  /* 0000=置收到错误的比特数目标志位 */
                        status = MI_NOTAUTHERR;
                        break;
                    case 0x01:                  /* 0001=置数据结构错误位 */
                        status = MI_VALERR;
                        break;
                    default:                    /* 收到NACK,发送的数据出错(CRC,PARITY) */
                        status = MI_CODEERR;
                        break;
                }
            }
        }
        else                                    /* 上条TRANSCEIVE命令执行不成功 */
        {
            if (status == MI_NOTAGERR )         /* MI_NOTAGERR=没有卡在此场里  */
                status = MI_OK;                 /* 恢复初始值 */
        }
    }
    if (status == MI_OK)                        /*  */
    {
        ResetInfo(MInfo);                       /* Minfo=INFO */
        SerBuffer[0] = PICC_TRANSFER;           /* 这才是真正的改变卡内存的指令(下载) */
        SerBuffer[1] = trans_addr;
        MInfo.nBytesToSend   = 2;
        status = M500PcdCmd(PCD_TRANSCEIVE,     /* 执行传送指令,下载到卡的EEROM */
                            SerBuffer,
                            &MInfo);            /* TRANSCEIVE指令的出口参数,一部分状态信息 */
        if (status != MI_NOTAGERR)
        {                                       /* 有卡在此场里 */
            if (MInfo.nBitsReceived != 4)
            {
                status = MI_BITCOUNTERR;        /* 收到的数据不是4比特 */
            }
            else                                /* 收到的数据是4比特 */
            {
                SerBuffer[0] &= 0x0f;           /* 取出低四位 */
                switch(SerBuffer[0])
                {
                    case 0x00:                  /* 0000=置收到错误的比特数目标志位 */
                        status = MI_NOTAUTHERR;
                        break;
                    case 0x0a:
                        status = MI_OK;          /* 1010=置命令正确执行位 */
                        break;
                    case 0x01:                   /* 0001=置数据结构错误位 */
                        status = MI_VALERR;
                        break;
                    default:                     /* 收到NACK,发送的数据出错(CRC,PARITY) */
                        status = MI_CODEERR;
                        break;
                }
            }
        }
    }
    return status;                               /* 这个SWITCH作为整个函数的反馈值 */
}

///////////////////////////////////////////////////////////////////////
// Set card in HALT-state
 /* 终止卡的操作 */
///////////////////////////////////////////////////////////////////////
char M500PiccHalt(void)
{
    char idata status = MI_CODEERR;   /* 将STATUS初值定为数据错  */

    // ************* Cmd Sequence **********************************
    ResetInfo(MInfo);                 /* Minfo=INFO */
    SerBuffer[0] = PICC_HALT ;        /* 执行IDLE指令,关闭卡 */
    SerBuffer[1] = 0x00;              /* 同上 */
    MInfo.nBytesToSend = 2;           /* 同上 */
    status = M500PcdCmd(PCD_TRANSCEIVE,   /* 调用命令执行程序 */
                       SerBuffer,
                       &MInfo);
    if (status)
    {
        // timeout error ==> no NAK received ==> OK
        if (status == MI_NOTAGERR || status == MI_ACCESSTIMEOUT)
        {                            /* 无卡响应,命令执行成功 */
            status = MI_OK;
        }
    }
    //reset command register - no response from tagit
    WriteIO(RegCommand,PCD_IDLE);    /* 有卡响应,命令执行不成功 */
    return status;                   /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Reset the MF RC500
 /* 重启RC500,开始新一轮寻卡 */
///////////////////////////////////////////////////////////////////////
char M500PcdReset(void)
{
    char idata status = MI_OK;       /* 状态初值 */
    unsigned int idata timecnt=0;    /* 局部计数器置初值 */

    RC500RST = 0;                    /* 重启时序 */
    delay_1ms(25);
    RC500RST = 1;
    delay_50us(200);
    RC500RST = 0;
    delay_50us(50);
    timecnt=1000;
    while ((ReadIO(RegCommand) & 0x3F) && timecnt--);       /* 循环查询? */
    if(!timecnt)
    {
        status = MI_RESETERR;        /* timecnt=0,则置status为重起失败标志 */
    }
    if (status == MI_OK)             /* 如果在timecnt没变成0时status就被置命令执行成功 */
    {
        //WriteIO(RegPage,0x80);
        if (ReadIO(RegCommand) != 0x00)    /* 如果此时regcommand不为0 */
        {
            status = MI_INTERFACEERR;      /* 则置status为接口出错(实质上是rc500没有响应单片机或是上位机) */
        }
    }
    return status;                         /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Configures the MF RC500
 /* 新一轮认卡后的寄存器配置过程 */
///////////////////////////////////////////////////////////////////////
char M500PcdConfig(void)
{
    char idata status;

    if ((status = M500PcdReset()) == MI_OK)      /* 如果返回的状态值是重启成功 */
    {
        WriteIO(RegClockQControl,0x00);          /* q通道时钟控制寄存器置0,自动校准时钟偏差 */
        WriteIO(RegClockQControl,0x40);          /* q通道时钟控制寄存器置40,不校准时钟偏差  ?   */
        delay_50us(2);                           /* 延时100us */
        ClearBitMask(RegClockQControl,0x40);     /* q通道时钟控制寄存器又置0,自动校准时钟偏差(1BH) */
        WriteIO(RegBitPhase,0xAD);               /* 选择发送与接收之间的时钟相位差,默认值:oxad -----important(1FH) */
        WriteIO(RegRxThreshold,0xFF);            /* 选择RX脚输入信号的门限电压值0XFF(1CH) */
        WriteIO(RegRxControl2,0x01);             /* 接收控制--使用内部解码器,用Q时钟,接收器时常处于激活态(1EH) */
        WriteIO(RegFIFOLevel,0x1A);              /* FIFO饱和度水平=1A(29H) */
        WriteIO(RegTimerControl,0x02);           /* 发送一完成自动开始计数(2BH) */
        WriteIO(RegIRqPinConfig,0x03);           /* IRQ脚配置:输出电平与IRQ标志相反,工作于标准CMOS输出模式(2DH) */
        M500PcdRfReset(1);                       /* 调用射频重启函数 */
    }
    return status;                               /* 返回状态值 */
}

///////////////////////////////////////////////////////////////
// Key loading into the MF RC500's EEPROM
 /* 将主密钥送入RC500的EEROM */
///////////////////////////////////////////////////////////////
char M500PcdLoadKeyE2(unsigned char key_type,
                       unsigned char sector,     /* 存放密钥的EEROM块地址 */
                       unsigned char *uncoded_keys)
{
    signed char status = MI_OK;
    unsigned int e2addr = 0x80 + sector * 0x18;      /* EEROM地址为两个字节 */
    unsigned char coded_keys[12];

    if (key_type == PICC_AUTHENT1B)      /* 如果是B类卡 */
    {
        e2addr += 12;                    /* 取12字节以后的作为密钥地址 */
    }
    if ((status = M500HostCodeKey(uncoded_keys,coded_keys)) == MI_OK)  /* 如果密钥编码成功 */
    {
        status = PcdWriteE2(e2addr,12,coded_keys);    /* 将主密钥(12字节)送入RC500的EEROM  */
    }
    return status;            /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Write the MF RC500's EEPROM
 /* 写RC500's EEPROM */
///////////////////////////////////////////////////////////////////////
char PcdWriteE2(unsigned int startaddr,      /* EEROM地址为两个字节 */
                unsigned char length,        /* 长度  */
                unsigned char* _data)        /* 密钥在单片机里的初始地址 */
{
    char status = MI_OK;
    ResetInfo(MInfo);
    SerBuffer[0] = startaddr & 0xFF;         /* 存放密钥的EEROM块地址 */
    SerBuffer[1] = (startaddr >> 8) & 0xFF;  /* STARTADDR为整型变量,16BIT */
    memcpy(SerBuffer + 2,_data,length);      /* 将密钥拷贝到发送缓冲区 */

    MInfo.nBytesToSend   = length + 2;       /* 发送14字节 */

    status = M500PcdCmd(PCD_WRITEE2,        /* 执行写RC500's EEPROM命令 */
                       SerBuffer,
                       &MInfo);
    return status;                          /* 返回状态值 */
}

///////////////////////////////////////////////////////////////////////
// Select Command defined in ISO14443(MIFARE)
 /* 配置MFOUT/MFIN两脚输出内容 */

⌨️ 快捷键说明

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