RC522通过SPI方式读写M1卡
更新时间:2024-04-14 18:48: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卡04-14
魏晋南北朝诗歌11-03
货物贸易关系实证研究论文05-01
2020年季度思想汇报精选5篇09-12
苏教版七年级数学教案05-13
人教版三年级上册语文期中试卷405-14
30亿资金的操盘手对缠论的理解05-26
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 读写
- 通过
- 方式
- RC522
- SPI