RC522通过SPI方式读写M1卡
更新时间:2024-01-24 12:58:01 阅读量: 教育文库 文档下载
1.准备工作
战舰V3开发板,RC522模块为淘宝所买,赠送一张M1卡。SPI方式实测可以读写。
2.RC522部分: rc522.h:
///////////////////////////////////////////////////////////////////// #include \
//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 #define #define #define #define #define #define #define #define // PAGE 1 #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define // PAGE 2 #define #define #define #define #define #define #define #define Status1Reg Status2Reg FIFODataReg FIFOLevelReg WaterLevelReg ControlReg BitFramingReg CollReg RFU0F
RFU10 ModeReg TxModeReg RxModeReg TxControlReg TxAutoReg TxSelReg RxSelReg RxThresholdReg DemodReg RFU1A RFU1B MifareReg RFU1D RFU1E SerialSpeedReg
RFU20 CRCResultRegM CRCResultRegL RFU23 ModWidthReg RFU25 RFCfgReg GsNReg 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x20 0x21 0x22 0x23 0x24 0x25 0x26 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
#define SPIReadByte() SPIWriteByte(0) u8 SPIWriteByte(u8 byte); void SPI2_Init(void);
#define SET_SPI_CS GPIO_SetBits(GPIOF,GPIO_Pin_0); #define CLR_SPI_CS GPIO_ResetBits(GPIOF,GPIO_Pin_0)
#define SET_RC522RST GPIO_SetBits(GPIOF,GPIO_Pin_1); #define CLR_RC522RST GPIO_ResetBits(GPIOF,GPIO_Pin_1)
void InitRc522(void);
void Usart1_Send_String(unsigned char *str); void ClearBitMask(u8 reg,u8 mask); void WriteRawRC(u8 Address, u8 value); void SetBitMask(u8 reg,u8 mask); char PcdComMF522(u8 Command, u8 *pIn ,
u8 InLenByte, u8 *pOut ,
u8 *pOutLenBit);
void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ); u8 ReadRawRC(u8 Address); void PcdAntennaOn(void);
char PcdReset(void);
char PcdRequest(unsigned char req_code,unsigned char *pTagType); void PcdAntennaOn(void); void PcdAntennaOff(void);
char M500PcdConfigISOType(unsigned char type); 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 PcdWrite(unsigned char addr,unsigned char *pData); char PcdRead(unsigned char addr,unsigned char *pData); char PcdHalt(void);
void Reset_RC522(void);
char PcdValue(u8 dd_mode,u8 addr,u8 *pValue);
//////////////////////////////////////////////////////////////////////////////////////////////////////
rc522.c:
#include \#include \#include \
void delay_ns(u32 ns) {
u32 i;
for(i=0;i __nop(); __nop(); __nop(); } } u8 SPIWriteByte(u8 Byte) { while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI2, Byte); while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI2); } //SPIx 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPI2_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位 { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据 retry=0; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 } void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE );//PORTB时钟使能 RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //IO-->PF0、PF1 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOF, &GPIO_InitStructure); //根据设定参数初始化PF0、PF1 GPIO_ResetBits(GPIOF,GPIO_Pin_1); //PF1输出低 //GPIO_SetBits(GPIOF,GPIO_Pin_0); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 //SPI2_ReadWriteByte(0xff);//启动传输 } void InitRc522(void) { SPI2_Init(); PcdReset(); PcdAntennaOff(); delay_ms(2); PcdAntennaOn(); M500PcdConfigISOType( 'A' ); } void Reset_RC522(void) { PcdReset(); PcdAntennaOff(); delay_ms(2); PcdAntennaOn(); } ///////////////////////////////////////////////////////////////////// //功 能:寻卡 //参数说明: 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(u8 req_code,u8 *pTagType) { char status; u8 unLen; u8 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; } ///////////////////////////////////////////////////////////////////// //功 能:防冲撞 //参数说明: pSnr[OUT]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdAnticoll(u8 *pSnr) { char status; u8 i,snr_check=0; u8 unLen; u8 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 ///////////////////////////////////////////////////////////////////// char 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); } 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; } ///////////////////////////////////////////////////////////////////// //功 能:验证卡片密码 //参数说明: auth_mode[IN]: 密码验证模式 // 0x60 = 验证A密钥 // 0x61 = 验证B密钥 // addr[IN]:块地址 // pKey[IN]:密码 // pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr) { char status; u8 unLen; u8 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; } ///////////////////////////////////////////////////////////////////// //功 能:读取M1卡一块数据 //参数说明: addr[IN]:块地址 // p [OUT]:读出的数据,16字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdRead(u8 addr,u8 *p ) { char status; u8 unLen; u8 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(p , ucComMF522Buf, 16); } { for (i=0; i<16; i++) { *(p +i) = ucComMF522Buf[i]; } } else { status = MI_ERR; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:写数据到M1卡一块 //参数说明: addr[IN]:块地址 // p [IN]:写入的数据,16字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdWrite(u8 addr,u8 *p ) { char status; u8 unLen; u8 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, p , 16); for (i=0; i<16; i++) { ucComMF522Buf[i] = *(p +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; } ///////////////////////////////////////////////////////////////////// //功 能:命令卡片进入休眠状态 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdHalt(void) { u8 status; u8 unLen; u8 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; } ///////////////////////////////////////////////////////////////////// //用MF522计算CRC16函数 ///////////////////////////////////////////////////////////////////// void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ) { u8 i,n; ClearBitMask(DivIrqReg,0x04); WriteRawRC(CommandReg,PCD_IDLE); SetBitMask(FIFOLevelReg,0x80); for (i=0; i { WriteRawRC(FIFODataReg, *(pIn +i)); } WriteRawRC(CommandReg, PCD_CALCCRC); i = 0xFF; do { n = ReadRawRC(DivIrqReg); i--; } while ((i!=0) && !(n&0x04)); pOut [0] = ReadRawRC(CRCResultRegL); pOut [1] = ReadRawRC(CRCResultRegM); } ///////////////////////////////////////////////////////////////////// //功 能:复位RC522 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdReset(void) { //PORTD|=(1< WriteRawRC(CommandReg,PCD_RESETPHASE); WriteRawRC(CommandReg,PCD_RESETPHASE); delay_ns(10); WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363 WriteRawRC(TReloadRegL,30); WriteRawRC(TReloadRegH,0); WriteRawRC(TModeReg,0x8D); WriteRawRC(TPrescalerReg,0x3E); WriteRawRC(TxAutoReg,0x40);//必须要 return MI_OK; } ////////////////////////////////////////////////////////////////////// //设置RC632的工作方式 ////////////////////////////////////////////////////////////////////// char M500PcdConfigISOType(u8 type) { if (type == 'A') //ISO14443_A { ClearBitMask(Status2Reg,0x08); WriteRawRC(ModeReg,0x3D);//3F 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); delay_ns(1000); PcdAntennaOn(); } else{ return 1; } return MI_OK; } ///////////////////////////////////////////////////////////////////// //功 能:读RC632寄存器 //参数说明:Address[IN]:寄存器地址 //返 回:读出的值 ///////////////////////////////////////////////////////////////////// u8 ReadRawRC(u8 Address) { u8 ucAddr; u8 ucResult=0; CLR_SPI_CS; ucAddr = ((Address<<1)&0x7E)|0x80; SPIWriteByte(ucAddr); delay_ms(5); ucResult=SPIReadByte(); delay_ms(5); SET_SPI_CS; return ucResult; } ///////////////////////////////////////////////////////////////////// //功 能:写RC632寄存器 //参数说明:Address[IN]:寄存器地址 // value[IN]:写入的值 ///////////////////////////////////////////////////////////////////// void WriteRawRC(u8 Address, u8 value) { u8 ucAddr; // u8 tmp; CLR_SPI_CS; ucAddr = ((Address<<1)&0x7E); SPIWriteByte(ucAddr); delay_ms(5); SPIWriteByte(value); delay_ms(5); SET_SPI_CS; // tmp=ReadRawRC(Address); // // if(value!=tmp) // printf(\} ///////////////////////////////////////////////////////////////////// //功 能:置RC522寄存器位 //参数说明:reg[IN]:寄存器地址 // mask[IN]:置位值 ///////////////////////////////////////////////////////////////////// void SetBitMask(u8 reg,u8 mask) { char tmp = 0x0; tmp = ReadRawRC(reg); WriteRawRC(reg,tmp | mask); // set bit mask } ///////////////////////////////////////////////////////////////////// //功 能:清RC522寄存器位 //参数说明:reg[IN]:寄存器地址 // mask[IN]:清位值 ///////////////////////////////////////////////////////////////////// void ClearBitMask(u8 reg,u8 mask) { char tmp = 0x0; tmp = ReadRawRC(reg); WriteRawRC(reg, tmp & ~mask); // clear bit mask } ///////////////////////////////////////////////////////////////////// //功 能:通过RC522和ISO14443卡通讯 //参数说明:Command[IN]:RC522命令字 // pIn [IN]:通过RC522发送到卡片的数据 // InLenByte[IN]:发送数据的字节长度 // pOut [OUT]:接收到的卡片返回数据 // *pOutLenBit[OUT]:返回数据的位长度 ///////////////////////////////////////////////////////////////////// char 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; } WriteRawRC(ComIEnReg,irqEn|0x80); ClearBitMask(ComIrqReg,0x80); //清所有中断位 WriteRawRC(CommandReg,PCD_IDLE); SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存 for (i=0; i { WriteRawRC(FIFODataReg, pIn [i]); } WriteRawRC(CommandReg, Command); // n = ReadRawRC(CommandReg); if (Command == PCD_TRANSCEIVE) { SetBitMask(BitFramingReg,0x80); } //开始传送 //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms 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 { pOut [i] = ReadRawRC(FIFODataReg); } } } else { status = MI_ERR; } } SetBitMask(ControlReg,0x80); // stop timer now WriteRawRC(CommandReg,PCD_IDLE); return status; } ///////////////////////////////////////////////////////////////////// //开启天线 //每次启动或关闭天险发射之间应至少有1ms的间隔 ///////////////////////////////////////////////////////////////////// void PcdAntennaOn(void) { u8 i; i = ReadRawRC(TxControlReg); if (!(i & 0x03)) { SetBitMask(TxControlReg, 0x03); } } ///////////////////////////////////////////////////////////////////// //关闭天线 ///////////////////////////////////////////////////////////////////// void PcdAntennaOff(void) { ClearBitMask(TxControlReg, 0x03); } ///////////////////////////////////////////////////////////////////// //功 能:扣款和充值 //参数说明: dd_mode[IN]:命令字 // 0xC0 = 扣款 // 0xC1 = 充值 // addr[IN]:钱包地址 // pValue[IN]:4字节增(减)值,低位在前 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// char PcdValue(u8 dd_mode,u8 addr,u8 *pValue) { char status; u8 unLen; u8 ucComMF522Buf[MAXRLEN]; //u8 i; 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; } = = 3.usart部分 用的串口1,打印读写数据到串口调试助手,hex_to_str函数为16进制转换为字符格式,可以不转换,直接串口打印数据,串口调试助手需要勾选hex。 4.main函 #include \#include \#include \#include \#include \ /* CS(SDA)--PF0 RST------PF1 CLK------PB13 MOSI-----PB15 MISO-----PB14 3.3V-----3.3V GND------GND */ u8 status; u8 CT[2]; u8 SN[4]; u8 RFID[16]; u8 RFID1[16]; u8 RFID2[16]; u8 temp[20]; u8 v[4]; u8 KEY[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; u8 money[16]={0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0X04,0XFB,0X04,0XFB}; /*0-3 :金额 4-7 :金额取反 8-11 :备份金额 12-15 :地址 地址取反 地址 地址取反 */ u8 CardStyle[16]={\ u8 CardNumber[16]={%u8 M1S50[]={%u8 M1S70[]={\ u8 Mifare_Pro[]={%u8 SOK[]={%u8 CardReady[]={%u8 Password[]={%u8 Clear4Zero[]={%u8 Block7[]={%u8 Add5[]={\ u8 Block4Money[]={%u8 Inc[]={0x01}; u8 dst[5]; int main(void) { delay_init(); uart_init(921600); InitRc522(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); while(1) { status = PcdRequest(PICC_REQALL,CT);// if(status==MI_OK)// { Usart1_Send_String(CardReady); usart_send_byte( '\\n'); Usart1_Send_String(CardStyle); hex_to_str(CT,sizeof(CT));// switch (CT[0]) { case 0x04:Usart1_Send_String(M1S50);break; case 0x02:Usart1_Send_String(M1S70);break; case 0x08:Usart1_Send_String(Mifare_Pro);break; } status=MI_ERR; status = PcdAnticoll(SN);// } if(status==MI_OK)// { Usart1_Send_String(CardNumber); hex_to_str(SN,sizeof(SN));// status=MI_ERR; status =PcdSelect(SN);// } if(status==MI_OK)// { Usart1_Send_String(SOK); status=MI_ERR; status =PcdAuthState(0x61,0x04,KEY,SN);// } if(status==MI_OK)// { Usart1_Send_String(Password); status=MI_ERR; status=PcdRead(7,RFID); delay_ms(100); } if(status==MI_OK) { v[0]=0x05;v[1]=0;v[2]=0;v[3]=0; Usart1_Send_String(Block7); usart_send_byte( '\\n');//next line hex_to_str(RFID,sizeof(RFID));// PcdWrite(4,money);// Usart1_Send_String(Clear4Zero); PcdRead(4,RFID1);/////// hex_to_str(RFID1,sizeof(RFID1)); usart_send_byte('\\n'); Usart1_Send_String(Add5);//money increase 5 PcdValue(0xC1,4,v);// Usart1_Send_String(Block4Money); PcdRead(4,RFID2);// hex_to_str(RFID2,sizeof(RFID2)); PcdHalt();// } } } 5.结果
正在阅读:
RC522通过SPI方式读写M1卡01-24
浅析大学生“村官”计划长效机制的构建-2019年精选文档01-02
会展旅游01-15
消防工程安装人工费单包工合同.03-08
教牧辅导学05-06
祝福语,公司02-24
煤矿安全生产建言献策征文08-25
关于我省推动文旅融合发展的调研报告04-25
华医网 继续教育 项目学习 临床护理教学实践探讨 答案03-25
企划文案市粮食局工作要点计划12-05
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 读写
- 通过
- 方式
- RC522
- SPI
- 晓坝镇“三务公开”开展情况报告
- 科技成果转化说明1
- 计算机网络故障诊断与排除(第2版)教学资料补充习题
- 权保护执行分配中优先权冲突下的工资债
- 土木工程毕业设计计算书最新(4)
- 四川2015安装定额说明 - 图文
- 2014届山东省高考压轴卷语文试题及答案
- 培训游戏大全-HR猫猫
- 承压水突涌计算
- 专题3 导数-2014届高三名校数学(理)试题解析分项汇编
- 关于landsat数据去条带的ENVI处理
- XX公园—特许经营协议
- 冲渣水泵工
- AC11牵引箱检修-V1.1分析
- 预防接种工作规范培训试题
- 必修三 物质循环和能量流动
- 众包的经济学思考
- 综合教程(第六册)教师用书
- 工具式卸料平台施工方案
- DB510100T 088-2012成都市建筑消防设施及电气防火检测规范