#include "MF522.h" #include "HW_MCUIO.h"//#include "stm32f4xx_hal.h" #include "platform.h" #include "platform_interface.h" #include "function.h" #if (NFC==1) //#if defined(NFC)&&(NFC==1) /* 2020.03,由于和Ethernet共用spi,Ethernet对速度要求高,所以切换到系统spi3 2020.05,修改硬件V03板,和W5500完全独立出来; RC522用模拟spi。 */ //#ifdef STM32F405xx //为F401增加 #define SYS_SPI3 extern SPI_HandleTypeDef hspi3; //#endif #define MF_DELAY 2//3//5 #define MAXRLEN 18 /* This i2c driver from stm32F1xx; we should add delay when operation io, because the stm32F4 much fast (The main frequency of stm32F4xx is 168M) !! F4系列速度太快,需要加延时,读写才正常!!!*/ static void mDelay(unsigned int nCount) { for (; nCount != 0; nCount--); } #define MF522_RST_PORT GPIOA #define MF522_RST_PIN GPIO_PIN_15 #define MF522_CS_PORT GPIOE #define MF522_CS_PIN GPIO_PIN_6 #define SET_MF522_RST {HAL_GPIO_WritePin(MF522_RST_PORT,MF522_RST_PIN,GPIO_PIN_SET);mDelay(MF_DELAY);} #define RESET_MF522_RST {HAL_GPIO_WritePin(MF522_RST_PORT,MF522_RST_PIN,GPIO_PIN_RESET);mDelay(MF_DELAY);} #define SET_MF522_NS {HAL_GPIO_WritePin(MF522_CS_PORT,MF522_CS_PIN,GPIO_PIN_SET);mDelay(MF_DELAY);} #define RESET_MF522_NS {HAL_GPIO_WritePin(MF522_CS_PORT,MF522_CS_PIN,GPIO_PIN_RESET);mDelay(MF_DELAY);} //#ifndef SYS_SPI3 #define MF522_SCK_PORT GPIOC #define MF522_SCK_PIN GPIO_PIN_15//GPIO_PIN_10 #define MF522_SI_PORT GPIOC #define MF522_SI_PIN GPIO_PIN_14//GPIO_PIN_12 #define MF522_MI_PORT GPIOE//GPIOC #define MF522_MI_PIN GPIO_PIN_12//GPIO_PIN_11 #define SET_MF522_SCK {HAL_GPIO_WritePin(MF522_SCK_PORT,MF522_SCK_PIN,GPIO_PIN_SET);mDelay(MF_DELAY);} #define RESET_MF522_SCK {HAL_GPIO_WritePin(MF522_SCK_PORT,MF522_SCK_PIN,GPIO_PIN_RESET);mDelay(MF_DELAY);} #define SET_MF522_SI {HAL_GPIO_WritePin(MF522_SI_PORT,MF522_SI_PIN,GPIO_PIN_SET);mDelay(MF_DELAY);} #define RESET_MF522_SI {HAL_GPIO_WritePin(MF522_SI_PORT,MF522_SI_PIN,GPIO_PIN_RESET);mDelay(MF_DELAY);} #define READ_MISO HAL_GPIO_ReadPin(MF522_MI_PORT,MF522_MI_PIN); //#endif //----------------------------------------------------------------- static void SPI_InitIO(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = MF522_RST_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;//GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(MF522_RST_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = MF522_CS_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH ;//GPIO_SPEED_FREQ_HIGH;//GPIO_SPEED_FREQ_MEDIUM;// HAL_GPIO_Init(MF522_CS_PORT, &GPIO_InitStruct); if( !get_hard_flag()){ //#ifndef SYS_SPI3 GPIO_InitStruct.Pin = MF522_SCK_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(MF522_SCK_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = MF522_SI_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(MF522_SI_PORT, &GPIO_InitStruct); //MISO GPIO_InitStruct.Pin = MF522_MI_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP;// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(MF522_MI_PORT, &GPIO_InitStruct); } SET_MF522_RST //*MF522_RST=1; SET_MF522_NS //*MF522_NS =1; //#endif } ///////////////////////////////////////////////////////////////////// //功 能:写RC632寄存器 //参数说明:Address[IN]:寄存器地址 // value[IN]:写入的值 ///////////////////////////////////////////////////////////////////// static void WriteRawRC(unsigned char Address, unsigned char value) { //#ifdef SYS_SPI3 if( get_hard_flag() ){ unsigned char ucAddr= ((Address << 1) & 0x7E); unsigned char tmp[2]; tmp[0] =ucAddr; tmp[1] =value; RESET_MF522_NS //*MF522_NS = 0; HAL_SPI_Transmit(&hspi3,tmp,2,100); SET_MF522_NS //*MF522_NS = 1; //#else } else{ unsigned char i, ucAddr; RESET_MF522_SCK //*MF522_SCK = 0; RESET_MF522_NS //*MF522_NS = 0; ucAddr = ((Address << 1) & 0x7E); for (i = 8; i > 0; i--){ if ((ucAddr & 0x80) == 0x80) SET_MF522_SI else RESET_MF522_SI SET_MF522_SCK //*MF522_SCK = 1; ucAddr <<= 1; RESET_MF522_SCK //*MF522_SCK = 0; } for (i = 8; i > 0; i--){ if ((value & 0x80) == 0x80) SET_MF522_SI else RESET_MF522_SI SET_MF522_SCK //*MF522_SCK = 1; value <<= 1; RESET_MF522_SCK //*MF522_SCK = 0; } SET_MF522_NS //*MF522_NS = 1; SET_MF522_SCK //*MF522_SCK = 1; } //#endif } ///////////////////////////////////////////////////////////////////// //功 能:读RC632寄存器 //参数说明:Address[IN]:寄存器地址 //返 回:读出的值 ///////////////////////////////////////////////////////////////////// static unsigned char ReadRawRC(unsigned char Address) { //#ifdef SYS_SPI3 if( get_hard_flag()){ unsigned char value[2],ucAddr = ((Address << 1) & 0x7E) | 0x80; RESET_MF522_NS //*MF522_NS = 0; HAL_SPI_TransmitReceive(&hspi3,&ucAddr,value,2,100); SET_MF522_NS //*MF522_NS = 1; return value[1]; //#else } else{ unsigned char i, ucAddr, ucResult = 0; RESET_MF522_SCK; //*MF522_SCK = 0; RESET_MF522_NS; //*MF522_NS = 0; ucAddr = ((Address << 1) & 0x7E) | 0x80; for (i = 8; i > 0; i--){ if ((ucAddr & 0x80) == 0x80) SET_MF522_SI else RESET_MF522_SI SET_MF522_SCK //*MF522_SCK = 1; ucAddr <<= 1; RESET_MF522_SCK //*MF522_SCK = 0; } for (i = 8; i > 0; i--){ SET_MF522_SCK //*MF522_SCK = 1; ucResult <<= 1; ucResult |=HAL_GPIO_ReadPin(MF522_MI_PORT,MF522_MI_PIN); RESET_MF522_SCK //*MF522_SCK = 0; } SET_MF522_NS; //*MF522_NS = 1; SET_MF522_SCK; //*MF522_SCK = 1; return ucResult; } //#endif } ///////////////////////////////////////////////////////////////////// //功 能:置RC522寄存器位 //参数说明:reg[IN]:寄存器地址 // mask[IN]:置位值 ///////////////////////////////////////////////////////////////////// static void SetBitMask(unsigned char reg, unsigned char mask) { char tmp = 0x0; tmp = ReadRawRC(reg); WriteRawRC(reg, tmp | mask); // set bit mask } ///////////////////////////////////////////////////////////////////// //功 能:清RC522寄存器位 //参数说明:reg[IN]:寄存器地址 // mask[IN]:清位值 ///////////////////////////////////////////////////////////////////// static void ClearBitMask(unsigned char reg, unsigned char mask) { char tmp = 0x0; tmp = ReadRawRC(reg); WriteRawRC(reg, tmp & ~mask); // clear bit mask } ///////////////////////////////////////////////////////////////////// //用MF522计算CRC16函数 ///////////////////////////////////////////////////////////////////// static 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); } ///////////////////////////////////////////////////////////////////// //开启天线 //每次启动或关闭天险发射之间应至少有1ms的间隔 ///////////////////////////////////////////////////////////////////// static void PcdAntennaOn(void) { unsigned char i; i = ReadRawRC(TxControlReg); if (!(i & 0x03)) { SetBitMask(TxControlReg, 0x03); } } ///////////////////////////////////////////////////////////////////// //关闭天线 ///////////////////////////////////////////////////////////////////// static void PcdAntennaOff(void) { ClearBitMask(TxControlReg, 0x03); } //---------------------------------------- static char PcdReset(void) { // SET_MF522_RST //*MF522_RST=1; // mDelay(50000); RESET_MF522_RST //*MF522_RST=0; mDelay(50000); SET_MF522_RST //*MF522_RST=1; mDelay(50000); WriteRawRC(CommandReg, PCD_RESETPHASE); mDelay(500); //_nop_(); WriteRawRC(ModeReg, 0x3D); //和Mifare卡通讯,CRC初始值0x6363 WriteRawRC(TReloadRegL, 30); WriteRawRC(TReloadRegH, 0); WriteRawRC(TModeReg, 0x8D); WriteRawRC(TPrescalerReg, 0x3E); WriteRawRC(TxAutoReg, 0x40); //必须要 ,设置逻辑1,强制100%ASK调制 Gavin return MI_OK; } ///////////////////////////////////////////////////////////////////// //功 能:通过RC522和ISO14443卡通讯 //参数说明:Command[IN]:RC522命令字 // pInData[IN]:通过RC522发送到卡片的数据 // InLenByte[IN]:发送数据的字节长度 // pOutData[OUT]:接收到的卡片返回数据 // *pOutLenBit[OUT]:返回数据的位长度 ///////////////////////////////////////////////////////////////////// //char PcdComMF522(unsigned char Command, static int PcdComMF522(unsigned char Command, unsigned char *pInData, unsigned char InLenByte, unsigned char *pOutData, unsigned int *pOutLenBit) { //char status = MI_ERR; int status = MI_ERR; unsigned char irqEn = 0x00; unsigned char waitFor = 0x00; //Mask by Gavin unsigned char lastBits; unsigned char n; unsigned int i; switch (Command) { case PCD_AUTHENT: irqEn = 0x12; waitFor = 0x10; break; case PCD_TRANSCEIVE: irqEn = 0x77; waitFor = 0x30; //Mask by Gavin break; default: break; } WriteRawRC(ComIEnReg, irqEn | 0x80); //reg0x02 ClearBitMask(ComIrqReg, 0x80); //reg0x04 ==0 WriteRawRC(CommandReg, PCD_IDLE); //reg0x01 SetBitMask(FIFOLevelReg, 0x80); //reg0x0A for (i = 0; i < InLenByte; i++) { WriteRawRC(FIFODataReg, pInData[i]); } //reg0x09 WriteRawRC(CommandReg, Command); if (Command == PCD_TRANSCEIVE) { SetBitMask(BitFramingReg, 0x80); } //reg0x0D // i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms i = 3600; #ifdef _NEW_NFC_APP i=1000;//800; //420是临界值 #endif do { n = ReadRawRC(ComIrqReg); //reg0x04 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) //timer IrQ==1 设定时间里没有找到? { 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 now WriteRawRC(CommandReg, PCD_IDLE); return status; } ///////////////////////////////////////////////////////////////////// //功 能:寻卡 //参数说明: 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) #ifdef _NEW_NFC_APP /* 2020.12.04 Gavin He * 调试发现,扫描函数PcdRequest 会消耗至少3ms的时间,这样拖慢整个主循环; * 慢的原因: 调用的PcdComMF522函数中有死循环等待! * 解决办法:将函数拆分成多个状态机,在主循环里多次访问完成; */ static int PcdRequest(unsigned char req_code, unsigned char *pTagType) { //PcdRequest 内部变量, int status = 1;//MI_ERR; static unsigned int unLen = 0; static unsigned char ucComMF522Buf[MAXRLEN]; //PcdComMF522 内部变量 static unsigned char irqEn = 0x00; static unsigned char waitFor = 0x00; //Mask by Gavin unsigned char lastBits; static unsigned char n; static unsigned int i; /*static int PcdComMF522(unsigned char Command, unsigned char *pInData, unsigned char InLenByte, unsigned char *pOutData, unsigned int *pOutLenBit)*/ //PcdComMF522 function input static unsigned char Command; static unsigned char *pInData; static unsigned char InLenByte; static unsigned char *pOutData; static unsigned int *pOutLenBit; static unsigned char find_step=0; //add by Gavin switch(find_step){ case 0: //----- PcdRequest part 1 --------------------- ClearBitMask(Status2Reg, 0x08); WriteRawRC(BitFramingReg, 0x07); SetBitMask(TxControlReg, 0x03); ucComMF522Buf[0] = req_code; //------- call function: PcdComMF522 Part1 start ---------- //status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen); Command = PCD_TRANSCEIVE; pInData = ucComMF522Buf; InLenByte =1; pOutData = ucComMF522Buf; unLen = 0; pOutLenBit =&unLen; switch (Command) { case PCD_AUTHENT: irqEn = 0x12; waitFor = 0x10; break; case PCD_TRANSCEIVE: irqEn = 0x77; waitFor = 0x30; //Mask by Gavin break; default: break; } WriteRawRC(ComIEnReg, irqEn | 0x80); //reg0x02 ClearBitMask(ComIrqReg, 0x80); //reg0x04 ==0 WriteRawRC(CommandReg, PCD_IDLE); //reg0x01 SetBitMask(FIFOLevelReg, 0x80); //reg0x0A for (i = 0; i < InLenByte; i++) { WriteRawRC(FIFODataReg, pInData[i]); } //reg0x09 WriteRawRC(CommandReg, Command); if (Command == PCD_TRANSCEIVE) { SetBitMask(BitFramingReg, 0x80); } //reg0x0D //-------- call function: PcdComMF522 Part1 end --------------------- i=200; //set waitfor timer find_step =1; //break; case 1: //-------- call function: PcdComMF522 Part2 --------------------- /* i = 3600; i=430; //420是临界值 do { n = ReadRawRC(ComIrqReg); //reg0x04 i--; } while ((i != 0) && !(n & 0x01) && !(n & waitFor)); */ // #define W_TIMER 255 i--; n = ReadRawRC(ComIrqReg); //reg0x04 if ( (i != 0) &&!(n & 0x01) && !(n & waitFor)){ //None find status = 1; } else{ //find; status = 1; find_step =2 ; } //-------------------------------------------------------------------------------- break; case 2: //-------- call function: PcdComMF522 Part3 --------------------- ClearBitMask(BitFramingReg, 0x80); if (i != 0) { if (!(ReadRawRC(ErrorReg) & 0x1B)) { status = MI_OK; if (n & irqEn & 0x01) //timer IrQ==1 设定时间里没有找到? { 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 now WriteRawRC(CommandReg, PCD_IDLE); //-------- call function: PcdComMF522 Part3 end --------------------- //----- PcdRequest part 2 --------------------- if ((status == MI_OK) && (unLen == 0x10)) { *pTagType = ucComMF522Buf[0]; *(pTagType + 1) = ucComMF522Buf[1]; } else { status = MI_ERR; } find_step =0; break; default: status = MI_ERR; break; }//sw return status; } #else static int PcdRequest(unsigned char req_code, unsigned char *pTagType) { int status; // //char status; unsigned int unLen = 0; 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) && (unLen == 0x10)) { *pTagType = ucComMF522Buf[0]; *(pTagType + 1) = ucComMF522Buf[1]; } else { status = MI_ERR; } return status; } #endif #if 0 ///////////////////////////////////////////////////////////////////// //功 能:防冲撞 //参数说明: pSnr[OUT]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// //char PcdAnticoll(unsigned char *pSnr) static int PcdAnticoll(unsigned char *pSnr) { //char status; int 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; } ///////////////////////////////////////////////////////////////////// //功 能:选定卡片 //参数说明: pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdSelect(unsigned char *pSnr) { int 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; } #else //将防碰撞级别由内置改为作为形参出入。YSY 2019.10.14 ///////////////////////////////////////////////////////////////////// //功 能:防冲撞 //参数说明: pSnr[OUT]:卡片序列号,4字节 // sec_code[IN]:防碰撞级别 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// //char PcdAnticoll(unsigned char *pSnr) static int PcdAnticoll(unsigned char sec_code, unsigned char *pSnr) { //char status; int 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] = sec_code; 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; } ///////////////////////////////////////////////////////////////////// //功 能:选定卡片 //参数说明: pSnr[IN]:卡片序列号,4字节 // sec_code[IN]:防碰撞级别 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdSelect(unsigned char sec_code, unsigned char *pSnr) { int status; unsigned char i; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = sec_code; 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; } #endif ///////////////////////////////////////////////////////////////////// //功 能:验证卡片密码 //参数说明: auth_mode[IN]: 密码验证模式 // 0x60 = 验证A密钥 // 0x61 = 验证B密钥 // addr[IN]:块地址 // pKey[IN]:密码 // pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// //static int PcdAuthState(unsigned char auth_mode, unsigned char addr, unsigned char *pKey, unsigned char *pSnr) //{ // int 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++) // //for (i = 0; i < 4; 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; //} ///////////////////////////////////////////////////////////////////// //功 能:写数据到M1卡一块 //参数说明: addr[IN]:块地址 // pData[IN]:写入的数据,16字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdWrite(unsigned char addr, unsigned char *pData) { int 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 < 4; i++) 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; } ///////////////////////////////////////////////////////////////////// //功 能:读取M1卡一块数据 //参数说明: addr[IN]:块地址 // pData[OUT]:读出的数据,16字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdRead(unsigned char addr, unsigned char *pData) { int 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) if ((status == MI_OK) && (unLen == 0x90)) // { memcpy(pData, ucComMF522Buf, 16); } { //for (i = 0; i < 4; i++)// for (i = 0; i < 16; i++) //2020.02.17 Gavin modify { *(pData + i) = ucComMF522Buf[i]; } } else { status = MI_ERR; } return status; } #ifdef NOUSE ///////////////////////////////////////////////////////////////////// //功 能:扣款和充值 //参数说明: dd_mode[IN]:命令字 // 0xC0 = 扣款 // 0xC1 = 充值 // addr[IN]:钱包地址 // pValue[IN]:4字节增(减)值,低位在前 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdValue(unsigned char dd_mode, unsigned char addr, unsigned char *pValue) { int status; unsigned int unLen; unsigned char i, ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = dd_mode; 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, pValue, 4); for (i = 0; i < 16; i++) { ucComMF522Buf[i] = *(pValue + i); } CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]); unLen = 0; status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen); if (status != MI_ERR) { status = MI_OK; } } if (status == MI_OK) { ucComMF522Buf[0] = PICC_TRANSFER; 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; } } return status; } ///////////////////////////////////////////////////////////////////// //功 能:备份钱包 //参数说明: sourceaddr[IN]:源地址 // goaladdr[IN]:目标地址 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr) { int status; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_RESTORE; ucComMF522Buf[1] = sourceaddr; 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) { ucComMF522Buf[0] = 0; ucComMF522Buf[1] = 0; ucComMF522Buf[2] = 0; ucComMF522Buf[3] = 0; CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]); status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen); if (status != MI_ERR) { status = MI_OK; } } if (status != MI_OK) { return MI_ERR; } ucComMF522Buf[0] = PICC_TRANSFER; ucComMF522Buf[1] = goaladdr; 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; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:命令卡片进入休眠状态 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// static int PcdHalt(void) { int status = 0x00; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_HALT; ucComMF522Buf[1] = 0; CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]); status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen); // return MI_OK; return status; } #endif #define CARD_SN_LEN 8 unsigned char error_count=0; unsigned char card_SN_last[CARD_SN_LEN]; #include "string.h" // ////MF522 卡验证时需要参数 //unsigned char DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; /* s1,开启自动寻卡,等待直到有卡0xE6+ 1byte + 4byte的序列号 S2,关闭自动寻卡 S3,开启1444A复合寻卡 S4, 读写操作 */ #ifdef _NEW_NFC_APP int nfc_write_read_N_block(struct nfc_app_STR *nfc) { unsigned char card_type[2]; unsigned char card_SN[4]; unsigned char card_SN_this[CARD_SN_LEN]; unsigned char i,rtmp[16],tmp[16],status; //寻卡,----得到卡的类型0x4400 if( (status =PcdRequest(PICC_REQALL, card_type) ) != MI_OK){ if( (status!=1) && (++error_count>=30) ){ error_count=0; memset(card_SN_last,0,CARD_SN_LEN); } return 0xE0; //return MI_ERR; } /* FM11NT ---0x44 , 0x00 M1 ---0x04 , //白卡 */ //更改为M0卡的防冲撞流程 YSY 2019.10.14 //防冲撞,----得到 卡片序列号,4字节 if( PcdAnticoll(0x93, card_SN) != MI_OK) return 0xE1; //return MI_ERR;goto rfid_error1; memcpy(card_SN_this,card_SN,4); //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x93, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; if( PcdAnticoll(0x95, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; memcpy(card_SN_this+4,card_SN,4); error_count =0; if(memcmp(card_SN_this,card_SN_last,CARD_SN_LEN) ==0) return 1; //tag保持add by Gavin 便于外部做应用 //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x95, card_SN) != MI_OK) return 0xE1; //goto rfid_error1; //--------------------------------------------------------------------- //a,write for(i=0;iwblock_cnt;i++){ //a1, read if(PcdRead(nfc->waddr[i],rtmp)!= MI_OK) goto rfid_error_retry1; //a2, modify memcpy(rtmp,nfc->wbuf[i],4); //a3,write if(PcdWrite(nfc->waddr[i], rtmp) != MI_OK) goto rfid_error_retry2; }//for //a4,read then check them for(i=0;iwblock_cnt;i++){ if(PcdRead(nfc->waddr[i],tmp)!= MI_OK) goto rfid_error_retry3; if( memcmp(nfc->wbuf[i],tmp,4) !=0 ) goto rfid_error_retry4; }//for //20201016 add by Gavin 修改次数 if(nfc->card_write_cnt_addr !=0){ unsigned int r_count,w_count=0; if(PcdRead(nfc->card_write_cnt_addr,tmp)!= MI_OK) goto rfid_error_retry6; w_count =(tmp[0]<<24)+(tmp[1]<<16)+(tmp[2]<<8)+(tmp[3]<<0) +1; tmp[0] = w_count>>24; tmp[1] = w_count>>16; tmp[2] = w_count>>8; tmp[3] = w_count>>0; if(PcdWrite(nfc->card_write_cnt_addr, tmp) != MI_OK) goto rfid_error_retry6; //read and check if(PcdRead(nfc->card_write_cnt_addr,tmp)!= MI_OK) goto rfid_error_retry6; r_count =(tmp[0]<<24)+(tmp[1]<<16)+(tmp[2]<<8)+(tmp[3]<<0); if( w_count != r_count) goto rfid_error_retry6; } //b,read keypad SN for(i=0;irblock_cnt;i++){ if( PcdRead(nfc->raddr[i],rtmp)!= MI_OK ) goto rfid_error_retry5; //return 0xE2; // memcpy(nfc->rbuf[i],rtmp,4); }//for //--------2020.12.17 从NFC直接获取UID; add by Gavin nfc->rbuf[0][0] = card_SN_this[7]; nfc->rbuf[0][1] = card_SN_this[6]; nfc->rbuf[0][2] = card_SN_this[5]; nfc->rbuf[0][3] = card_SN_this[4]; nfc->rbuf[1][0] = card_SN_this[3]; nfc->rbuf[1][1] = card_SN_this[2]; nfc->rbuf[1][2] = card_SN_this[1]; nfc->rbuf[1][3] = card_SN_this[0]; //------------------------------------- memcpy(card_SN_last,card_SN_this,CARD_SN_LEN); return 0x12; //return MI_OK; //---------------------------------------------------------------------------- rfid_error_retry1: rfid_error_retry2: rfid_error_retry3: rfid_error_retry4: rfid_error_retry5: rfid_error_retry6: return 0xE2; // } #else int nfc_write_read_N_block(struct nfc_app_STR *nfc) { unsigned char card_type[2]; unsigned char card_SN[4]; unsigned char card_SN_this[CARD_SN_LEN]; unsigned char i,rtmp[16],tmp[16]; //寻卡,----得到卡的类型0x4400 if( PcdRequest(PICC_REQALL, card_type) != MI_OK){ if(++error_count>=10){ error_count=0; memset(card_SN_last,0,CARD_SN_LEN); } return 0xE0; //return MI_ERR; } /* FM11NT ---0x44 , 0x00 M1 ---0x04 , //白卡 */ //更改为M0卡的防冲撞流程 YSY 2019.10.14 //防冲撞,----得到 卡片序列号,4字节 if( PcdAnticoll(0x93, card_SN) != MI_OK) return 0xE1; //return MI_ERR;goto rfid_error1; memcpy(card_SN_this,card_SN,4); //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x93, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; if( PcdAnticoll(0x95, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; memcpy(card_SN_this+4,card_SN,4); //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x95, card_SN) != MI_OK) return 0xE1; //goto rfid_error1; #ifdef _NFC_DEBUG_ nfc->debug_driver_keep_cnt++; #endif error_count =0; if(memcmp(card_SN_this,card_SN_last,CARD_SN_LEN) ==0) return 1; //tag保持add by Gavin 便于外部做应用 //--------------------------------------------------------------------- #ifdef _NFC_DEBUG_ nfc->debug_driver_start_cnt++; #endif #if 0 //a,write for(i=0;iwblock_cnt;i++){ //a1, read if(PcdRead(nfc->waddr[i],rtmp)!= MI_OK) goto rfid_error_retry1; //a2, modify memcpy(rtmp,nfc->wbuf[i],4); //a3,write PcdWrite(nfc->waddr[i], rtmp); mDelay(50); if(PcdWrite(nfc->waddr[i], rtmp) != MI_OK) goto rfid_error_retry2; mDelay(50); //a4,read then check them if(PcdRead(nfc->waddr[i],tmp)!= MI_OK) goto rfid_error_retry3; if( memcmp(rtmp,tmp,4) !=0 ) goto rfid_error_retry4; }//for #else //a,write for(i=0;iwblock_cnt;i++){ //a1, read if(PcdRead(nfc->waddr[i],rtmp)!= MI_OK) goto rfid_error_retry1; //a2, modify memcpy(rtmp,nfc->wbuf[i],4); //a3,write if(PcdWrite(nfc->waddr[i], rtmp) != MI_OK) goto rfid_error_retry2; }//for ////a4,read then check them for(i=0;iwblock_cnt;i++){ if(PcdRead(nfc->waddr[i],tmp)!= MI_OK) goto rfid_error_retry3; if( memcmp(nfc->wbuf[i],tmp,4) !=0 ) goto rfid_error_retry4; }//for //20201016 add by Gavin 修改次数 if(nfc->card_write_cnt_addr !=0){ unsigned int r_count,w_count=0; if(PcdRead(nfc->card_write_cnt_addr,tmp)!= MI_OK) goto rfid_error_retry6; w_count =(tmp[0]<<24)+(tmp[1]<<16)+(tmp[2]<<8)+(tmp[3]<<0) +1; tmp[0] = w_count>>24; tmp[1] = w_count>>16; tmp[2] = w_count>>8; tmp[3] = w_count>>0; if(PcdWrite(nfc->card_write_cnt_addr, tmp) != MI_OK) goto rfid_error_retry6; //read and check if(PcdRead(nfc->card_write_cnt_addr,tmp)!= MI_OK) goto rfid_error_retry6; r_count =(tmp[0]<<24)+(tmp[1]<<16)+(tmp[2]<<8)+(tmp[3]<<0); if( w_count != r_count) goto rfid_error_retry6; } #endif //b,read keypad SN for(i=0;irblock_cnt;i++){ if( PcdRead(nfc->raddr[i],rtmp)!= MI_OK ) goto rfid_error_retry5; //return 0xE2; // memcpy(nfc->rbuf[i],rtmp,4); }//for #ifdef _NFC_DEBUG_ nfc->debug_driver_ok_cnt++; memcpy(nfc->card_sn,card_SN_this,CARD_SN_LEN); #endif memcpy(card_SN_last,card_SN_this,CARD_SN_LEN); return 0x12; //return MI_OK; //---------------------------------------------------------------------------- #ifdef _NFC_DEBUG_ rfid_error_retry1: memcpy(nfc->error[1].card_sn[nfc->error[1].cnt],card_SN_this,CARD_SN_LEN); nfc->error[1].cnt++; return 0xE2; // rfid_error_retry2: memcpy(nfc->error[2].card_sn[nfc->error[2].cnt],card_SN_this,CARD_SN_LEN); nfc->error[2].cnt++; return 0xE2; // rfid_error_retry3: memcpy(nfc->error[3].card_sn[nfc->error[3].cnt],card_SN_this,CARD_SN_LEN); nfc->error[3].cnt++; return 0xE2; // rfid_error_retry4: memcpy(nfc->error[4].card_sn[nfc->error[4].cnt],card_SN_this,CARD_SN_LEN); nfc->error[4].cnt++; return 0xE2; // rfid_error_retry5: memcpy(nfc->error[5].card_sn[nfc->error[5].cnt],card_SN_this,CARD_SN_LEN); nfc->error[5].cnt++; return 0xE2; // rfid_error_retry6: memcpy(nfc->error[6].card_sn[nfc->error[6].cnt],card_SN_this,CARD_SN_LEN); nfc->error[6].cnt++; return 0xE2; // #else rfid_error_retry1: rfid_error_retry2: rfid_error_retry3: rfid_error_retry4: rfid_error_retry5: rfid_error_retry6: return 0xE2; // #endif } #endif ////////////////////////////////////////////////////////////////////// //??RC632????? ////////////////////////////////////////////////////////////////////// static int M500PcdConfigISOType(unsigned char type) { if (type == 'A'){ //ISO14443_A ClearBitMask(Status2Reg, 0x08); WriteRawRC(RxSelReg, 0x86); //84 WriteRawRC(RFCfgReg, 0x7F); //4F WriteRawRC(TReloadRegL, 30); //tmoLength);// TReloadVal = 'h6a =tmoLength(dec) WriteRawRC(TReloadRegH, 0); WriteRawRC(TModeReg, 0x8D); WriteRawRC(TPrescalerReg, 0x3E); WriteRawRC(TxAutoReg, 0x40); //Force100ASK(???)//add by Gavin mDelay(100); PcdAntennaOn(); } else{ return MI_NOTAGERR;//-1; } return MI_OK; } /* * initinal RFid card enter; */ void rfid_init(void) { SPI_InitIO(); PcdReset(); PcdAntennaOff(); //关闭天线 PcdAntennaOn(); //开启天线 M500PcdConfigISOType('A'); } //unsigned char testx; /* * this function using check rfid reader connect or not */ unsigned char get_rfid_reader_Hard_connect_status(void) { //testx =ReadRawRC(RFCfgReg); return ( (ReadRawRC(RFCfgReg)==0x7F)?1:0); } /* * rfid reader-- debug only */ unsigned char nfc_reader(unsigned char addr,unsigned char cnt,unsigned char *out) { unsigned char card_type[2]; unsigned char card_SN[4]; unsigned char card_SN_this[CARD_SN_LEN]; unsigned char i;//,rtmp[16],tmp[16]; //寻卡,----得到卡的类型0x4400 if( PcdRequest(PICC_REQALL, card_type) != MI_OK){ if(++error_count>=10){ error_count=0; memset(card_SN_last,0,CARD_SN_LEN); } return 0xE0; //return MI_ERR; } /* FM11NT ---0x44 , 0x00 M1 ---0x04 , //白卡 */ //更改为M0卡的防冲撞流程 YSY 2019.10.14 //防冲撞,----得到 卡片序列号,4字节 if( PcdAnticoll(0x93, card_SN) != MI_OK) return 0xE1; //return MI_ERR;goto rfid_error1; memcpy(card_SN_this,card_SN,4); //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x93, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; if( PcdAnticoll(0x95, card_SN)!= MI_OK) return 0xE1; //goto rfid_error1; memcpy(card_SN_this+4,card_SN,4); //选卡--INPUT 卡片的序列号4字节!! if( PcdSelect(0x95, card_SN) != MI_OK) return 0xE1; //goto rfid_error1; error_count =0; if(memcmp(card_SN_this,card_SN_last,CARD_SN_LEN) ==0) return 1; //tag保持add by Gavin 便于外部做应用 //b,read keypad SN for(i=0;i