近期因为各种原因,重新租了个房子住,小区外面有门禁系统,楼下也有个门禁系统。房东只给了一套门禁卡,而我家人也需要门禁卡,所以我就去小区物业那里补卡,结果小区物业那里只能补小区的门禁卡,楼下的门禁卡需要在另外个地方补。物业工作人员给说了下地方,我找了下没找到,又想起了我一年前买了个RFID模块和十几个空白门禁卡,还没开封。又正好时值国庆,空闲时间比较多,不如自己来复制吧。

基础知识

一两个月前,我写了两篇STM32F103+RTT的入门博客。那两篇是非常基础的,到这里直接就是复制门禁卡,看起来好像不是循序渐进。不过也是没法子,毕竟现在从事的工作和这些完全不沾边,工作又忙,所以没太多时间来一步一步学习并且写博客,只能玩到哪是哪了。
先看了下门禁卡的分类和一些基础资料,了解到我新租住的房子所在的小区用的门禁卡是S50类型的。它具有16个 扇区,每个扇区具有四个Block,分别为0、1、2、3,每个Block可以存储16字节的数据。其中每个扇区的Block3存储的为6字节A密码+4字节控制位+6字节B密码。另外第一扇区的Block0存储的为卡号以及厂商的基本信息。卡就是下面的这个鬼样子:

一般来说,第一扇区的Block0下内容是不能更改的,我原以为小区门禁卡是通过其他扇区的数据来做验证的,后面写好了读数据的代码,发现从门禁卡中从数据块中读取的数据都是0,只有密码区、控制区及ID下第一扇区的Block0中有数据。所以我们的那个小区中的门禁卡应该是通过卡的第一扇区的Block0中的信息来验证的。也就是说我们要做的是复制整个卡,包括第一扇区的Block0。
要复制第一扇区的Block0,普通的IC卡就不行了,我之前买的卡就是普通的IC卡,鼓捣了很久,一直以为是程序写的有问题,后来才发现是卡不行。没办法,只能重新买卡了。
选卡也要选择合适的卡,查了下资料,能够修改第一扇区Block0的兼容S50类型的卡,有UID卡(可以使用后门指令无限制重复修改第一扇区Block0,会响应后门指令)、CUID卡(可以使用后门指令无限制重复修改第一扇区的Block0,不会响应后门指令)、FUID卡(使用普通指令,只能修改一次第一扇区的Block0)等。根据上面的说明,可以知道,UID卡可以无限制修改,但是由于会响应后门指令,所以如果门禁系统有检测后门指令并且禁用,那就不能用了。CUID不响应后门指令,但是由于可以用后面指令修改,门禁系统如果先去修改一下,确认不能修改,再进行门禁验证,那么CUID的卡就也不能用了。FUID显然是最保险的,但是从价格来说,FUID(2.2元) > CUID(1.3元) > UID(0.78元)。
所以我先试了下房东给的门禁卡,发现它是可以被修改的,而且也会响应后门指令,那么考虑性价比,当然是买UID卡了。10块钱13个还包邮,加上8块钱不到的一个RFID-RC522,一共18块钱(PS : 物业那里20块钱一个门禁卡,真坑)。

门禁卡复制实现

上面提到修改门禁卡第一扇区Block0是需要使用后门指令的,直接按照普通的写数据的方式进行修改,是无法修改的。既然主要目的是复制门禁卡,懒得重复去造轮子了。我之前买的RFID-RC522模块,使用的是SPI的通信模式,淘宝上搜索,应该很多都是这样的,如下图所示:

对,买的就是这样没焊脚的,然后我又买了个电烙铁套装。。。

然后上位机还是使用之前的那个STM32F103C8T6。

RC522驱动程序

然后再网上找了下STM32F103下RC522的驱动程序,并增加利用后门指令写第一扇区block0的代码如下:
驱动头文件rc522.h

#ifndef __RC522_H
#define __RC522_H#define MF522_RST_PIN                    GPIO_Pin_0
#define MF522_RST_PORT                   GPIOB
#define MF522_RST_CLK                    RCC_APB2Periph_GPIOB#define MF522_MISO_PIN                   GPIO_Pin_6
#define MF522_MISO_PORT                  GPIOA
#define MF522_MISO_CLK                   RCC_APB2Periph_GPIOA#define MF522_MOSI_PIN                   GPIO_Pin_7
#define MF522_MOSI_PORT                  GPIOA
#define MF522_MOSI_CLK                   RCC_APB2Periph_GPIOA#define MF522_SCK_PIN                    GPIO_Pin_5
#define MF522_SCK_PORT                   GPIOA
#define MF522_SCK_CLK                    RCC_APB2Periph_GPIOA#define MF522_NSS_PIN                    GPIO_Pin_4
#define MF522_NSS_PORT                   GPIOA
#define MF522_NSS_CLK                    RCC_APB2Periph_GPIOA#define RST_H                            GPIO_SetBits(MF522_RST_PORT, MF522_RST_PIN)
#define RST_L                            GPIO_ResetBits(MF522_RST_PORT, MF522_RST_PIN)
#define MOSI_H                           GPIO_SetBits(MF522_MOSI_PORT, MF522_MOSI_PIN)
#define MOSI_L                           GPIO_ResetBits(MF522_MOSI_PORT, MF522_MOSI_PIN)
#define SCK_H                            GPIO_SetBits(MF522_SCK_PORT, MF522_SCK_PIN)
#define SCK_L                            GPIO_ResetBits(MF522_SCK_PORT, MF522_SCK_PIN)
#define NSS_H                            GPIO_SetBits(MF522_NSS_PORT, MF522_NSS_PIN)
#define NSS_L                            GPIO_ResetBits(MF522_NSS_PORT, MF522_NSS_PIN)
#define READ_MISO                        GPIO_ReadInputDataBit(MF522_MISO_PORT, MF522_MISO_PIN)// ????
void PcdInit(void);
char PcdReset(void);
void PcdAntennaOn(void);
void PcdAntennaOff(void);
char PcdRequest(unsigned char req_code,unsigned char *pTagType);
char PcdAnticoll(unsigned char *pSnr);
char PcdSelect(unsigned char *pSnr);
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);
char PcdRead(unsigned char addr,unsigned char *pData);
char PcdWrite(unsigned char addr,unsigned char *pData);
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);
char PcdHalt(void);
char PcdComMF522(unsigned char Command,unsigned char *pInData, unsigned char InLenByte,unsigned char *pOutData, unsigned int  *pOutLenBit);
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);
void WriteRawRC(unsigned char Address,unsigned char value);
unsigned char ReadRawRC(unsigned char Address);
void SetBitMask(unsigned char reg,unsigned char mask);
void ClearBitMask(unsigned char reg,unsigned char mask);
char M500PcdConfigISOType(unsigned char type);
void delay_10ms(unsigned int _10ms);
void WaitCardOff(void);
char PcdSpicelWrite(unsigned char *pData);#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              #define PICC_REQIDL           0x26
#define PICC_REQALL           0x52
#define PICC_ANTICOLL1        0x93
#define PICC_ANTICOLL2        0x95
#define PICC_AUTHENT1A        0x60
#define PICC_AUTHENT1B        0x61
#define PICC_READ             0x30
#define PICC_WRITE            0xA0
#define PICC_DECREMENT        0xC0
#define PICC_INCREMENT        0xC1
#define PICC_RESTORE          0xC2
#define PICC_TRANSFER         0xB0
#define PICC_HALT             0x50    #define PCD_SPECIAL_COPY          0x43#define DEF_FIFO_LENGTH       64                 #define     RFU00                 0x00
#define     CommandReg            0x01
#define     ComIEnReg             0x02
#define     DivlEnReg             0x03
#define     ComIrqReg             0x04
#define     DivIrqReg             0x05
#define     ErrorReg              0x06
#define     Status1Reg            0x07
#define     Status2Reg            0x08
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2
#define     RFU20                 0x20
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
// PAGE 3
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39
#define     TestDAC2Reg           0x3A
#define     TestADCReg            0x3B
#define     RFU3C                 0x3C
#define     RFU3D                 0x3D
#define     RFU3E                 0x3E
#define     RFU3F                       0x3F#define     REQ_ALL               0x52
#define     KEYA                  0x60
#define     KEYB                  0x61#define MI_OK                          (char)0
#define MI_NOTAGERR                    (char)(-1)
#define MI_ERR                         (char)(-2)#endif

驱动实现rc522.c

#include "rc522.h"
#include "stm32f10x_gpio.h"#define MAXRLEN 18                        void PcdInit()
{GPIO_InitTypeDef  GPIO_InitStructure;/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(MF522_RST_CLK, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = MF522_RST_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(MF522_RST_PORT, &GPIO_InitStructure);/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(MF522_MISO_CLK, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = MF522_MISO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(MF522_MISO_PORT, &GPIO_InitStructure);/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(MF522_MOSI_CLK, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = MF522_MOSI_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(MF522_MOSI_PORT, &GPIO_InitStructure);/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(MF522_SCK_CLK, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = MF522_SCK_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(MF522_SCK_PORT, &GPIO_InitStructure);/* Enable the GPIO Clock */RCC_APB2PeriphClockCmd(MF522_NSS_CLK, ENABLE);/* Configure the GPIO pin */GPIO_InitStructure.GPIO_Pin = MF522_NSS_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(MF522_NSS_PORT, &GPIO_InitStructure);
}char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{char status;  unsigned int  unLen;unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x07);SetBitMask(TxControlReg,0x03);ucComMF522Buf[0] = req_code;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
//     if(status  == MI_OK )
//   { LED_GREEN  =0 ;}
//   else {LED_GREEN =1 ;}if ((status == MI_OK) && (unLen == 0x10)){    *pTagType     = ucComMF522Buf[0];*(pTagType+1) = ucComMF522Buf[1];}else{   status = MI_ERR;   }return status;
}char PcdAnticoll(unsigned char *pSnr)
{char status;unsigned char i,snr_check=0;unsigned int  unLen;unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x00);ClearBitMask(CollReg,0x80);ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x20;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);if (status == MI_OK){for (i=0; i<4; i++){   *(pSnr+i)  = ucComMF522Buf[i];snr_check ^= ucComMF522Buf[i];}if (snr_check != ucComMF522Buf[i]){   status = MI_ERR;    }}SetBitMask(CollReg,0x80);return status;
}char PcdSelect(unsigned char *pSnr)
{char status;unsigned char i;unsigned int  unLen;unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x70;ucComMF522Buf[6] = 0;for (i=0; i<4; i++){ucComMF522Buf[i+2] = *(pSnr+i);ucComMF522Buf[6]  ^= *(pSnr+i);}CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);ClearBitMask(Status2Reg,0x08);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x18)){   status = MI_OK;  }else{   status = MI_ERR;    }return status;
}char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{char status;unsigned int  unLen;unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = auth_mode;ucComMF522Buf[1] = addr;for (i=0; i<6; i++){    ucComMF522Buf[i+2] = *(pKey+i);   }for (i=0; i<6; i++){    ucComMF522Buf[i+8] = *(pSnr+i);   }//   memcpy(&ucComMF522Buf[2], pKey, 6); //   memcpy(&ucComMF522Buf[8], pSnr, 4); status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))){   status = MI_ERR;   }return status;
}char PcdRead(unsigned char addr,unsigned char *pData)
{char status;unsigned int  unLen;unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_READ;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x90))//   {   memcpy(pData, ucComMF522Buf, 16);   }{for (i=0; i<16; i++){    *(pData+i) = ucComMF522Buf[i];   }}else{   status = MI_ERR;   }return status;
}char PcdWrite(unsigned char addr,unsigned char *pData)
{char status;unsigned int  unLen;unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_WRITE;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){   status = MI_ERR;   }if (status == MI_OK){//memcpy(ucComMF522Buf, pData, 16);for (i=0; i<16; i++){    ucComMF522Buf[i] = *(pData+i);   }CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){   status = MI_ERR;   }}return status;
}//这个是写第一扇区Block0的代码
char PcdSpicelWrite(unsigned char *pData)
{char status;unsigned int  unLen;unsigned char i,ucComMF522Buf[MAXRLEN]; //需要使用以下步骤开启后门PcdHalt();WriteRawRC(BitFramingReg, 0x07);//WriteRawRC(CommandReg, 0x40);ucComMF522Buf[0] = 0x40;PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);WriteRawRC(BitFramingReg, 0x00);ucComMF522Buf[0] = 0x43;PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);return PcdWrite(0, pData);
}char PcdHalt(void)
{unsigned int  unLen;unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_HALT;ucComMF522Buf[1] = 0;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);return MI_OK;
}//?MF522??CRC16??
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{unsigned char i,n;ClearBitMask(DivIrqReg,0x04);WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80);for (i=0; i<len; i++){   WriteRawRC(FIFODataReg, *(pIndata+i));   }WriteRawRC(CommandReg, PCD_CALCCRC);i = 0xFF;do {n = ReadRawRC(DivIrqReg);i--;}while ((i!=0) && !(n&0x04));pOutData[0] = ReadRawRC(CRCResultRegL);pOutData[1] = ReadRawRC(CRCResultRegM);
}char PcdReset(void)
{RST_H;delay_10ms(1);RST_L;delay_10ms(1);RST_H;delay_10ms(10);if(ReadRawRC(0x02) == 0x80){}WriteRawRC(CommandReg,PCD_RESETPHASE);WriteRawRC(ModeReg,0x3D);           WriteRawRC(TReloadRegL,30);           WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);WriteRawRC(TxAutoReg,0x40);     return MI_OK;
}char M500PcdConfigISOType(unsigned char type)
{if (type == 'A'){ ClearBitMask(Status2Reg,0x08);WriteRawRC(ModeReg,0x3D);//3FWriteRawRC(RxSelReg,0x86);//84WriteRawRC(RFCfgReg,0x7F);   //4FWriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);delay_10ms(1);PcdAntennaOn();}else{ return (char)-1; }return MI_OK;
}unsigned char ReadRawRC(unsigned char Address)
{unsigned char i, ucAddr;unsigned char ucResult=0;NSS_L;ucAddr = ((Address<<1)&0x7E)|0x80;for(i=8;i>0;i--){SCK_L;if(ucAddr&0x80)MOSI_H;elseMOSI_L;SCK_H;ucAddr <<= 1;}for(i=8;i>0;i--){SCK_L;ucResult <<= 1;SCK_H;if(READ_MISO == 1)ucResult |= 1;}NSS_H;SCK_H;return ucResult;
}void WriteRawRC(unsigned char Address, unsigned char value)
{  unsigned char i, ucAddr;SCK_L;NSS_L;ucAddr = ((Address<<1)&0x7E);for(i=8;i>0;i--){if(ucAddr&0x80)MOSI_H;elseMOSI_L;SCK_H;ucAddr <<= 1;SCK_L;}for(i=8;i>0;i--){if(value&0x80)MOSI_H;elseMOSI_L;SCK_H;value <<= 1;SCK_L;}NSS_H;SCK_H;
}void SetBitMask(unsigned char reg,unsigned char mask)
{char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg,tmp | mask);  // set bit mask
}void ClearBitMask(unsigned char reg,unsigned char mask)
{char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg, tmp & ~mask);  // clear bit mask
} char PcdComMF522(unsigned char Command, unsigned char *pInData, unsigned char InLenByte,unsigned char *pOutData, unsigned int  *pOutLenBit)
{char status = MI_ERR;unsigned char irqEn   = 0x00;unsigned char waitFor = 0x00;unsigned char lastBits;unsigned char n;unsigned int i;switch (Command){case PCD_AUTHENT:irqEn   = 0x12;waitFor = 0x10;break;case PCD_TRANSCEIVE:case PCD_SPECIAL_COPY:irqEn   = 0x77;waitFor = 0x30;break;default:break;}WriteRawRC(ComIEnReg,irqEn|0x80);ClearBitMask(ComIrqReg,0x80);WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80);for (i=0; i<InLenByte; i++){   WriteRawRC(FIFODataReg, pInData[i]);    }WriteRawRC(CommandReg, Command);if (Command == PCD_TRANSCEIVE){    SetBitMask(BitFramingReg,0x80);  }i = 2000;do {n = ReadRawRC(ComIrqReg);i--;}while ((i!=0) && !(n&0x01) && !(n&waitFor));ClearBitMask(BitFramingReg,0x80);if (i!=0){    if(!(ReadRawRC(ErrorReg)&0x1B)){status = MI_OK;if (n & irqEn & 0x01){   status = 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<n; i++){   pOutData[i] = ReadRawRC(FIFODataReg);    }}}else{   status = MI_ERR;   }}SetBitMask(ControlReg,0x80);           // stop timer nowWriteRawRC(CommandReg,PCD_IDLE); return status;
}void PcdAntennaOn()
{unsigned char i;i = ReadRawRC(TxControlReg);if (!(i & 0x03)){SetBitMask(TxControlReg, 0x03);}
}void PcdAntennaOff()
{ClearBitMask(TxControlReg, 0x03);
}void WaitCardOff(void)
{char          status;unsigned char TagType[2];while(1){status = PcdRequest(REQ_ALL, TagType);if(status){status = PcdRequest(REQ_ALL, TagType);if(status){status = PcdRequest(REQ_ALL, TagType);if(status){return;}}}delay_10ms(10);}
}void delay_10ms(unsigned int _10ms)
{unsigned int i, j;for(i=0; i<_10ms; i++){for(j=0; j<60000; j++);}
}

后门代码实现依据来源于这篇博客,RC522驱动代码来源于这篇博客,在此表示感谢。

主要控制逻辑

按照之前点亮LED的经验,我们使用RTthread来进行进行门禁卡的检测和复制。主要代码如下:
复制代码被注释了,我们先使用检测并读取的代码,读取出原卡的内容,然后把读取内容记录下来,复制到新卡上去。正确的做法应该是使用完整逻辑来实现这个流程,这里为了方便,直接手动记录,然后修改代码重新编译来进行卡的复制,有兴趣有需要的朋友可在此基础上自行补充完成。


#include <board.h>
#include <rtthread.h>
#include "led.h"
#include "rc522.h"ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t led_stack[ 512 ];
static struct rt_thread led_thread;
static void led_thread_entry(void* parameter)
{unsigned int count=0;rt_hw_led_init();while (1){count++;rt_hw_led_on(0);rt_thread_delay( RT_TICK_PER_SECOND/2 ); /* sleep 0.5 second and switch to other thread */rt_hw_led_off(0);rt_thread_delay( RT_TICK_PER_SECOND/2 );}
}static void ShowID(u8 *p)
{u8 num[9];u8 i;for(i=0; i<4; i++){num[i*2]=p[i]/16;num[i*2]>9?(num[i*2]+='7'):(num[i*2]+='0');num[i*2+1]=p[i]%16;num[i*2+1]>9?(num[i*2+1]+='7'):(num[i*2+1]+='0');}num[8]=0;rt_kprintf("ID>>>%s\r\n", num);
}static rt_uint8_t rfid_stack[ 512 ];
static struct rt_thread rfid_thread;
static void rfid_thread_entry(void* parameter)
{unsigned int count=0;char status;unsigned char snr, buf[16], TagType[2], SelectedSnr[4], DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};PcdInit();PcdReset();PcdAntennaOff();PcdAntennaOn();M500PcdConfigISOType( 'A' );rt_kprintf( "rc522 init over!\n" );while(1){status= PcdRequest( REQ_ALL , TagType );if(!status) {status = PcdAnticoll(SelectedSnr);if(!status){status=PcdSelect(SelectedSnr);if(!status){ShowID(SelectedSnr);/*unsigned char inDoor[16] = {0x91, 0x94, 0x09, 0xa5, 0xa9, 0x88, 0x04, 0x00, 0x85, 0x00, 0xb4, 0x2e, 0xf0, 0xbb, 0x6a, 0xa8};unsigned char outDoor[16] = {0x1c, 0x6a, 0xa0, 0xa5, 0x73, 0x88, 0x04, 0x00,0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};status = PcdSpicelWrite(inDoor);*/if(!status){for(int i = 0;i < 16 ;i++){snr = i;status = PcdAuthState(KEYB, (snr*4+3), DefaultKey, SelectedSnr);for(int j = 0; j < 4; j++){status = PcdRead((snr*4+j), buf);//status = PcdWrite((snr*4+0), "way2"); if(!status){uint16_t * e = 0;e = (uint16_t *)TagType;//rt_kprintf("Snr Index : %d, type = %x \n", snr * 4 + j, *e);for(int n = 0; n < 16; n++){rt_kprintf("%x ", (uint16_t)buf[n]);}  rt_kprintf("\n"); }}}}rt_kprintf("operate finished! %x \n", status);WaitCardOff();}}}}
}void rt_init_thread_entry(void* parameter)
{#ifdef RT_USING_COMPONENTS_INIT/* initialization RT-Thread Components */rt_components_init();
#endif
}int rt_application_init(void)
{rt_thread_t init_thread;rt_err_t result;/* init led thread */result = rt_thread_init(&led_thread,"led",led_thread_entry,RT_NULL,(rt_uint8_t*)&led_stack[0],sizeof(led_stack),20,5);if (result == RT_EOK){rt_thread_startup(&led_thread);}result = rt_thread_init(&rfid_thread,"rfid",rfid_thread_entry,RT_NULL,(rt_uint8_t*)&rfid_stack[0],sizeof(rfid_stack),22,5);if (result == RT_EOK){rt_thread_startup(&rfid_thread);}#if (RT_THREAD_PRIORITY_MAX == 32)init_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 8, 20);
#elseinit_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 80, 20);
#endifif (init_thread != RT_NULL)rt_thread_startup(init_thread);return 0;
}/*@}*/

工程源码

工程源码挂载在CSDN下载频道,攒点下载分备用。欢迎转载,转载博客请注明出处湖广午王的博客。

STM32F103+RTT从零开始(三)—— S50门禁卡复制相关推荐

  1. id门禁卡复制到手机_怎么将手机当做门禁卡使用?给大家详解手机设置门禁卡功能...

    随着科技的发展,手机的功能是越来越强大了 . 门禁卡,相信大家都不陌生.进出小区都需要刷卡,自从手机可以使用微信跟支付宝支付功能以来,很少人携带钱包出门,一部手机便可以打车.吃饭付钱 等.银行卡跟身份 ...

  2. id门禁卡复制到手机_门禁卡复制到手机苹果

    大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答. 门禁卡复制到苹果手机的步骤如下: 1.首先读取卡的ID,并安装"NFC TagInfo",打开手机的NFC设置 ...

  3. 苹果7pnfc功能门禁卡_iPhone12门禁卡NFC功能怎么设置?门禁卡复制到手机上的方法...

    iPhone12门禁卡NFC功能怎么设置?大家都知道,目前安卓手机是可以轻松将IC门禁卡复制到手机上的,但是很多人不知道苹果手机怎么用NFC来复制门禁,今天,智能手机网小编就来分享一下iPhone12 ...

  4. 小区门禁卡可以复制到手机上吗_怎样把小区门禁卡复制到手机上

    展开全部 使用NFC功能 NFC是Near Field Communication缩写,即近距离无线通讯技术. 目前许多手机厂商62616964757a686964616fe78988e69d8331 ...

  5. 如何将电梯门禁卡复制到手机/手环上

    文章目录 背景 工具 将卡片复制到手机 方法一:"创建空白卡"方式 方法二:"模拟实体门禁卡"方式 方法三:直接使用设备上的"将门禁卡写入手机/手环& ...

  6. id门禁卡复制到手机_手机NFC有哪些功能?怎么设置手机门禁卡?别浪费了手机的NFC功能...

    NFC功能早前都运用一些手机旗舰机中,随着手机技术的发展,现在有许多的手机都有NFC的功能,那手机中的NFC只是个摆设吗?NFC不仅仅有不依靠数据网络.安全稳定的特点,其实还有许多你不知道的功能!比如 ...

  7. id门禁卡复制到手机_门禁卡复制到苹果手机

    NFC手机一枚 Root Explorer NFC Taginfo 方法/步骤 1,读取卡的ID.安装"NFC TagInfo",打开手机的NFC设置,门禁卡贴到手机后盖NFC部分 ...

  8. id门禁卡复制到手机_门禁卡怎么复制到苹果手机?

    NFC手机一枚 Root Explorer NFC Taginfo 方法/步骤 1,读取卡的62616964757a686964616fe78988e69d8331333363396461ID.安装& ...

  9. 北京千丁门禁卡复制 芯片是Nt芯片

    千丁门禁卡是由,北京千丁互联科技有限公司(简称"千丁")成立于2014年3月,是一家面向社区布局的科技公司.通过物联网.云技术.大数据及人工智能的创新科技,实现社区数字化.线上化. ...

最新文章

  1. html弹性重叠,关于html5弹性布局(2)
  2. ubuntu16.04 英文环境安装中文输入法
  3. 第3周实践项目7 删除链表元素最大值
  4. const char * 和 char const * 和 char * const 区别
  5. scikit_learn 官方文档翻译(集成学习)
  6. JAVA Web学习篇--Servlet
  7. Linux内核 获取本机mac,Linux获取本机MAC地址
  8. Daily Scrum02 12.17
  9. flAbsPath on /var/lib/dpkg/status failed 解决 Cydia 红字
  10. OSG实时纹理提取 离屏渲染 输出到OpenCV 反向渲染 OSG摄像头反转 OSG动态模型 摄像机实时渲染
  11. mrpoid模拟器java版_mrpoid2冒泡模拟器下载-mrpoid2模拟器下载3.0安卓版-西西软件下载...
  12. 爬取中国地震网地震数据
  13. Echars 如何描绘世界地图
  14. 实现网站在线客服系统代码过程中解决问题-js实现点击复制文本
  15. e.pageX、e.clientX、e.screenX、e.offsetX的区别以及元素的一些CSS属性
  16. Backstepping反步法控制四旋翼无人机(一)
  17. 有线广电如何转型和发展
  18. 3628中小企业的网络生存
  19. MDK 更换版本,原工程debug标签setting闪退
  20. java8时间间隔计算_Java8中Instant和LocalDate来计算时间或者日期间隔

热门文章

  1. 墨绘学:向孩子敞开心扉
  2. 计算机病毒生命开始周期,计算机病毒是人工生命第一个案例吗?
  3. class AdamWeightDecayOptimizer(tf.train.Optimizer): AttributeError: module ‘tensorflow._api.v2.tra
  4. 开源免费Webrtc转发服务器Mediasoup的概念解释与基本介绍(一)
  5. 怎样用计算机告白,计算机学科的告白情话
  6. C#学习之面象对象继承练习(二)
  7. 转贴汪应果先生的“全球华人应该向大陆中国人学什么?”
  8. 香港股市api调用代码返回示例
  9. AI 作画领域中的“神笔马良”是怎样炼成的?
  10. Minecraft 开服记录 自动备份