/************************************************************************************************** * @fn MFRC522_CrcCheck * @brief 用MF522计算CRC校验 * @param CrcData -> 要校验CRC的数据 CrcLen -> 数据长度 CheckData -> CRC校验结果 * @return Size -> 卡号容量 ************************************************************************************************** */ void MFRC522_CrcCheck(uint8_t *CrcData, uint8_t CrcLen, uint8_t *CheckData) { uint8_t i; uint8_t CrcIrq; MFRC522_ClearBitMask(DivIrqReg,0x04); //BIT2=CRCIrq(0) MFRC522_SetBitMask(FIFOLevelReg,0x80); //BIT7=FlushBuffer(1), FIFO初始化 /*1.向FIFO中写入数据*/ for(i=0; i<CrcLen; i++) { MFRC522_Write(FIFODataReg,CrcData[i]); } MFRC522_Write(CommandReg,PCD_CALCCRC); //激活CRC协处理器或执行自测试 /*2.等待CRC校验完成*/ i = 0xFF; do { CrcIrq = MFRC522_Read(DivIrqReg); //BIT2=CRCIrq,CRC协处理器在处理完FIFO缓冲区的所有数据后置位CRCIRq标志 i--; } while((i!=0)&&!(CrcIrq & 0x04)); //1)i=0超时跳出 2)处理完FIFO缓冲区的所有数据跳出 /*3.读取CRC校验结果*/ CheckData[0] = MFRC522_Read(CRCResultRegL); CheckData[1] = MFRC522_Read(CRCResultRegM); }
/************************************************************************************************** * @fn MFRC522_ConfigISOType * @brief 设置RC632的工作方式,ISO14443A协议标准 * @param 无 * @return 无 ************************************************************************************************** */ void MFRC522_ISO14443A(void) { MFRC522_SetBitMask(Status2Reg, 0x08); //该位用来指示MIFARE Cypto1单元接通和因此所有卡的数据通信被加密的情况,MFCrypto1On=0 MFRC522_Write(RxSelReg , 0x86); //84 非接触式UART的输入选择内部模拟部分的调制信号 MFRC522_Write(RFCfgReg , 0x7F); //4F 接收器信号电压的增益因子48dB MFRC522_Delay(1); MFRC522_AntennaOn(); }
/************************************************************************************************** * @fn MFRC522_Anticoll * @brief RC522和ISO14443卡通讯 * @param CardData -> 卡号数据 * @return ReqStatus -> 寻卡结果 ************************************************************************************************** */ uint8_t MFRC522_Anticoll(uint8_t *CardData) { uint8_t i; uint8_t AntiStatus = MFRC522_ERR; uint32_t AntiBits; //接收到的数据有效位数 uint8_t CardDataCheck = 0; MFRC522_ClearBitMask(Status2Reg,0x08); //关闭内部温度传感器 MFRC522_Write(BitFramingReg,0x00); //BIT2-BIT0=TxLastBists(000) 定义发送的最后一个字节的位数,000表示最后一个字节的所有位都应发送 MFRC522_ClearBitMask(CollReg,0x80); //BIT7=ValuesAfterColl(1) CardData[0] = PICC_ANTICOLL; CardData[1] = 0x20; AntiStatus = MFRC522_ToCard(PCD_TRANSCEIVE,CardData,2,CardData,&AntiBits); if(AntiStatus == MFRC522_OK) { /*校验卡号*/ for(i=0; i<4; i++) { CardDataCheck ^= CardData[i]; //1.datasheet/RFID/MifareCard/1.M1简单介绍,4byte卡号 1byte校验字 } if(CardDataCheck != CardData[i]) { AntiStatus = MFRC522_ERR; } } MFRC522_SetBitMask(CollReg,0x80); //BIT7=ValuesAfterColl(1) return AntiStatus; }
uint8_t MFRC522_RequestCard(uint8_t ReqMode,uint8_t *CardType) { uint8_t ReqStatus = MFRC522_ERR; uint32_t ReqBits; //接收到的数据有效位数 MFRC522_Write(BitFramingReg,0x07); //BIT2-BIT0=TxLastBists(111)? //ReqStatus = MFRC522_Read(BitFramingReg); CardType[0] = ReqMode; ReqStatus = MFRC522_ToCard(PCD_TRANSCEIVE, CardType, 1, CardType, &ReqBits); if((ReqStatus != MFRC522_OK)||(ReqBits != 0x10)) //如果返回的不是16bit 0x0400正好是16bit { ReqStatus = MFRC522_ERR; } return ReqStatus; }
/************************************************************************************************** * @fn MFRC522_Reset * @brief MFRC522复位阶段设置 * @param n * @return 无 ************************************************************************************************** */ void MFRC522_Reset(void) { MFRC522_RST = 1; MFRC522_Delay(1); MFRC522_RST = 0; //低电平时切断内部电流吸收,关闭振荡器,断开输入管脚与外部电路的连接 MFRC522_Delay(1); MFRC522_RST = 1; //上升沿来启动内部复位阶段 MFRC522_Delay(1); MFRC522_Write(CommandReg, PCD_RESETPHASE); //BIT4=PowerDown(0):启动唤醒过程 BIT3-BIT0(1111):复位MFRC522 /*TPrescaler 12位预分频器 110100111110(3390)**/ MFRC522_Write(TModeReg,0x8D); //BIT7=TAuto(1):定时器启动 BIT3-BIT0=TPrescaler_Hi(1101):预分频器高4位 MFRC522_Write(TPrescalerReg,0x3E); //BIT7-BIT0(00111110)=TPrescaler_Lo:定时器预分频器低8位 /*TreloadVal 16位定时器重装值 30*/ MFRC522_Write(TReloadRegL,0x30); //定时器频率f = 6.78Mhz/TPrescaler T = 1/f = TPrescaler/6.78Mhz MFRC522_Write(TReloadRegH,0); //t = TreloadVal * T = 15ms 如果要为24ms,TReloadRegL = 0x30 MFRC522_Write(ModeReg, 0x3D); //BIT1-BIT0=CRCPreset(01):6363 MFRC522_Write(TxAutoReg, 0x40); //100%ASK }
/************************************************************************************************** * @fn MFRC522_SetBitMask * @brief 清RC522寄存器位 * @param RegAddr -> 寄存器地址 Mask -> 置位值 * @return 无 ************************************************************************************************** */ void MFRC522_SetBitMask(uint8_t RegAddr,uint8_t Mask) { uint8_t tmp; tmp = MFRC522_Read(RegAddr); MFRC522_Write(RegAddr, tmp | Mask); }
/************************************************************************************************** * @fn MFRC522_ClearBitMask * @brief 清RC522寄存器位 * @param RegAddr -> 寄存器地址 Mask -> 清位值 * @return 无 ************************************************************************************************** */ void MFRC522_ClearBitMask(uint8_t RegAddr,uint8_t Mask) { uint8_t tmp; tmp = MFRC522_Read(RegAddr); MFRC522_Write(RegAddr, tmp&(~Mask)); }
/************************************************************************************************** * @fn MFRC522_ToCard * @brief RC522和ISO14443卡通讯 * @param Command -> MF522命令字 SendData -> 过RC522发送到卡片的数据, SendLen -> 发送的数据长度 ReceiveData -> 接收到的卡片返回数据 ReveiveLen -> 返回数据的位长度 * @return ReqStatus -> 寻卡结果 ************************************************************************************************** */ uint8_t MFRC522_ToCard(uint8_t Command, uint8_t *SendData, uint8_t SendLen, uint8_t *ReceiveData, uint32_t *ReveiveBits) { uint8_t Status = MFRC522_ERR; uint8_t IrqEn = 0x00; uint8_t WaitIrq = 0x00; uint32_t i; uint8_t IRqStatus; uint8_t FIFOLevel = 0x00; //FIFOLevelReg BIT6-BIT0 FIFO缓冲区中保存的字节数,BIT7被读时返回为0无须担心 uint8_t RxLastBits = 0x00; //ControlReg BIT2-BIT0 显示最后接收到的字节的有效位数目,如果该位为0,整个字节有效 switch(Command) { case PCD_AUTHENT: IrqEn = 0x12; //认证卡密 WaitIrq = 0x10; break; case PCD_TRANSCEIVE: IrqEn = 0x77; //发送FIFO中数据 WaitIrq = 0x30; break; default: break; } MFRC522_Write(CommIEnReg, IrqEn|0x80); //允许中断请求 MFRC522_ClearBitMask(CommIrqReg, 0x80); //清除所有中断请求位 MFRC522_SetBitMask(FIFOLevelReg, 0x80); //BIT7=FlushBuffer(1), FIFO初始化 MFRC522_Write(CommandReg, PCD_IDLE); //无动作,取消当前动作的执行 /*1.向FIFO中写入数据*/ for(i=0; i<SendLen; i++) { MFRC522_Write(FIFODataReg,SendData[i]); } /*2.执行发送命令,将FIFO缓冲区的数据发送到天线,发送完成后自动激活接收器*/ MFRC522_Write(CommandReg,Command); if((Command == PCD_TRANSCEIVE) ||(Command == PCD_AUTHENT)) { MFRC522_SetBitMask(BitFramingReg,0x80); //BIT7=StartSend(1):启动数据发送 } /*3.等待数据接收完成*/ i = 2000; //i根据时钟频率调整,操作M1卡最大等待时间15ms?注意上面MFRC522_Reset函数中定时器的设置时间是15ms do { IRqStatus = MFRC522_Read(CommIrqReg); i--; } while((i!=0)&& !(IRqStatus&0x01) && !(IRqStatus&WaitIrq)); //1)i=0超时跳出 2)定时器(15ms)减到0时跳出 3)命令终止或者接收完成跳出 MFRC522_ClearBitMask(BitFramingReg,0x80); //停止数据发送 /*4.检测寻卡状态*/ if(i != 0) { /*4.1.寻卡未发生错误*/ if(!(MFRC522_Read(ErrorReg) & 0x1B)) //未发生以下错误:BufferOvfl Collerr CRCErr ProtecolErr { Status = MFRC522_OK; //这里可以设一个断点查看,表明未发生错误 if(IRqStatus & IrqEn & 0x01) //定时器递减到零,寻卡超时 { Status = MFRC522_TIMEOUT; } /*4.1.1 接收到的数据处理*/ if(Command == PCD_TRANSCEIVE) { FIFOLevel = MFRC522_Read(FIFOLevelReg); //接收到的字节数 RxLastBits = MFRC522_Read(ControlReg) & 0x07; //最后一个字节的有效数 if(RxLastBits) //如果不是0,最后一个字节并不是整个字节有效 { *ReveiveBits = (FIFOLevel-1)*8 + RxLastBits; } else //如果是0,整个字节有效 { *ReveiveBits = FIFOLevel * 8; } if(FIFOLevel == 0) { FIFOLevel = 1; } if(FIFOLevel > FIFOLEVEL_MAX) { FIFOLevel = FIFOLEVEL_MAX; } /*4.1.2 读取接收到的数据*/ for(i=0; i<FIFOLevel; i++) { ReceiveData[i] = MFRC522_Read(FIFODataReg); //读取FIFO缓冲区的数据 } } } /*4.2.寻卡发生错误,错误类型未知*/ else { Status = MFRC522_ERR; } } /*5.清除*/ MFRC522_SetBitMask(ControlReg,0x80); //停止定时器 MFRC522_Write(CommandReg,PCD_IDLE); //无动作,取消当前动作的执行 return Status; }
static int rc522_open(struct inode *inode, struct file *file) { uint8_t str[MAX_LEN]; uint8_t writeData[16]={1, 2, 3, 4, 0}; uint8_t i; uint8_t status; uint8_t size; uint8_t blockAddr; //选择操作的块地址0~63 //扇区A密码,16个扇区,每个扇区密码6Byte uint8_t sectorKeyA[16][16] = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},}; printk("rc522_open\r\n"); SPI_Init(); MFRC522_Init(); while (1) { //寻卡,返回卡类型 status = MFRC522_Request(PICC_REQIDL, str); if (status == MI_OK) { printk("%d \r\n", str[0]); printk("%d \r\n", str[1]); } //防冲撞,返回卡的序列号 4字节 status = MFRC522_Anticoll(str); memcpy(serNum, str, 5); if (status == MI_OK) { printk("%d \r\n", serNum[0]); printk("%d \r\n", serNum[1]); printk("%d \r\n", serNum[2]); printk("%d \r\n", serNum[3]); printk("%d \r\n", serNum[4]); } //选卡,返回卡容量 size = MFRC522_SelectTag(serNum); if (size != 0) { printk("size is %d", size); } //写 blockAddr = 1; //数据块 status = MFRC522_Auth(PICC_AUTHENT1A, blockAddr, sectorKeyA[blockAddr/4], serNum); //认证 if (status == MI_OK) { //写数据 status = MFRC522_Write(blockAddr, writeData); } //读 blockAddr = 1; //数据块 status = MFRC522_Auth(PICC_AUTHENT1A, blockAddr, sectorKeyA[blockAddr/4], serNum); //认证 if (status == MI_OK) { //读数据 status = MFRC522_Read(blockAddr, str); if (status == MI_OK) { for (i=0; i<16; i++) { printk("%d ", str[i]); } } } MFRC522_Halt(); //命令卡片进入休眠状态*/ } }