
STM32 + RC522(SPI2 和 模拟SPI)
一. STM32 + RC522(SPI2 模式)
1. 头文件: rc522.h
#include "stm32f10x.h"
/////////////////////////////////////////////////////////////////////
//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 //
//#define spi_cs 1;
//sbit spi_ck=P0^6;
//sbit spi_mosi=P0^7;
//sbit spi_miso=P4^1;
//sbit spi_rst=P2^7;
#define SPIReadByte() SPIWriteByte(0)
u8 SPIWriteByte(u8 byte);
void SPI2_Init(void); #define SET_SPI_CS (GPIOF->BSRR=0X01)
#define CLR_SPI_CS (GPIOF->BRR=0X01) #define SET_RC522RST GPIOF->BSRR=0X02
#define CLR_RC522RST GPIOF->BRR=0X02
void InitRc522(void);
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);
char PcdBakValue(u8 sourceaddr, u8 goaladdr);
2. C文件:rc522.c
#include "sys.h"
#include "rc522.h"
#include "delay.h" void delay_ns(u32 ns)
{
u32 i;
for(i=;i<ns;i++)
{
__nop();
__nop();
__nop();
}
} u8 SPIWriteByte(u8 Byte)
{
while((SPI2->SR&0X02)==); //等待发送区空
SPI2->DR=Byte; //发送一个byte
while((SPI2->SR&0X01)==); //等待接收完一个byte
return SPI2->DR; //返回收到的数据
} //SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 retry=;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>)return ;
}
SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
retry=; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>)return ;
}
return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
} //SPI 速度设置函数
//SpeedSet:
//SPI_BaudRatePrescaler_2 2分频
//SPI_BaudRatePrescaler_8 8分频
//SPI_BaudRatePrescaler_16 16分频
//SPI_BaudRatePrescaler_256 256分频 void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI2->CR1&=0XFFC7;
SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI2速度
SPI_Cmd(SPI2,ENABLE); } 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_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = ; //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();
PcdAntennaOn();
M500PcdConfigISOType( 'A' );
}
void Reset_RC522(void)
{
PcdReset();
PcdAntennaOff();
delay_ms();
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[] = req_code; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[];
*(pTagType+) = ucComMF522Buf[];
}
else
{ status = MI_ERR; } return status;
} /////////////////////////////////////////////////////////////////////
//功 能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(u8 *pSnr)
{
char status;
u8 i,snr_check=;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80); ucComMF522Buf[] = PICC_ANTICOLL1;
ucComMF522Buf[] = 0x20; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if (status == MI_OK)
{
for (i=; i<; 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[] = PICC_ANTICOLL1;
ucComMF522Buf[] = 0x70;
ucComMF522Buf[] = ;
for (i=; i<; i++)
{
ucComMF522Buf[i+] = *(pSnr+i);
ucComMF522Buf[] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); ClearBitMask(Status2Reg,0x08); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,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[] = auth_mode;
ucComMF522Buf[] = 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[], pKey, );
memcpy(&ucComMF522Buf[], pSnr, ); status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,,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[] = PICC_READ;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
// { memcpy(p , ucComMF522Buf, 16); }
{
for (i=; i<; 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[] = PICC_WRITE;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
//memcpy(ucComMF522Buf, p , 16);
for (i=; i<; i++)
{
ucComMF522Buf[i] = *(p +i);
}
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; }
} return status;
} /////////////////////////////////////////////////////////////////////
//功 能:命令卡片进入休眠状态
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
u8 status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_HALT;
ucComMF522Buf[] = ;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,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=; i<len; i++)
{ WriteRawRC(FIFODataReg, *(pIn +i)); }
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!=) && !(n&0x04));
pOut [] = ReadRawRC(CRCResultRegL);
pOut [] = ReadRawRC(CRCResultRegM);
} /////////////////////////////////////////////////////////////////////
//功 能:复位RC522
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
//PORTD|=(1<<RC522RST);
SET_RC522RST;
delay_ns();
//PORTD&=~(1<<RC522RST);
CLR_RC522RST;
delay_ns();
//PORTD|=(1<<RC522RST);
SET_RC522RST;
delay_ns();
WriteRawRC(CommandReg,PCD_RESETPHASE);
WriteRawRC(CommandReg,PCD_RESETPHASE);
delay_ns(); WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(TReloadRegL,);
WriteRawRC(TReloadRegH,);
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);//
WriteRawRC(RFCfgReg,0x7F); //4F
WriteRawRC(TReloadRegL,);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
WriteRawRC(TReloadRegH,);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
delay_ns();
PcdAntennaOn();
}
else{ return ; } return MI_OK;
}
/////////////////////////////////////////////////////////////////////
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/////////////////////////////////////////////////////////////////////
u8 ReadRawRC(u8 Address)
{
u8 ucAddr;
u8 ucResult=;
CLR_SPI_CS;
ucAddr = ((Address<<)&0x7E)|0x80; SPIWriteByte(ucAddr);
ucResult=SPIReadByte();
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<<)&0x7E); SPIWriteByte(ucAddr);
SPIWriteByte(value);
SET_SPI_CS; // tmp=ReadRawRC(Address);
//
// if(value!=tmp)
// printf("wrong\n");
}
/////////////////////////////////////////////////////////////////////
//功 能:置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=; i<InLenByte; i++)
{ WriteRawRC(FIFODataReg, pIn [i]); }
WriteRawRC(CommandReg, Command);
// n = ReadRawRC(CommandReg); if (Command == PCD_TRANSCEIVE)
{ SetBitMask(BitFramingReg,0x80); } //开始传送 //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
i = ;
do
{
n = ReadRawRC(ComIrqReg);
i--;
}
while ((i!=) && !(n&0x01) && !(n&waitFor));
ClearBitMask(BitFramingReg,0x80); if (i!=)
{
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-)* + lastBits; }
else
{ *pOutLenBit = n*; }
if (n == )
{ n = ; }
if (n > MAXRLEN)
{ n = MAXRLEN; }
for (i=; i<n; 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[] = dd_mode;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
memcpy(ucComMF522Buf, pValue, );
//for (i=0; i<16; i++)
//{ ucComMF522Buf[i] = *(pValue+i); }
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]);
unLen = ;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
} if (status == MI_OK)
{
ucComMF522Buf[] = PICC_TRANSFER;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
} /////////////////////////////////////////////////////////////////////
//功 能:备份钱包
//参数说明: sourceaddr[IN]:源地址
// goaladdr[IN]:目标地址
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdBakValue(u8 sourceaddr, u8 goaladdr)
{
char status;
u8 unLen;
u8 ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_RESTORE;
ucComMF522Buf[] = sourceaddr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
} if (status != MI_OK)
{ return MI_ERR; } ucComMF522Buf[] = PICC_TRANSFER;
ucComMF522Buf[] = goaladdr; CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } return status;
}
一. STM32 + RC522(模拟SPI 模式)
1. 头文件: rc522.h
#ifndef _RC522_H
#define _RC522_H
#include "sys.h"
#include "delay.h" /////////////////////////////////////////////////////////////////////
//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 /////////////////////////////////////////////////////////////////////
//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 MF522_NSS PFout(0) //PF0 SDA
#define MF522_SCK PFout(1) //PF1
#define MF522_SI PFout(2) //PF2
#define MF522_SO PFin(3) //PF3
#define MF522_RST PFout(4) //PF4 /////////////////////////////////////////////////////////////////////
//函数原型
/////////////////////////////////////////////////////////////////////
char PcdReset(void);
void PcdAntennaOn(void);
void PcdAntennaOff(void);
char PcdRequest(unsigned char req_code,unsigned char *pTagType);
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 PcdRead(unsigned char addr,unsigned char *pData);
char PcdWrite(unsigned char addr,unsigned char *pData);
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);
char PcdHalt(void);
char PcdComMF522(unsigned char Command,
unsigned char *pInData,
unsigned char InLenByte,
unsigned char *pOutData,
unsigned int *pOutLenBit);
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);
void WriteRawRC(unsigned char Address,unsigned char value);
unsigned char ReadRawRC(unsigned char Address);
void SetBitMask(unsigned char reg,unsigned char mask);
void ClearBitMask(unsigned char reg,unsigned char mask);
void RC522_Init(void);
#endif
2. C文件:rc522.c
#include "RC522.h" #define MAXRLEN 18 void RC522_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能PF端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4); //拉高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOF, &GPIO_InitStructure);
} /////////////////////////////////////////////////////////////////////
//功 能:寻卡
//参数说明: 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)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
SetBitMask(TxControlReg,0x03); ucComMF522Buf[] = req_code; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[];
*(pTagType+) = ucComMF522Buf[];
}
else
{ status = MI_ERR;
} return status;
} /////////////////////////////////////////////////////////////////////
//功 能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80); ucComMF522Buf[] = PICC_ANTICOLL1;
ucComMF522Buf[] = 0x20; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if (status == MI_OK)
{
for (i=; i<; 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(unsigned char *pSnr)
{
char status;
unsigned char i;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_ANTICOLL1;
ucComMF522Buf[] = 0x70;
ucComMF522Buf[] = ;
for (i=; i<; i++)
{
ucComMF522Buf[i+] = *(pSnr+i);
ucComMF522Buf[] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); ClearBitMask(Status2Reg,0x08); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,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(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = auth_mode;
ucComMF522Buf[] = addr;
for (i=; i<; i++)
{ ucComMF522Buf[i+] = *(pKey+i); }
for (i=; i<; i++)
{ ucComMF522Buf[i+] = *(pSnr+i); }
// memcpy(&ucComMF522Buf[2], pKey, 6);
// memcpy(&ucComMF522Buf[8], pSnr, 4); status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; } return status;
} /////////////////////////////////////////////////////////////////////
//功 能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// pData[OUT]:读出的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRead(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_READ;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
// { memcpy(pData, ucComMF522Buf, 16); }
{
for (i=; i<; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; } return status;
} /////////////////////////////////////////////////////////////////////
//功 能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// pData[IN]:写入的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdWrite(unsigned char addr,unsigned char *pData)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_WRITE;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
//memcpy(ucComMF522Buf, pData, 16);
for (i=; i<; i++)
{ ucComMF522Buf[i] = *(pData+i); }
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; }
} return status;
} /////////////////////////////////////////////////////////////////////
//功 能:扣款和充值
//参数说明: dd_mode[IN]:命令字
// 0xC0 = 扣款
// 0xC1 = 充值
// addr[IN]:钱包地址
// pValue[IN]:4字节增(减)值,低位在前
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)
{
char status;
unsigned int unLen;
unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = dd_mode;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
// memcpy(ucComMF522Buf, pValue, 4);
for (i=; i<; i++)
{ ucComMF522Buf[i] = *(pValue+i); }
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]);
unLen = ;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
} if (status == MI_OK)
{
ucComMF522Buf[] = PICC_TRANSFER;
ucComMF522Buf[] = addr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; }
}
return status;
} /////////////////////////////////////////////////////////////////////
//功 能:备份钱包
//参数说明: sourceaddr[IN]:源地址
// goaladdr[IN]:目标地址
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_RESTORE;
ucComMF522Buf[] = sourceaddr;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } if (status == MI_OK)
{
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
ucComMF522Buf[] = ;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen);
if (status != MI_ERR)
{ status = MI_OK; }
} if (status != MI_OK)
{ return MI_ERR; } ucComMF522Buf[] = PICC_TRANSFER;
ucComMF522Buf[] = goaladdr; CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); if ((status != MI_OK) || (unLen != ) || ((ucComMF522Buf[] & 0x0F) != 0x0A))
{ status = MI_ERR; } return status;
} /////////////////////////////////////////////////////////////////////
//功 能:命令卡片进入休眠状态
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[] = PICC_HALT;
ucComMF522Buf[] = ;
CalulateCRC(ucComMF522Buf,,&ucComMF522Buf[]); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,,ucComMF522Buf,&unLen); return MI_OK;
} /////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
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=; i<len; i++)
{ WriteRawRC(FIFODataReg, *(pIndata+i)); }
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!=) && !(n&0x04));
pOutData[] = ReadRawRC(CRCResultRegL);
pOutData[] = ReadRawRC(CRCResultRegM);
} /////////////////////////////////////////////////////////////////////
//功 能:复位RC522
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
//unsigned char i;
MF522_RST=; delay_us(); MF522_RST=; delay_us(); MF522_RST=; delay_us(); WriteRawRC(CommandReg,PCD_RESETPHASE); delay_us(); WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(TReloadRegL,);
WriteRawRC(TReloadRegH,);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
WriteRawRC(TxAutoReg,0x40);
return MI_OK;
} /////////////////////////////////////////////////////////////////////
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
unsigned char i, ucAddr;
unsigned char ucResult=; MF522_SCK = ;
MF522_NSS = ;
ucAddr = ((Address<<)&0x7E)|0x80; for(i=;i>;i--)
{
MF522_SI = ((ucAddr&0x80)==0x80);
MF522_SCK = ;
ucAddr <<= ;
MF522_SCK = ;
delay_us(); //STM32需要多加的延时时间。51的不需要加
} for(i=;i>;i--)
{
MF522_SCK = ;
ucResult <<= ;
ucResult|=MF522_SO;
MF522_SCK = ;
delay_us(); //STM32需要多加的延时时间。51的不需要加
} MF522_NSS = ;
MF522_SCK = ;
return ucResult;
} /////////////////////////////////////////////////////////////////////
//功 能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
unsigned char i, ucAddr; MF522_SCK = ;
MF522_NSS = ;
ucAddr = ((Address<<)&0x7E); for(i=;i>;i--)
{
MF522_SI = ((ucAddr&0x80)==0x80);
MF522_SCK = ;
ucAddr <<= ;
MF522_SCK = ;
delay_us(); //STM32需要多加的延时时间。51的不需要加
} for(i=;i>;i--)
{
MF522_SI = ((value&0x80)==0x80);
MF522_SCK = ;
value <<= ;
MF522_SCK = ;
delay_us(); //STM32需要多加的延时时间。51的不需要加
}
MF522_NSS = ;
MF522_SCK = ;
} /////////////////////////////////////////////////////////////////////
//功 能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
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]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0;
tmp = ReadRawRC(reg);
WriteRawRC(reg, tmp & ~mask); // clear bit mask
} /////////////////////////////////////////////////////////////////////
//功 能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
// pInData[IN]:通过RC522发送到卡片的数据
// InLenByte[IN]:发送数据的字节长度
// pOutData[OUT]:接收到的卡片返回数据
// *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command,
unsigned char *pInData,
unsigned char InLenByte,
unsigned char *pOutData,
unsigned int *pOutLenBit)
{
char status = MI_ERR;
unsigned char irqEn = 0x00;
unsigned char waitFor = 0x00;
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;
break;
default:
break;
} WriteRawRC(ComIEnReg,irqEn|0x80);
ClearBitMask(ComIrqReg,0x80);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80); for (i=; i<InLenByte; i++)
{ WriteRawRC(FIFODataReg, pInData[i]); }
WriteRawRC(CommandReg, Command); if (Command == PCD_TRANSCEIVE)
{ SetBitMask(BitFramingReg,0x80); } i = ;//根据时钟频率调整,操作M1卡最大等待时间25ms
do
{
n = ReadRawRC(ComIrqReg);
i--;
}
while ((i!=) && !(n&0x01) && !(n&waitFor));
ClearBitMask(BitFramingReg,0x80); if (i!=)
{
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-)* + lastBits; }
else
{ *pOutLenBit = n*; }
if (n == )
{ n = ; }
if (n > MAXRLEN)
{ n = MAXRLEN; }
for (i=; i<n; i++)
{ pOutData[i] = ReadRawRC(FIFODataReg); }
}
}
else
{ status = MI_ERR; } } SetBitMask(ControlReg,0x80); // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
} /////////////////////////////////////////////////////////////////////
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn()
{
unsigned char i;
i = ReadRawRC(TxControlReg);
if (!(i & 0x03))
{
SetBitMask(TxControlReg, 0x03);
}
} /////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff()
{
ClearBitMask(TxControlReg, 0x03);
}