STM32F103-RFID RC522射频识别

STM32F1 RFID RC522射频识别    ,正点原子的精英板实现。

只有读卡的功能  ,直接建立对应文件即可直接使用。

main.c


#include "stm32f10x.h"
#include "oled.h"
#include "rc522.h"
#include "delay.h"





//主函数
int main()
{
	u8 RC522_ID[4];   //存放IC卡的类型
	u8 RC522_NUM[4];  //存放IC卡的卡号
	u8 RC522_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};  //存放密码
	u8 RC522_return;  //返回的状态
	
	delay_init();
	LED_init();
	OLED_init();
	RC522_Init();  //  **RC522初始化**
	OLED_ShowCharString(0,0,"RC522 TEST:",16);
	OLED_RESET_Gram();
	LED1 = 0;
	Pcd_Reset();   //  **复位RC522 ,此处容易卡死 ,LED1指示**
	LED1 = 1;
	M500PcdConfigISOType('A');  //设置工作方式
	while(1)
	{
		//  **首先寻卡**
		RC522_return = PcdRequest(PICC_REQALL,RC522_ID);
		if( RC522_return != MI_OK)
		{
			OLED_ShowNum(90,20,999,3,16);
		  OLED_RESET_Gram();
			//  **失败再次寻卡 ,次数不可过多 , 时间太长**
			//RC522_return = PcdRequest(PICC_REQALL,RC522_ID);
		}
		
		//  **成功寻到卡**
		if(RC522_return == MI_OK)
		{
			OLED_ShowNum(0,20,100,3,16);
		  OLED_RESET_Gram();
			
			//  **防冲撞,防止多卡同时检测**
			if( (PcdAnticoll(RC522_NUM) == MI_OK) )  //确认选择刚才检测到的IC卡
			{
				OLED_ShowNum(30,20,200,3,16);
		    OLED_RESET_Gram();
				
				//  **选卡成功**
				if( PcdSelect(RC522_NUM)== MI_OK)
				{
					OLED_ShowNum(60,20,300,3,16);
		      OLED_RESET_Gram();
					
					//
					if(PcdAuthState(0x61,0x06,RC522_KEY,RC522_NUM)==MI_OK)
					{
						OLED_ShowNum(25,40,RC522_ID[0],3,16);
						OLED_ShowNum(50,40,RC522_ID[1],3,16);
						OLED_ShowNum(75,40,RC522_ID[2],3,16);
						OLED_ShowNum(100,40,RC522_ID[3],3,16);
		        OLED_RESET_Gram();
					}
				}
			}
		}
		LED0=!LED0;
	}
}
//

rc522.h


#ifndef     __RC522_H__
#define     __RC522_H__
#include "stm32f10x.h"
#include "sys.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                 0x07   //  **可以自行设置**
#define 	MI_ERR                0x08
#define 	MI_NOTAGERR           0x09
// ************************************************************************************************************** //








// ************************************************************************************************************** //
//GPIO_ResetBits(GPIOB,GPIO_Pin_x);  //设置为0
//GPIO_SetBits(GPIOB,GPIO_Pin_x);    //设置为1
#define RC522_RST  PBout(10)   //RST  0为使能 ,1为失能
#define RC522_CS   PBout(11)   //SDA  0为使能 ,1为失能
#define RC522_SCK  PBout(13)   //SCK
#define RC522_MOSI PBout(15)   //MOSI
#define RC522_MISO PBin (14)   //MISO



// ************************************************************************************************************** //
void Delay_ns(u32 ns);
void RC522_SPI_SendData(u8 data);
  u8 RC522_SPI_ReadData(void);
  u8 RC522_Read_Reg(u8 regaddr);
void RC522_Write_Reg(u8 regaddr,u8 regvalue);
void RC522_SetBit(u8 reg_add, u8 reg_val);
void RC522_ClearBit(u8 reg_add,u8 reg_val);
void PcdAntenna_On(void);
void PcdAntenna_Off(void);
void Pcd_Reset(void);
void M500PcdConfigISOType(u8 Type);
char PcdComMF522(u8 ucCommand,u8 *pInData,u8 ucInLenByte,u8 *pOutData,u32 *pOutLenBit);
char PcdRequest(u8 ucReq_code,u8 *pTagType);
char PcdAnticoll(u8 *pSnr);
void CalulateCRC(u8 *pIndata,u8 ucLen,u8 *pOutData);
char PcdSelect(u8 *pSnr);
char PcdAuthState(u8 ucAuth_mode,u8 ucAddr,u8 *pKey,u8 *pSnr);
char PcdWrite(u8 ucAddr,u8 *pData);
char PcdRead(u8 ucAddr,u8 *pData);
char PcdHalt(void);
void RC522_Init(void);
void SPI_init(void);


#endif


rc522.c


#include "rc522.h"
#include "delay.h"




//  **使用正点原子的延时 ,大概率程序卡死在 222行do-while循环 寻卡与认证等待时间**
#define   RC522_DELAY()  Delay_ns(200)
// ************************************************************************************************************** //
void Delay_ns(u32 ns)  //可以自行Debug调试时间
{
	while(ns--)
	{__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();}
}
// ************************************************************************************************************** //
//向RC522发送一字节数据
void RC522_SPI_SendData(u8 data)
{
	u8 i;
	for(i=0;i<8;i++)
	{
		if (data & 0x80)
      RC522_MOSI = 1;
    else 
      RC522_MOSI = 0;
		
    RC522_DELAY();
    RC522_SCK = 0;
    RC522_DELAY();
    RC522_SCK = 1;
    RC522_DELAY();
    data <<= 1; 
	}
}
// ************************************************************************************************************** //
//读取RC522的值
u8 RC522_SPI_ReadData()
{
	u8 t;
  u8 Data;

  for(t=0;t<8;t++)
  {
    Data <<= 1;
    RC522_SCK = 0;
    RC522_DELAY();
    if(RC522_MISO ==1) // // //
        Data |= 0x01;
		
    RC522_DELAY();
    RC522_SCK = 1;
    RC522_DELAY();
  }
  return Data;
}
// ************************************************************************************************************** //
//读RC522寄存器的值
//addr 寄存器地址
u8 RC522_Read_Reg(u8 regaddr)
{
	u8 ucaddr;  //寄存器有效地址
	u8 return_value; //寄存器返回值
	
	ucaddr = ((regaddr<<1) & 0x7E) | 0x80;	 //  **变成有效地址形式,最低位为0,最高位为1 从RC522中读出数据
	RC522_CS = 0;  //0为使能
	RC522_SPI_SendData(ucaddr);  //发送有效地址
	return_value = RC522_SPI_ReadData();  //收到寄存去返回值
	RC522_CS = 1;  //1为失能
	
	return return_value;
}
// ************************************************************************************************************** //
//写RC522寄存器的值
//regaddr  寄存器地址
//regvalue  寄存器中的值
void RC522_Write_Reg(u8 regaddr,u8 regvalue)
{
	u8 ucaddr;  //寄存器有效地址
	
	ucaddr = (regaddr<<1) & 0x7E;	   //  **变成有效地址形式,最低位为0,最高位为0 从EC522中写入数据
	RC522_CS = 0;
	RC522_SPI_SendData(ucaddr);   //发送地址
	RC522_SPI_SendData(regvalue);  //发送数据
	RC522_CS = 1;	
}
// ************************************************************************************************************** //
//对RC522寄存器置位,相当于对MF522中的地址写数据,控制不同的操作
//reg_add 寄存器地址
//w_val  置位值
void RC522_SetBit(u8 reg_add, u8 reg_val)  
{
  u8 ucTemp;
	
  ucTemp=RC522_Read_Reg(reg_add);  //读取当前地址寄存器的值
  RC522_Write_Reg(reg_add,ucTemp | reg_val);         // set bit mask
}
// ************************************************************************************************************** //
//对RC522寄存器清位,清除MF522寄存器中的值  还原之前数据,或者换为无用值
//reg_add 寄存器地址
//w_val  清位值
void RC522_ClearBit(u8 reg_add,u8 reg_val)
{
  u8 ucTemp;
	
  ucTemp=RC522_Read_Reg(reg_add);   //读取当前地址寄存器的值
  RC522_Write_Reg(reg_add,ucTemp & (~reg_val));  // clear bit mask
}
// ************************************************************************************************************** //
//开启天线 
void PcdAntenna_On()
{
  u8 uc;
  
  uc=RC522_Read_Reg(TxControlReg);  //读取 TxControlReg 的值
  if (!(uc & 0x03))                 //盘丢按是否为正确值
	RC522_SetBit(TxControlReg,0x03); //否则写入正确值
}
// ************************************************************************************************************** //
//关闭天线
void PcdAntenna_Off()
{
  RC522_ClearBit(TxControlReg,0x03);	 //清除写入值
}
// ************************************************************************************************************** //
//复位RC522 
void Pcd_Reset()
{
	RC522_RST = 1;
	//delay_us(1);
	Delay_ns(10);
	RC522_RST = 0;
	//delay_us(1);
	Delay_ns(10);
	RC522_RST = 1;
	//delay_us(1);
	Delay_ns(10);
	
	RC522_Write_Reg(CommandReg,0x0f);
	RC522_Write_Reg(CommandReg,0x0f);   //  **写入两遍 ,防止出错**
	//while(RC522_Read_Reg(CommandReg) & 0x10); //  **使用等待 ,可能出错 ,初始化不通过**
	//delay_us(1);
	Delay_ns(10);
	
  RC522_Write_Reg(ModeReg,0x3D);           //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
  RC522_Write_Reg(TReloadRegL,30);         //16位定时器低位
	RC522_Write_Reg(TReloadRegH,0);			     //16位定时器高位
  RC522_Write_Reg(TModeReg,0x8D);				   //定义内部定时器的设置
  RC522_Write_Reg(TPrescalerReg,0x3E);		 //设置定时器分频系数
	RC522_Write_Reg(TxAutoReg,0x40);				 //调制发送信号为100%ASK
}
// ************************************************************************************************************** //
//设置RC522的工作方式
//Type 工作方式选择
void M500PcdConfigISOType(u8 Type)
{
	if (Type=='A')                     //ISO14443_A
  {
		RC522_ClearBit(Status2Reg,0x08);  //状态2寄存器
		
    RC522_Write_Reg(ModeReg,0x3D);    //3F  和Mifare卡通讯,CRC初始值0x6363
		RC522_Write_Reg(RxSelReg,0x86);   //84  选择内部接收器设置,内部模拟部分调制信号,发送数据后延迟6个位时钟接收
		RC522_Write_Reg(RFCfgReg,0x7F);   //4F  配置接收器 48dB最大增益
		RC522_Write_Reg(TReloadRegL,30);  //tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
		RC522_Write_Reg(TReloadRegH,0);
		RC522_Write_Reg(TModeReg,0x8D);
		RC522_Write_Reg(TPrescalerReg,0x3E);
		//delay_us(2);
		Delay_ns(1000);
		
		PcdAntenna_On();//开天线
  }	 
}
// ************************************************************************************************************** //
//通过RC522和ISO14443卡通讯
//ucCommand  RC522命令字
//pInData  通过RC522发送到卡片的数据
//ucInLenByte  发送数据的字节长度
//pOutData  接收到的卡片返回数据
//pOutLenBit  返回数据的位长度
//状态值= MI_OK  成功
char PcdComMF522(u8 ucCommand,u8 *pInData,u8 ucInLenByte,u8 *pOutData,u32 *pOutLenBit)
{
  char cStatus = MI_ERR;
  u8 ucIrqEn   = 0x00;
  u8 ucWaitFor = 0x00;
  u8 ucLastBits;
  u8 ucN;
  u32 ul;
	
  switch(ucCommand)
  {
     case PCD_AUTHENT:		  //Mifare认证
        ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEn
        ucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位
        break;
     
     case PCD_TRANSCEIVE:		//接收发送 发送接收
        ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
        ucWaitFor = 0x30;		//寻卡等待时候 查询接收中断标志位与 空闲中断标志位
        break;
     
     default:
       break;     
  }
  RC522_Write_Reg(ComIEnReg,ucIrqEn | 0x80);		//IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
  RC522_ClearBit(ComIrqReg,0x80);			//Set1该位清零时,CommIRqReg的屏蔽位清零
  RC522_Write_Reg(CommandReg,PCD_IDLE);		//写空闲命令
  RC522_SetBit(FIFOLevelReg,0x80);			//置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除

  for(ul=0;ul<ucInLenByte;ul++)
  {  RC522_Write_Reg(FIFODataReg,pInData[ul]); }   		//写数据进FIFOdata
    
  RC522_Write_Reg(CommandReg,ucCommand);					//写命令


  if(ucCommand==PCD_TRANSCEIVE)
	{  RC522_SetBit(BitFramingReg,0x80); } 				//StartSend置位启动数据发送 该位与收发命令使用时才有效

  ul = 800;//根据时钟频率调整,操作M1卡最大等待时间25ms
	
  do 														//认证 与寻卡等待时间	
  {
    ucN = RC522_Read_Reg(ComIrqReg);							//查询事件中断
    ul--;
  }
	while((ul != 0)&&(!(ucN & 0x01))&&(!(ucN & ucWaitFor)));		//退出条件i=0,定时器中断,与写空闲命令

  RC522_ClearBit(BitFramingReg,0x80);					//清理允许StartSend位

  if(ul != 0)
  {
    if(!(RC522_Read_Reg(ErrorReg) & 0x1B))			//读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
    {
      cStatus = MI_OK;
      
      if(ucN & ucIrqEn & 0x01)					//是否发生定时器中断
        cStatus = MI_NOTAGERR;   
        
      if(ucCommand==PCD_TRANSCEIVE)
      {
        ucN=RC522_Read_Reg(FIFOLevelReg);			//读FIFO中保存的字节数
        
        ucLastBits = RC522_Read_Reg(ControlReg) & 0x07;	//最后接收到得字节的有效位数
        
        if(ucLastBits)
          *pOutLenBit = (ucN-1) * 8 + ucLastBits;   	//N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
        else
          *pOutLenBit = ucN*8;   					//最后接收到的字节整个字节有效
        
        if(ucN==0)		
          ucN = 1;    
        
        if(ucN > MAXRLEN)
          ucN = MAXRLEN;   
        
        for(ul=0;ul<ucN;ul++)
          pOutData[ul]=RC522_Read_Reg(FIFODataReg);
        }
    }
    else
      cStatus = MI_ERR;       
  }

  RC522_SetBit(ControlReg,0x80);    // stop timer now
  RC522_Write_Reg(CommandReg,PCD_IDLE); 
   
  return cStatus;
}
// ************************************************************************************************************** //
//  **寻卡**
//ucReq_code,寻卡方式 = 0x52,寻感应区内所有符合14443A标准的卡;寻卡方式= 0x26,寻未进入休眠状态的卡
//pTagType,卡片类型代码
//  = 0x4400,Mifare_UltraLight
//  = 0x0400,Mifare_One(S50)
//  = 0x0200,Mifare_One(S70)
//  = 0x0800,Mifare_Pro(X))
//  = 0x4403,Mifare_DESFire
//状态值= MI_OK,成功
char PcdRequest(u8 ucReq_code,u8 *pTagType)
{
  char cStatus;  
  u8 ucComMF522Buf[MAXRLEN]; 
	u32 ulLen;


  RC522_ClearBit(Status2Reg,0x08);	//清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
  RC522_Write_Reg(BitFramingReg,0x07);	//	发送的最后一个字节的 七位
  RC522_SetBit(TxControlReg,0x03);	//TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号

  ucComMF522Buf[0] = ucReq_code;		//存入 卡片命令字

  cStatus = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&ulLen);	//寻卡

  if((cStatus==MI_OK)&&(ulLen==0x10))	//寻卡成功返回卡类型 
  {
    *pTagType       = ucComMF522Buf[0];
    *(pTagType + 1) = ucComMF522Buf[1];
  }
  else
   cStatus = MI_ERR;

  return cStatus;
}
// ************************************************************************************************************** //
//防冲撞
//pSnr,卡片序列号,4字节
//状态值= MI_OK,成功
char PcdAnticoll(u8 *pSnr)
{
  char cStatus;
  u8 uc,ucSnr_check=0;
  u8 ucComMF522Buf[MAXRLEN]; 
  u32 ulLen;
  

  RC522_ClearBit(Status2Reg,0x08);		//清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
  RC522_Write_Reg(BitFramingReg,0x00);		//清理寄存器 停止收发
  RC522_ClearBit(CollReg,0x80);			//清ValuesAfterColl所有接收的位在冲突后被清除
 
  ucComMF522Buf[0] = 0x93;	//卡片防冲突命令
  ucComMF522Buf[1] = 0x20;
 
  cStatus = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&ulLen);//与卡片通信

  if(cStatus == MI_OK)		//通信成功
  {
    for(uc=0;uc<4;uc++)
    {
      *(pSnr + uc) = ucComMF522Buf[uc];			//读出UID
      ucSnr_check ^= ucComMF522Buf[uc];
    }
    
    if(ucSnr_check != ucComMF522Buf[uc])
    cStatus = MI_ERR;    				 
  }
  RC522_SetBit(CollReg,0x80);
      
  return cStatus;		
}

// ************************************************************************************************************** //
//用RC522计算CRC16
//pIndata,计算CRC16的数组
//ucLen,计算CRC16的数组字节长度
//pOutData,存放计算结果存放的首地址
void CalulateCRC(u8 *pIndata,u8 ucLen,u8 *pOutData)
{
  u8 uc,ucN;

  RC522_ClearBit(DivIrqReg,0x04);
  RC522_Write_Reg(CommandReg,PCD_IDLE);
  RC522_SetBit(FIFOLevelReg,0x80);

  for(uc=0;uc<ucLen;uc++)
    RC522_Write_Reg(FIFODataReg,*(pIndata + uc));   

  RC522_Write_Reg(CommandReg,PCD_CALCCRC);
  uc = 0xFF;

  do 
  {
    ucN = RC522_Read_Reg(DivIrqReg);
    uc--;
  } 
	while((uc != 0) && !(ucN & 0x04));
  
  pOutData[0] = RC522_Read_Reg(CRCResultRegL);
  pOutData[1] = RC522_Read_Reg(CRCResultRegM);
}

// ************************************************************************************************************** //
//选定卡片
//pSnr,卡片序列号,4字节
//状态值= MI_OK,成功
char PcdSelect(u8 *pSnr)
{
  char ucN;
  u8 uc;
  u8 ucComMF522Buf [ MAXRLEN ]; 
  u32  ulLen;
  
  
  ucComMF522Buf[0] = PICC_ANTICOLL1;
  ucComMF522Buf[1] = 0x70;
  ucComMF522Buf[6] = 0;

  for(uc=0;uc<4;uc++)
  {
    ucComMF522Buf[uc + 2] = *(pSnr + uc);
    ucComMF522Buf[6] ^= *(pSnr + uc);
  }
  
  CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);

  RC522_ClearBit(Status2Reg,0x08);

  ucN = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&ulLen);
  
  if((ucN==MI_OK)&&(ulLen==0x18))
    ucN = MI_OK;  
  else
    ucN = MI_ERR;    
  
  return ucN;		
}
// ************************************************************************************************************** //
//验证卡片密码
//ucAuth_mode,密码验证模式= 0x60,验证A密钥,密码验证模式= 0x61,验证B密钥
//uint8_t ucAddr,块地址
//pKey,密码
//pSnr,卡片序列号,4字节状态值= MI_OK,成功
char PcdAuthState(u8 ucAuth_mode,u8 ucAddr,u8 *pKey,u8 *pSnr)
{
  char cStatus;
  u8 uc, ucComMF522Buf[MAXRLEN];
  u32 ulLen;
  
  ucComMF522Buf[0] = ucAuth_mode;
  ucComMF522Buf[1] = ucAddr;

  for(uc=0;uc<6;uc++)
    ucComMF522Buf[uc + 2] = *(pKey + uc);   

  for(uc=0;uc<6;uc++)
    ucComMF522Buf[uc + 8] = *(pSnr + uc);  
	
   //memcpy(&ucComMF522Buf[2], pKey, 6); 
   //memcpy(&ucComMF522Buf[8], pSnr, 4); 	

  cStatus = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&ulLen);

  if((cStatus != MI_OK)||(!(RC522_Read_Reg(Status2Reg) & 0x08)))
    cStatus = MI_ERR;   
    
  return cStatus;
}

// ************************************************************************************************************** //
//写数据到M1卡一块
//uint8_t ucAddr,块地址
//pData,写入的数据,16字节
//状态值= MI_OK,成功
char PcdWrite(u8 ucAddr,u8 *pData)
{
  char cStatus;
  u8 uc, ucComMF522Buf[MAXRLEN];
  u32 ulLen;
   
  
  ucComMF522Buf[0] = PICC_WRITE;
  ucComMF522Buf[1] = ucAddr;

  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

  cStatus = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&ulLen);

  if((cStatus != MI_OK)||(ulLen != 4)||((ucComMF522Buf[0] & 0x0F) != 0x0A))
	  cStatus = MI_ERR;
      
  if(cStatus==MI_OK)
  {
    //memcpy(ucComMF522Buf, pData, 16);
    for(uc=0;uc<16;uc++)
      ucComMF522Buf[uc] = *(pData + uc);  
    
    CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);

    cStatus = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&ulLen);
    
    if((cStatus != MI_OK)||(ulLen != 4)||((ucComMF522Buf[0] & 0x0F) != 0x0A))
      cStatus = MI_ERR;   
  }
	
  return cStatus;		
}

// ************************************************************************************************************** //
//读取M1卡一块数据
//ucAddr,块地址
//pData,读出的数据,16字节
//状态值= MI_OK,成功
char PcdRead(u8 ucAddr,u8 *pData)
{
  char cStatus;
  u8 uc, ucComMF522Buf[MAXRLEN]; 
  u32 ulLen;
  
  ucComMF522Buf[0] = PICC_READ;
  ucComMF522Buf[1] = ucAddr;

  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
  cStatus = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&ulLen);

  if((cStatus==MI_OK)&&(ulLen==0x90))
  {
    for(uc=0;uc<16;uc++)
      *(pData + uc) = ucComMF522Buf[uc];
  }
  else
    cStatus = MI_ERR;   
   
  return cStatus;		
}

// ************************************************************************************************************** //
//命令卡片进入休眠状态
//状态值= MI_OK,成功
char PcdHalt()
{
	u8 ucComMF522Buf[MAXRLEN]; 
	u32  ulLen;
  
  ucComMF522Buf[0] = PICC_HALT;
  ucComMF522Buf[1] = 0;
	
  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 	PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&ulLen);

  return MI_OK;	
}
// ************************************************************************************************************** //
//RC522初始化
void RC522_Init()
{
	SPI_init();	
	RC522_RST = 1;  //失能
	RC522_CS = 1;   //失能
}
// ************************************************************************************************************** //
void SPI_init(void)
{
  GPIO_InitTypeDef GPIO_Initspi;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE );
	
	//复位,即即RC522模块的RST引脚,接STM32的普通IO即可
	GPIO_Initspi.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Initspi.GPIO_Pin = GPIO_Pin_10;
  GPIO_Initspi.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
  GPIO_Init(GPIOB,&GPIO_Initspi);
	
	//片选,即RC522模块的SDA引脚
	//  **正点原子对应引脚可以原理图查看**
  GPIO_Initspi.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Initspi.GPIO_Pin = GPIO_Pin_11;
  GPIO_Initspi.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
  GPIO_Init(GPIOB,&GPIO_Initspi);
	
	//时钟,即RC522模块的SCK引脚,接STM32的SPI的SCK引脚
	//  **正点原子对应引脚可以原理图查看**
  GPIO_Initspi.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Initspi.GPIO_Pin = GPIO_Pin_13;
  GPIO_Initspi.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
  GPIO_Init(GPIOB,&GPIO_Initspi);
	
	// 数据输入,即即RC522模块的MOSI引脚,接STM32的SPI的MOSI引脚
	//  **正点原子对应引脚可以原理图查看**
  GPIO_Initspi.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Initspi.GPIO_Pin = GPIO_Pin_15;
  GPIO_Initspi.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
  GPIO_Init(GPIOB,&GPIO_Initspi);	
	
	// 数据输出,即即RC522模块的MISO引脚,接STM32的SPI的MISO引脚
	//  **正点原子对应引脚可以原理图查看**
  GPIO_Initspi.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Initspi.GPIO_Pin = GPIO_Pin_14;
  GPIO_Initspi.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空输入
  GPIO_Init(GPIOB,&GPIO_Initspi);
}
// ************************************************************************************************************** //

个人见解,感谢阅读。

  • 3
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,具有丰富的外设资源和强大的性能,适合用于各种嵌入式应用。 RFID-RC522是一款高性能的识别模块,能够实现对13.56MHz标签的读写操作,广泛应用于门禁、物流、仓储等领域。 将STM32F103C8T6和RFID-RC522结合起来,可以实现智能门禁、物流追踪等应用,具有广阔的市场前景。 ### 回答2: STM32F103C8T6是一款由STMicroelectronics公司推出的32位微控制器,采用ARM Cortex-M3内核,集成了128KB闪存、20KB标准SRAM,拥有多种通信接口(如SPI、I²C、USART等)和外设(如定时器、PWM等),可广泛应用于工业控制、电力控制、仪器仪表、家庭自动化等领域。 而RFID-RC522是一款经典的13.56MHz识别模块,可实现非接触式读取和写入标签、卡片等物品上的数据,被广泛应用于物联网、智能家居、安防等领域。该模块内部集成了高度集成的模拟电路和数字电路,可与STM32F103C8T6等微控制器通过SPI接口通信,实现RFID技术在各种应用场景中的应用。 需要注意的是,STM32F103C8T6与RFID-RC522之间的连接应该正确,特别是SPI接口的引脚连接。同时,应根据具体的应用场景和目标以及相关要求,对于STM32F103C8T6和RFID-RC522的程序设计进行充分规划和设计,以达到良好的应用效果。 ### 回答3: STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,其具有丰富的外设和通讯接口,适用于各种嵌入式应用领域。而RFID-RC522则是一种RFID读写器芯片,可以读取和编写ISO/IEC 14443类型A和B的标签。这两种芯片结合在一起,可以实现各种有趣的应用。 STM32F103C8T6的主要特点是有72MHz的时钟率,具有64kB的Flash和20kB的SRAM,可以通过USART、I2C、SPI等多种通讯接口进行通讯。此外,它还支持定时器、看门狗、ADC等多种外设,可实现众多应用。 而RFID-RC522读写器芯片则有13.56MHz的工作率,支持ISO/IEC 14443类型A和B标签的读取和编写。它有一个SPI接口,可以轻松地与STM32F103C8T6进行通讯。 利用STM32F103C8T6和RFID-RC522可以实现诸如门禁系统、无人售货机、智能车库等应用。例如,当用户使用RFID卡或标签靠近读卡器时,RFID-RC522读取卡或标签中的信息,并通过SPI接口将其传输给STM32F103C8T6,使其在控制下执行相应的操作。 总之,STM32F103C8T6和RFID-RC522组成了一款强大的组合,适用于各种嵌入式应用领域,可以为开发者带来更多的灵活性和创造性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值