RC522通过SPI方式读写M1卡.docx
- 文档编号:5342758
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:30
- 大小:29.21KB
RC522通过SPI方式读写M1卡.docx
《RC522通过SPI方式读写M1卡.docx》由会员分享,可在线阅读,更多相关《RC522通过SPI方式读写M1卡.docx(30页珍藏版)》请在冰豆网上搜索。
RC522通过SPI方式读写M1卡
1.准备工作
战舰V3开发板,RC522模块为淘宝所买,赠送一张M1卡。
SPI方式实测可以读写。
2.RC522部分:
rc522.h:
/////////////////////////////////////////////////////////////////////
#include"sys.h"
//MF522命令字
/////////////////////////////////////////////////////////////////////
#definePCD_IDLE0x00//取消当前命令
#definePCD_AUTHENT0x0E//验证密钥
#definePCD_RECEIVE0x08//接收数据
#definePCD_TRANSMIT0x04//发送数据
#definePCD_TRANSCEIVE0x0C//发送并接收数据
#definePCD_RESETPHASE0x0F//复位
#definePCD_CALCCRC0x03//CRC计算
/////////////////////////////////////////////////////////////////////
//Mifare_One卡片命令字
/////////////////////////////////////////////////////////////////////
#definePICC_REQIDL0x26//寻天线区内未进入休眠状态
#definePICC_REQALL0x52//寻天线区内全部卡
#definePICC_ANTICOLL10x93//防冲撞
#definePICC_ANTICOLL20x95//防冲撞
#definePICC_AUTHENT1A0x60//验证A密钥
#definePICC_AUTHENT1B0x61//验证B密钥
#definePICC_READ0x30//读块
#definePICC_WRITE0xA0//写块
#definePICC_DECREMENT0xC0//扣款
#definePICC_INCREMENT0xC1//充值
#definePICC_RESTORE0xC2//调块数据到缓冲区
#definePICC_TRANSFER0xB0//保存缓冲区中数据
#definePICC_HALT0x50//休眠
/////////////////////////////////////////////////////////////////////
//MF522FIFO长度定义
/////////////////////////////////////////////////////////////////////
#defineDEF_FIFO_LENGTH64//FIFOsize=64byte
#defineMAXRLEN18
/////////////////////////////////////////////////////////////////////
//MF522寄存器定义
/////////////////////////////////////////////////////////////////////
//PAGE0
#defineRFU000x00
#defineCommandReg0x01
#defineComIEnReg0x02
#defineDivlEnReg0x03
#defineComIrqReg0x04
#defineDivIrqReg0x05
#defineErrorReg0x06
#defineStatus1Reg0x07
#defineStatus2Reg0x08
#defineFIFODataReg0x09
#defineFIFOLevelReg0x0A
#defineWaterLevelReg0x0B
#defineControlReg0x0C
#defineBitFramingReg0x0D
#defineCollReg0x0E
#defineRFU0F0x0F
//PAGE1
#defineRFU100x10
#defineModeReg0x11
#defineTxModeReg0x12
#defineRxModeReg0x13
#defineTxControlReg0x14
#defineTxAutoReg0x15
#defineTxSelReg0x16
#defineRxSelReg0x17
#defineRxThresholdReg0x18
#defineDemodReg0x19
#defineRFU1A0x1A
#defineRFU1B0x1B
#defineMifareReg0x1C
#defineRFU1D0x1D
#defineRFU1E0x1E
#defineSerialSpeedReg0x1F
//PAGE2
#defineRFU200x20
#defineCRCResultRegM0x21
#defineCRCResultRegL0x22
#defineRFU230x23
#defineModWidthReg0x24
#defineRFU250x25
#defineRFCfgReg0x26
#defineGsNReg0x27
#defineCWGsCfgReg0x28
#defineModGsCfgReg0x29
#defineTModeReg0x2A
#defineTPrescalerReg0x2B
#defineTReloadRegH0x2C
#defineTReloadRegL0x2D
#defineTCounterValueRegH0x2E
#defineTCounterValueRegL0x2F
//PAGE3
#defineRFU300x30
#defineTestSel1Reg0x31
#defineTestSel2Reg0x32
#defineTestPinEnReg0x33
#defineTestPinValueReg0x34
#defineTestBusReg0x35
#defineAutoTestReg0x36
#defineVersionReg0x37
#defineAnalogTestReg0x38
#defineTestDAC1Reg0x39
#defineTestDAC2Reg0x3A
#defineTestADCReg0x3B
#defineRFU3C0x3C
#defineRFU3D0x3D
#defineRFU3E0x3E
#defineRFU3F0x3F
/////////////////////////////////////////////////////////////////////
//和MF522通讯时返回的错误代码
/////////////////////////////////////////////////////////////////////
#defineMI_OK0
#defineMI_NOTAGERR
(1)
#defineMI_ERR
(2)
#defineSHAQU10X01
#defineKUAI40X04
#defineKUAI70X07
#defineREGCARD0xa1
#defineCONSUME0xa2
#defineREADCARD0xa3
#defineADDMONEY0xa4
#defineSPIReadByte()SPIWriteByte(0)
u8SPIWriteByte(u8byte);
voidSPI2_Init(void);
#defineSET_SPI_CSGPIO_SetBits(GPIOF,GPIO_Pin_0);
#defineCLR_SPI_CSGPIO_ResetBits(GPIOF,GPIO_Pin_0)
#defineSET_RC522RSTGPIO_SetBits(GPIOF,GPIO_Pin_1);
#defineCLR_RC522RSTGPIO_ResetBits(GPIOF,GPIO_Pin_1)
voidInitRc522(void);
voidUsart1_Send_String(unsignedchar*str);
voidClearBitMask(u8reg,u8mask);
voidWriteRawRC(u8Address,u8value);
voidSetBitMask(u8reg,u8mask);
charPcdComMF522(u8Command,
u8*pIn,
u8InLenByte,
u8*pOut,
u8*pOutLenBit);
voidCalulateCRC(u8*pIn,u8len,u8*pOut);
u8ReadRawRC(u8Address);
voidPcdAntennaOn(void);
charPcdReset(void);
charPcdRequest(unsignedcharreq_code,unsignedchar*pTagType);
voidPcdAntennaOn(void);
voidPcdAntennaOff(void);
charM500PcdConfigISOType(unsignedchartype);
charPcdAnticoll(unsignedchar*pSnr);
charPcdSelect(unsignedchar*pSnr);
charPcdAuthState(unsignedcharauth_mode,unsignedcharaddr,unsignedchar*pKey,unsignedchar*pSnr);
charPcdWrite(unsignedcharaddr,unsignedchar*pData);
charPcdRead(unsignedcharaddr,unsignedchar*pData);
charPcdHalt(void);
voidReset_RC522(void);
charPcdValue(u8dd_mode,u8addr,u8*pValue);
//////////////////////////////////////////////////////////////////////////////////////////////////////
rc522.c:
#include"sys.h"
#include"rc522.h"
#include"delay.h"
voiddelay_ns(u32ns)
{
u32i;
for(i=0;i { __nop(); __nop(); __nop(); } } u8SPIWriteByte(u8Byte) { 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); returnSPI_I2S_ReceiveData(SPI2); } //SPIx读写一个字节 //TxData: 要写入的字节 //返回值: 读取到的字节 u8SPI2_ReadWriteByte(u8TxData) { u8retry=0; while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET)//检查指定的SPI标志位设置与否: 发送缓存空标志位 { retry++; if(retry>200)return0; } SPI_I2S_SendData(SPI2,TxData);//通过外设SPIx发送一个数据 retry=0; while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET)//检查指定的SPI标志位设置与否: 接受缓存非空标志位 { retry++; if(retry>200)return0; } returnSPI_I2S_ReceiveData(SPI2);//返回通过SPIx最近接收的数据 } voidSPI2_Init(void) { GPIO_InitTypeDefGPIO_InitStructure; SPI_InitTypeDefSPI_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);//启动传输 } voidInitRc522(void) { SPI2_Init(); PcdReset(); PcdAntennaOff(); delay_ms (2); PcdAntennaOn(); M500PcdConfigISOType('A'); } voidReset_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 ///////////////////////////////////////////////////////////////////// charPcdRequest(u8req_code,u8*pTagType) { charstatus; u8unLen; u8ucComMF522Buf[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;} returnstatus; } ///////////////////////////////////////////////////////////////////// //功能: 防冲撞 //参数说明: pSnr[OUT]: 卡片序列号,4字节 //返回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// charPcdAnticoll(u8*pSnr) { charstatus; u8i,snr_check=0; u8unLen; u8ucComMF522Buf[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); returnstatus; } ///////////////////////////////////////////////////////////////////// //功能: 选定卡片 //参数说明: pSnr[IN]: 卡片序列号,4字节 //返回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// charPcdSelect(u8*pSnr) { charstatus; u8i; u8unLen; u8ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0]=PICC_ANTICOLL1; ucComMF522Buf[1]=0x70; ucComMF522Buf[6]=0; for(i=0;i<4;i++) { ucComMF522Buf[i+2]=*(pSnr+i); ucComM
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- RC522 通过 SPI 方式 读写 M1