目录

一、环境介绍

二、功能介绍

三、MFR522介绍

四、IC卡介绍

五、核心代码

资料下载地址:STM32+MFRC522完成IC卡号读取、密码修改、数据读写

一、环境介绍

MCU: STM32F103ZET6

开发软件: Keil5

非接触式读写卡模块: MFRC522

二、功能介绍

使用MFRC522模块完成对IC卡卡号读取、卡类型区分、IC卡扇区密码修改、扇区数据读写等功能;底层采用SPI模拟时序,可以很方便的移植到其他设备,完成项目开发。 现在很多嵌入式方向的毕业设计经常使用到该模块,比如: 校园一卡通设计、水卡充值消费设计、公交卡充值消费设计等。

三、MFR522介绍

MF RC522 是应用于13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员。是NXP 公司针对“三表”应用推出的一款低电压、低成本、体积小的非接触式读写卡芯片,是智能仪表和便携式手持设备研发的较好选择。

MF RC522 利用了先进的调制和解调概念,完全集成了在13.56MHz 下所有类型的被动非接触式通信方式和协议。支持 ISO14443A 的多层应用。其内部发送器部分可驱动读写器天线与ISO 14443A/MIFARE卡和应答机的通信,无需其它的电路。接收器部分提供一个坚固而有效的解调和解码电路,用于处理ISO14443A 兼容的应答器信号。数字部分处理ISO14443A 帧和错误检测(奇偶 &CRC)。此外,它还支持快速CRYPTO1 加密算法,用于验证MIFARE 系列产品。MFRC522 支持MIFARE?更高速的非接触式通信,双向数据传输速率高达424kbit/s。

作为13.56MHz 高集成度读写卡系列芯片家族的新成员,MF RC522 与MF RC500和 MF RC530 有不少相似之处,同时也具备诸多特点和差异。它与主机间的通信采用连线较少的串行通信,且可根据不同的用户需求,选取SPI、I2C 或串行UART(类似RS232)模式之一,有利于减少连线,缩小PCB 板体积,降低成本。

四、IC卡介绍

非接触式IC卡又称射频卡,由IC芯片、感应天线组成,封装在一个标准的PVC卡片内,芯片及天线无任何外露部分。是世界上最近几年发展起来的一项新技术,它成功的将射频识别技术和IC卡技术结合起来,结束了无源(卡中无电源)和免接触这一难题,是电子器件领域的一大突破。卡片在一定距离范围(通常为5—10cm)靠近读写器表面,通过无线电波的传递来完成数据的读写操作。

射频读写器向IC卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,这样在电磁波激励下,LC谐振电路产生共振,从而使电容内有了电荷;在这个电荷的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内存储,当所积累的电荷达到2V时,此电容可作为电源为其它电路提供工作电压,将卡内数据发射出去或接受读写器的数据。

非接触性IC卡与读卡器之间通过无线电波来完成读写操作。二者之间的通讯频率为13.56MHZ。非接触性IC卡本身是无源卡,当读写器对卡进行读写操作时,读写器发出的信号由两部分叠加组成:一部分是电源信号,该信号由卡接收后,与本身的L/C产生一个瞬间能量来供给芯片工作。另一部分则是指令和数据信号,指挥芯片完成数据的读取、修改、储存等,并返回信号给读写器,完成一次读写操作。读写器则一般由单片机,专用智能模块和天线组成,并配有与PC的通讯接口,打印口,I/O口等,以便应用于不同的领域。

M1卡详细指标

M1卡是指M1芯片,是指菲利浦下属子公司恩智浦出品的芯片缩写,全称为NXP Mifare1系列,常用的有S50及S70两种型号。

M1(S50)卡详细规格:

  1. 芯片类型:PhilipsMifare1ICS50
  2. 存储容量:8Kbit,16个分区,每分区两组密码;
  3. 工作频率:13.56?MHz;
  4. 通讯速率:106KBoud;
  5. 读写距离:2.5~10cm;
  6. 读写时间:1~2ms;
  7. 工作温度:-20℃~55℃;
  8. 擦写寿命:>100,000次;
  9. 数据保存:>10年;
  10. 外形尺寸:ISO标准卡85.6x54x0.82;
  11. 封装材料:PVC、PET、PETG、0.13mm铜线;

Mifare S50和Mifare S70又常被称为Mifare Standard、Mifare Classic、MF1,是遵守ISO14443A标准的卡片中应用最为广、影响力最大的的一员。而Mifare S70的容量是S50的4倍,S50的容量是1K字节,S70的容量为4K字节。

读写器对卡片的操作时序和操作命令,二者完全一致。 Mifare S50和Mifare S70的每张卡片都有一个4字节的全球唯一序列号,卡上数据保存期为10年,可改写10万次,读无限次。一般的应用中,不用考虑卡片是否会被读坏写坏的问题,

当然暴力硬损坏除外。 Mifare S50和Mifare S70的区别主要有两个方面。一是读写器对卡片发出请求命令,二者应答返回的卡类型(ATQA)字节不同。Mifare S50的卡类型(ATQA)是0004H,Mifare S70的卡类型(ATQA)是0002H。另一个区别就是二者的容量和内存结构不同。

M1卡分为16个扇区,每个扇区由4块(0、1、2、3)组成。实际操作时,将16个扇区分为64个块,按绝对地址编号为0-63。

结构如下:

  1. 第0个扇区用于存放厂商代码,意见固话,不可更改。
  2. 每个扇区的块0、块1、块2为数据块,可以用于存储数据。数据块可以进行读写操作。
  3. 每个扇区的块3为控制块,包括了密码A、存储控制、密码B。具体结构如下:

4. 每个扇区的密码和控制位都是独立的,可以根据实际需求设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据和控制块)存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有一个相应的三个控制位。定义如下:

Mifare 1 S50 白卡读写时一般步骤: 寻卡-->下载块密码--> 读写块数据。控制块也是一样。

数据块的访问权限设置表格:(根据自己需要的权限,完成上图字节6、7、8的填充即可)

控制块的读写权限设置:(包含了对密码A、控制权限、密码的读写权限)

7 6 5 4 3 2 1 0

字节6 1 1 1 1 1 1 1 1

字节7 0 0 0 0 1 1 1 1

字节8 0 0 0 0 0 0 0 0

字节9

设置的控制权限如下:0xFF 0x0F 0x00 0x00

代表数据块的权限: 验证密码A或者密码B都可以对数据块进行读写操作或者加值键值操作。

2. 代表控制块的权限

(1) 验证A密码之后可以写A/B密码,不能读密码。

可以读控制字节(4个),无法写控制字节

可以读写B密码

(2) 验证B密码之后,可以读写A/B密码,也可读控制字节,但无法写控制字节。

五、核心代码

#include "sys.h"
#include "RFID_RC522.h"
#include "delay.h"
#include "string.h"
#include "usart.h"/*
函数功能:移植接口--SPI时序读写一个字节
函数参数:data:要写入的数据
返 回 值:读到的数据
*/
u8 RC522_SPI_ReadWriteOneByte(u8 tx_data)
{                u8 rx_data=0;              u8 i;for(i=0;i<8;i++){RC522_SCLK=0;  if(tx_data&0x80){RC522_OUTPUT=1;}else {RC522_OUTPUT=0;}tx_data<<=1;   RC522_SCLK=1;rx_data<<=1;if(RC522_INPUT)rx_data|=0x01;}return rx_data;
}/*
函数功能:初始化RC522的IO口
*/
void RC522_IO_Init(void)
{RCC->APB2ENR|=1<<2;     //PA时钟使能 RCC->APB2ENR|=1<<7;     //PF时钟使能//PA5  时钟 RC522_SCLK//PA6  输入 RC522_INPUT//PA7  输出 RC522_OUTPUT GPIOA->CRL&=0x000FFFFF;GPIOA->CRL|=0x38300000;GPIOA->ODR|=0x3<<5;//RC522_RST <----->PF1--复位脚//RC522_SDA <----->PF0--片选脚GPIOF->CRL&=0xFFFFFF00;GPIOF->CRL|=0x00000033;GPIOF->ODR|=0x3<<0;
}   /*
功能描述:选卡读取卡存储器容量
输入参数:serNum 传入卡序列号
返 回 值:成功返回卡容量
*/
u8 RC522_MFRC522_SelectTag(u8 *serNum) //读取卡存储器容量
{     u8 i;     u8 status;     u8 size;     u8 recvBits;     u8 buffer[9];buffer[0]=PICC_ANTICOLL1;      //防撞码1     buffer[1]=0x70;buffer[6]=0x00;                            for(i=0;i<4;i++)                 {buffer[i+2]=*(serNum+i);    //buffer[2]-buffer[5]为卡序列号buffer[6]^=*(serNum+i);   //卡校验码}RC522_CalulateCRC(buffer,7,&buffer[7]);    //buffer[7]-buffer[8]为RCR校验码RC522_ClearBitMask(Status2Reg,0x08);status=RC522_PcdComMF522(PCD_TRANSCEIVE,buffer,9,buffer,&recvBits);if((status==MI_OK)&&(recvBits==0x18))    size=buffer[0];     else    size=0;return size;
}/*
延时函数,纳秒级
*/
void RC522_Delay(u32 ns)
{u32 i;for(i=0;i<ns;i++){__nop();__nop();__nop();}
}/*
函数功能:RC522芯片初始化
*/
void RC522_Init(void)
{RC522_IO_Init();   //RC522初始化RC522_PcdReset();             //复位RC522 RC522_PcdAntennaOff();    //关闭天线DelayMs(2);         //延时2毫秒RC522_PcdAntennaOn();      //开启天线M500PcdConfigISOType('A'); //设置RC632的工作方式
}/*
函数功能:复位RC522
*/
void RC522_Reset(void)
{RC522_PcdReset();              //复位RC522RC522_PcdAntennaOff(); //关闭天线DelayMs(2);         //延时2毫秒RC522_PcdAntennaOn();      //开启天线
}     /*
功    能: 寻卡
参数说明: req_code[IN]:寻卡方式0x52   = 寻感应区内所有符合14443A标准的卡0x26   = 寻未进入休眠状态的卡pTagType[OUT]:卡片类型代码0x4400 = Mifare_UltraLight0x0400 = Mifare_One(S50)0x0200 = Mifare_One(S70)0x0800 = Mifare_Pro(X)0x4403 = Mifare_DESFire
返 回 值: 成功返回MI_OK
*/
char RC522_PcdRequest(u8 req_code,u8 *pTagType)
{char status;  u8 unLen;u8 ucComMF522Buf[MAXRLEN];         // MAXRLEN  18RC522_ClearBitMask(Status2Reg,0x08);   //清RC522寄存器位,/接收数据命令RC522_WriteRawRC(BitFramingReg,0x07); //写RC632寄存器RC522_SetBitMask(TxControlReg,0x03);  //置RC522寄存器位ucComMF522Buf[0]=req_code;      //寻卡方式status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); //通过RC522和ISO14443卡通讯if((status==MI_OK)&&(unLen==0x10)){    *pTagType=ucComMF522Buf[0];*(pTagType+1)=ucComMF522Buf[1];}else{status = MI_ERR;}  return status;
}/*
功    能: 防冲撞
参数说明: pSnr[OUT]:卡片序列号,4字节
返    回: 成功返回MI_OK
*/
char RC522_PcdAnticoll(u8 *pSnr)
{char status;u8 i,snr_check=0;u8 unLen;u8 ucComMF522Buf[MAXRLEN]; RC522_ClearBitMask(Status2Reg,0x08);  //清RC522寄存器位 RC522_WriteRawRC(BitFramingReg,0x00); //写RC522_ClearBitMask(CollReg,0x80);     //清ucComMF522Buf[0]=PICC_ANTICOLL1;   //PICC_ANTICOLL1 = 0x93ucComMF522Buf[1]=0x20;status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); //0x0c,通过RC522和ISO14443卡通讯//PCD_TRANSCEIVE =发送并接收数据//2:写入卡里的数据字节长度//ucComMF522Buf:存放数据的地址//unLen:从卡里读出的数据长度if(status==MI_OK){for(i=0;i<4;i++){   *(pSnr+i)=ucComMF522Buf[i];  //把读到的卡号赋值给pSnrsnr_check^=ucComMF522Buf[i];}if(snr_check!=ucComMF522Buf[i]){status = MI_ERR;}}   RC522_SetBitMask(CollReg,0x80);return status;
}/*
功    能:选定卡片
参数说明:pSnr[IN]:卡片序列号,4字节
返    回:成功返回MI_OK
*/
char RC522_PcdSelect(u8 *pSnr)
{char status;u8 i;u8 unLen;u8 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);}RC522_CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]); //用MF522计算CRC16函数,校验数据RC522_ClearBitMask(Status2Reg,0x08);                 //清RC522寄存器位status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);if((status==MI_OK)&&(unLen==0x18))status=MI_OK;else status=MI_ERR;return status;
}/*
功    能:验证卡片密码
参数说明:auth_mode[IN]: 密码验证模式0x60 = 验证A密钥0x61 = 验证B密钥 addr[IN]:块地址pKey[IN]:扇区密码pSnr[IN]:卡片序列号,4字节
返    回:成功返回MI_OK
*/
char RC522_PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr)
{char status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];  //MAXRLEN  18(数组的大小)//验证模式+块地址+扇区密码+卡序列号   ucComMF522Buf[0]=auth_mode;        ucComMF522Buf[1]=addr;             memcpy(&ucComMF522Buf[2],pKey,6); //拷贝,复制memcpy(&ucComMF522Buf[8],pSnr,4); status=RC522_PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);if((status!= MI_OK)||(!(RC522_ReadRawRC(Status2Reg)&0x08)))status = MI_ERR;return status;
}/*
功    能:读取M1卡一块数据
参数说明: addr:块地址p   :读出的块数据,16字节
返    回:成功返回MI_OK
*/
char RC522_PcdRead(u8 addr,u8 *p)
{char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN]; //18ucComMF522Buf[0]=PICC_READ;ucComMF522Buf[1]=addr;RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);//通过RC522和ISO14443卡通讯if((status==MI_OK&&(unLen==0x90))){for(i=0;i<16;i++){*(p +i)=ucComMF522Buf[i];}}else{   status=MI_ERR;}return status;
}/*
功    能:写数据到M1卡指定块
参数说明:addr:块地址p   :向块写入的数据,16字节
返    回:成功返回MI_OK
*/
char RC522_PcdWrite(u8 addr,u8 *p)
{char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0]=PICC_WRITE;// 0xA0 //写块ucComMF522Buf[1]=addr;      //块地址RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if((status!= MI_OK)||(unLen != 4)||((ucComMF522Buf[0]&0x0F)!=0x0A)){status = MI_ERR;}if(status==MI_OK){for(i=0;i<16;i++)//向FIFO写16Byte数据 {    ucComMF522Buf[i]=*(p +i);   }RC522_CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);status = RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);if((status != MI_OK)||(unLen != 4)||((ucComMF522Buf[0]&0x0F)!=0x0A)){   status = MI_ERR;   }}return status;
}/*
功    能:命令卡片进入休眠状态
返    回:成功返回MI_OK
*/
char RC522_PcdHalt(void)
{u8 status;u8 unLen;u8 ucComMF522Buf[MAXRLEN]; //MAXRLEN==18status=status;ucComMF522Buf[0]=PICC_HALT;ucComMF522Buf[1]=0;RC522_CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status=RC522_PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);return MI_OK;
}/*
功    能:用MF522计算CRC16函数
参    数:*pIn :要读数CRC的数据len:-数据长度*pOut:计算的CRC结果
*/
void RC522_CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )
{u8 i,n;RC522_ClearBitMask(DivIrqReg,0x04);  //CRCIrq = 0  RC522_WriteRawRC(CommandReg,PCD_IDLE);RC522_SetBitMask(FIFOLevelReg,0x80); //清FIFO指针//向FIFO中写入数据  for(i=0;i<len;i++){  RC522_WriteRawRC(FIFODataReg,*(pIn +i));  //开始RCR计算}RC522_WriteRawRC(CommandReg,PCD_CALCCRC);   //等待CRC计算完成 i=0xFF;do {n=RC522_ReadRawRC(DivIrqReg);i--;}while((i!=0)&&!(n&0x04));//CRCIrq = 1//读取CRC计算结果 pOut[0]=RC522_ReadRawRC(CRCResultRegL);pOut[1]=RC522_ReadRawRC(CRCResultRegM);
}/*
功    能:复位RC522
返    回:成功返回MI_OK
*/
char RC522_PcdReset(void)
{RC522_RST=1;   //PF1写1RC522_Delay(10);RC522_RST=0;   //PF1清0RC522_Delay(10);RC522_RST=1;     //PF1写1RC522_Delay(10);RC522_WriteRawRC(CommandReg,PCD_RESETPHASE);  //写RC632寄存器,复位RC522_WriteRawRC(CommandReg,PCD_RESETPHASE); //写RC632寄存器,复位RC522_Delay(10);RC522_WriteRawRC(ModeReg,0x3D);             //和Mifare卡通讯,CRC初始值0x6363RC522_WriteRawRC(TReloadRegL,30);           //写RC632寄存器   RC522_WriteRawRC(TReloadRegH,0);RC522_WriteRawRC(TModeReg,0x8D);RC522_WriteRawRC(TPrescalerReg,0x3E);RC522_WriteRawRC(TxAutoReg,0x40);//必须要return MI_OK;
}/*
函数功能:设置RC632的工作方式
*/
char M500PcdConfigISOType(u8 type)
{if(type=='A')                        //ISO14443_A{ RC522_ClearBitMask(Status2Reg,0x08);     //清RC522寄存器位RC522_WriteRawRC(ModeReg,0x3D);          //3F//CRC初始值0x6363RC522_WriteRawRC(RxSelReg,0x86);         //84RC522_WriteRawRC(RFCfgReg,0x7F);         //4F  //调整卡的感应距离//RxGain = 48dB调节卡感应距离  RC522_WriteRawRC(TReloadRegL,30);        //tmoLength);// TReloadVal = 'h6a =tmoLength(dec) RC522_WriteRawRC(TReloadRegH,0);RC522_WriteRawRC(TModeReg,0x8D);RC522_WriteRawRC(TPrescalerReg,0x3E);RC522_Delay(1000);RC522_PcdAntennaOn();       //开启天线 }else return 1;       //失败,返回1return MI_OK;               //成功返回0
}/*
功    能:读RC632寄存器
参数说明:Address[IN]:寄存器地址
返    回:读出的值
*/
u8 RC522_ReadRawRC(u8 Address)
{u8 ucAddr;u8 ucResult=0;      RC522_CS=0;                        //片选选中RC522ucAddr=((Address<<1)&0x7E)|0x80;RC522_SPI_ReadWriteOneByte(ucAddr);         //发送命令ucResult=RC522_SPI_ReadWriteOneByte(0); //读取RC522返回的数据RC522_CS=1;                        //释放片选线(PF0)return ucResult;         //返回读到的数据
}/*
功    能:写RC632寄存器
参数说明:Address[IN]:寄存器地址value[IN] :写入的值
*/
void RC522_WriteRawRC(u8 Address,u8 value)
{  u8 ucAddr;RC522_CS=0; //PF0写 0 (SDA)(SPI1片选线,低电平有效)ucAddr=((Address<<1)&0x7E); RC522_SPI_ReadWriteOneByte(ucAddr); //SPI1发送一个字节RC522_SPI_ReadWriteOneByte(value);  //SPI1发送一个字节RC522_CS=1;                                             //PF1写1(SDA)(SPI1片选线)
}/*
功    能:置RC522寄存器位
参数说明:reg[IN]:寄存器地址mask[IN]:置位值
*/
void RC522_SetBitMask(u8 reg,u8 mask)
{char tmp=0x0;tmp=RC522_ReadRawRC(reg);                   //读RC632寄存器RC522_WriteRawRC(reg,tmp|mask);   //写RC632寄存器
}/*
功    能:清RC522寄存器位
参数说明:reg[IN]:寄存器地址mask[IN]:清位值
*/
void RC522_ClearBitMask(u8 reg,u8 mask)
{char tmp=0x0;tmp=RC522_ReadRawRC(reg);        //读RC632寄存器RC522_WriteRawRC(reg,tmp&~mask); // clear bit mask
} /*
功    能:通过RC522和ISO14443卡通讯
参数说明:Command[IN]:RC522命令字pIn [IN]:通过RC522发送到卡片的数据InLenByte[IN]:发送数据的字节长度pOut [OUT]:接收到的卡片返回数据*pOutLenBit[OUT]:返回数据的位长度
*/
char RC522_PcdComMF522(u8 Command,u8 *pIn,u8 InLenByte,u8 *pOut,u8 *pOutLenBit)
{char status=MI_ERR;u8 irqEn=0x00;u8 waitFor=0x00;u8 lastBits;u8 n;u16 i;switch(Command){case PCD_AUTHENT:    //验证密钥irqEn=0x12;waitFor=0x10;break;case PCD_TRANSCEIVE: //发送并接收数据irqEn=0x77;waitFor=0x30;break;default:break;}RC522_WriteRawRC(ComIEnReg,irqEn|0x80); RC522_ClearBitMask(ComIrqReg,0x80);         //清所有中断位RC522_WriteRawRC(CommandReg,PCD_IDLE);  RC522_SetBitMask(FIFOLevelReg,0x80);        //清FIFO缓存for(i=0;i<InLenByte;i++){   RC522_WriteRawRC(FIFODataReg,pIn[i]);}RC522_WriteRawRC(CommandReg,Command);   if(Command==PCD_TRANSCEIVE){  RC522_SetBitMask(BitFramingReg,0x80);   //开始传送}//有问题,下面的循环//i = 600;//根据时钟频率调整,操作M1卡最大等待时间25msi=2000;do {n=RC522_ReadRawRC(ComIrqReg);i--;}while((i!=0)&&!(n&0x01)&&!(n&waitFor));RC522_ClearBitMask(BitFramingReg,0x80);if(i!=0){    if(!(RC522_ReadRawRC(ErrorReg)&0x1B)){status=MI_OK;if(n&irqEn&0x01){status=MI_NOTAGERR;}if(Command==PCD_TRANSCEIVE){n=RC522_ReadRawRC(FIFOLevelReg);lastBits=RC522_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++){   pOut[i]=RC522_ReadRawRC(FIFODataReg);    }}}else{   status=MI_ERR;   }}RC522_SetBitMask(ControlReg,0x80);// stop timer nowRC522_WriteRawRC(CommandReg,PCD_IDLE); return status;
}/*
函数功能:开启天线
参    数:每次启动或关闭天险发射之间应至少有1ms的间隔
*/
void RC522_PcdAntennaOn(void)
{u8 i;i=RC522_ReadRawRC(TxControlReg);if(!(i&0x03)){RC522_SetBitMask(TxControlReg,0x03);}
}/*
函数功能:关闭天线
参    数:每次启动或关闭天险发射之间应至少有1ms的间隔
*/
void RC522_PcdAntennaOff(void)
{RC522_ClearBitMask(TxControlReg,0x03); //清RC522寄存器位
}

5.2 rc522.h

#ifndef RFID_RC522_H
#define RFID_RC522_H
#include "sys.h"/*
RC522射频模块外部的接口:
*1--SDA <----->PF0--片选脚
*2--SCK <----->PA5--时钟线
*3--MOSI<----->PA7--输出
*4--MISO<----->PA6--输入
*5--悬空
*6--GND <----->GND
*7--RST <----->PF1--复位脚
*8--VCC <----->VCC
*/
#define RC522_OUTPUT PAout(7)
#define RC522_INPUT PAin(6)
#define RC522_SCLK PAout(5)
#define RC522_CS PFout(0)
#define RC522_RST PFout(1)//MF522命令字
#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               //CRC计算//Mifare_One卡片命令字
#define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态,返回的是卡的类型
#define PICC_REQALL           0x52               //寻天线区内全部卡,返回的是卡的类型
#define PICC_ANTICOLL1        0x93               //防冲撞
#define PICC_ANTICOLL2        0x95               //防冲撞
#define PICC_AUTHENT1A        0x60               //验证A密钥
#define PICC_AUTHENT1B        0x61               //验证B密钥   命令认证代码
#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               //休眠//MF522 FIFO长度定义
#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
#define MAXRLEN  18//MF522寄存器定义
// PAGE 0
#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//和MF522通讯时返回的错误代码
#define     MI_OK                 0
#define     MI_NOTAGERR           1
#define     MI_ERR                2#define  SHAQU1      0X01
#define KUAI4           0X04
#define KUAI7           0X07
#define REGCARD     0xa1
#define CONSUME     0xa2
#define READCARD    0xa3
#define ADDMONEY    0xa4/*RC522各种驱动函数
*/
void RC522_Init(void);                                                                          //功    能:RC522射频卡模块初始化
void RC522_ClearBitMask(u8 reg,u8 mask);                                        //功    能:清RC522寄存器位
void RC522_WriteRawRC(u8 Address, u8 value);                                //功    能:写RC632寄存器
void RC522_SetBitMask(u8 reg,u8 mask);                                          //功    能:置RC522寄存器位
char RC522_PcdComMF522(u8 Command,u8*pIn,u8 InLenByte,u8*pOut,u8*pOutLenBit);   //功能:通过RC522和ISO14443卡通讯
void RC522_CalulateCRC(u8 *pIn,u8 len,u8 *pOut );                     //功    能:用MF522计算CRC16函数
u8 RC522_ReadRawRC(u8 Address);                                                           //功    能:读RC632寄存器char RC522_PcdReset(void);                                                                                       //功    能:复位RC522
char RC522_PcdRequest(unsigned char req_code,unsigned char *pTagType);//功    能:寻卡
void RC522_PcdAntennaOn(void);                                                                              //功    能:开启天线
void RC522_PcdAntennaOff(void);                                                                             //功    能:关闭天线
char M500PcdConfigISOType(unsigned char type);                                        //功    能:设置RC632的工作方式
char RC522_PcdAnticoll(unsigned char *pSnr);                                                    //功    能:防冲撞
char RC522_PcdSelect(unsigned char *pSnr);                                                      //功    能:选定卡片
char RC522_PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);//功    能:验证卡片密码
char RC522_PcdWrite(unsigned char addr,unsigned char *pData);                   //功    能:写数据到M1卡一块
char RC522_PcdRead(unsigned char addr,unsigned char *pData);                    //功    能:读取M1卡一块数据
char RC522_PcdHalt(void);                                                                                           //功    能:命令卡片进入休眠状态
void RC522_Reset(void);                                                                                       //功    能:复位RC522
u8 RC522_MFRC522_SelectTag(u8 *serNum);                               //功    能:读取卡存储器容量
u8 RC522_SPI_ReadWriteOneByte(u8 tx_data);
#endif

STM32+MFRC522完成IC卡号读取、密码修改、数据读写相关推荐

  1. VC如何制作用IC卡读卡器读取系统

     VC如何制作用IC卡读卡器读取系统 大型会议签到系统 运动会签到系统 记录出勤率

  2. 关于IC卡密钥理解和修改(简易篇)

    关于IC卡密钥理解和修改(简易篇) 常用的IC卡由于结构简单,使用方便,价格低,越来越受到普通应用的欢迎.本文主要描述普通IC卡的密钥相关的知识. 关于IC卡的读写,必须使用IC卡读写器, 我们推荐使 ...

  3. STM32F103:二.(6)mrc522卡号读取

    暂时只贴代码 main.c #include "public.h"int main(void) {delay_init(); //延时函数初始化 uart_init(115200) ...

  4. java如何读取ic卡_java读取IC卡设备

    有几个项目都用到IC卡设备,IC卡供应商提供的例程里没有java的例子,调试过程发现各种问题,总算是测试通过了,mark一下. 基本思路:通过JNative.jar包调用dll方式,读取IC卡的序列号 ...

  5. web调用IC卡读卡器开发第四章--读写IC卡数据

    IC卡读卡器WEB读写IC卡数据 IC卡WEB读数据 IC卡网页自动读数据 IC卡网页写数据 采用友我科技IC卡读卡器web插件可以对普通IC卡进行读和写操作,根据实际业务需求,可以手动点击读写和在w ...

  6. stm32读取目标芯片_使用stm32驱动RC522读IC卡(代码留言邮箱)

    RC522与PN532简介 关于STM32驱动方式 接线说明 程序烧录 查看卡号 总结 RC522与PN532简介 在写这篇文章之前有写过一篇有关于PN532的文章,RC522与PN532在使用上都可 ...

  7. Arduino + RFID 读取 IC 卡 Arduino uno中获得RFID的UID 并通过串口转发RFID卡号

    RFID简介:射频识别即RFID(Radio Frequency IDentification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需识别系统与特定 ...

  8. stm32驱动RFID高频读卡器读取IC卡

    stm32驱动RFID读卡器读取IC卡 1.介绍RFID 2.RFID控制指令 2.1 读IC卡号 2.2 读IC卡数据块 2.3 写数据到IC卡数据块 2.4 读取RFID读卡器用户数据 2.5 向 ...

  9. html实现读取读卡器,如何在web浏览器页面使用IC卡读卡器并且兼容所有浏览器

    随着H5技术的不断发展与推广,H5技术被广泛用于移动设备,PC终端等众多领域.同时,越来越多的应用都基于B/S(浏览器/服务器)模式,降低开发难度的同时还能更好的普及和应用,突破了硬件设备的兼容性问题 ...

  10. IC卡卡号修改软件,UID卡CUID卡物理卡号修改软件操作演示

    普通IC卡的卡号是唯一的,也是锁死的,无法修改,而UID卡和CUID卡的物理卡号是可以修改的,一些考勤等用户需要修改卡片的卡号. 一般考勤等使用的卡号是10进制的,软件支持写入10进制卡号和16进制卡 ...

最新文章

  1. 吴恩达机器学习Week4神经网络表述
  2. .NET创建WebService服务简单的例子
  3. mysql 有两种数据库引擎发音
  4. 共享数据库、独立 Schema
  5. 【教你一招】30分钟考完广开所有科目,广开期末考试网页如何多开?
  6. Nifty File Lists for Mac(文件列表创建工具)
  7. 死锁必要条件、解决死锁策略
  8. jasper 常用知识点总结
  9. UIActionSheet的最后一项点击失效
  10. zencart 对首页静态化处理
  11. tika获取压缩文件内容
  12. 如何将计算机网络作为热点,教你如何三步让笔记本电脑做wifi热点??
  13. flash游戏开发学习
  14. 系统集成(IBMS)软件的功能
  15. 开源网安实现高效、高精度的静态应用安全检测 -CodeSec
  16. 绿色花灯【热门主题】
  17. Esp8266 进阶之路36【外设篇】乐鑫esp8266芯片SDK编程驱动时间芯片 ds1302,同步网络时间到本地,再也不怕掉电断网也可以同步时间了!(附带Demo)
  18. python中的命令,python学习——python中命令行
  19. 涨知识!原来华为手机摄像头还有这些高级玩法,学会轻松提高工作效率
  20. 【枚举找规律】记一次找规律题 埃匹希斯水晶

热门文章

  1. android html5小游戏源代码下载,HTML5小游戏源代码大全
  2. 【病毒程序】发一个无聊的小病毒(无限弹窗)
  3. 坐标计算机在线使用,经纬度换算器(度分秒计算器在线使用)
  4. 闭环计算机控制系统的例子,自动控制的举例_自动控制的例子_开环和闭环自动控制系统举例...
  5. PyCharm专业版 2021.3 Anaconda安装教程
  6. vasp软件全名是什么_VaspCZ软件详细介绍
  7. 时间序列预测——ARIMA模型
  8. xps数据怎么导出为txt_如何处理XPS原始数据
  9. Java学到什么程度可以找工作?
  10. python怎么修改界面颜色_python中颜色设置