其他分享
首页 > 其他分享> > stm32F1门禁卡RC522模块快速上手心得

stm32F1门禁卡RC522模块快速上手心得

作者:互联网

##stm32F1门禁卡RC522模块快速上手心得

1.配置GPIO

//LED  推挽输出    GPIOC   GPIO13
//NSS  推挽输出    GPIOB   GPIO12
//SCK  推挽输出    GPIOB   GPIO14
//M0SI 推挽输出    GPIOA   GPIO8
//MSIO 浮空输入    GPIOA   GPIO10
//RST  推挽输出    GPIOA   GPIO12
void GPIO_init(void)
{
	  RCC->APB2ENR|=1<<2;  //gpioA 时钟
	  RCC->APB2ENR|=1<<3;  //gpioB 时钟
	  RCC->APB2ENR|=1<<4;  //gpioC 时钟
	  GPIOA->CRH&=0XFFF0F000;
	  GPIOA->CRH|=0X000304B3;
	  GPIOA->CRL&=0XFFFFFFFF;
	  GPIOA->CRL|=0X00000000;
	  GPIOA->ODR|=1<<8;         // 输出端口数据位 复位脚拉高  
	  GPIOB->CRH&=0XF0F0FFFF;
	  GPIOB->CRH|=0X03030000;   // gpiob 8-15
	  GPIOB->CRL&=0XFFFFFFFF;
	  GPIOB->CRL|=0X00000000;  // gpiob 0-7
	  GPIOB->ODR&=0; 
	  GPIOC->CRH&=0XFF0FFFFF;
	  GPIOC->CRH|=0X00300000;
	  GPIOC->CRL&=0XFFFFFFFF;
	  GPIOC->CRL|=0X00000000;
	  GPIOC->ODR=0;
}

2.写SPI通信

void   Write_addr_dat(unsigned char  addr,unsigned char dat)
{
  unsigned  char i;

   NSS=0;
	 SCK=0;

	 addr=((addr<<1)&0x7E);
	 
	 for(i=0;i<8;i++)
	 {
	    if(addr&0x80) MOSI=1;
			else MOSI=0;
			
			SCK=1;
	    addr<<=1;
			SCK=0;
	 }
   for(i=0;i<8;i++)
	  {
		  if(dat&0x80) MOSI=1;
			else MOSI=0;		
			SCK=1;
		  dat<<=1;
			SCK=0; 
		}
	 NSS=1;
	 SCK=1;
}
unsigned char  Read_dat(unsigned char  addr)
{

  unsigned  char i;
	unsigned  char  dat=0;
   NSS=0;
	 
	addr=((addr<<1)&0x7E)|0x80;
	 
  for(i=0;i<8;i++)
	 {
	 	  SCK=0;
	    if(addr&0x80) MOSI=1;
			else MOSI=0;
			SCK=1;
		  addr<<=1;
	 }

  for(i=0;i<8;i++)
	 {
	  	SCK=0;
      dat<<=1;
			SCK=1; 
	   if(MISO) dat|=1;
	  }
	 NSS=1;
	 SCK=1;	 
	return dat;
	 
}

3.读RC522寄存器原理

/
//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      //包含CRC 、中断和FIFO缓冲区的状态标志
#define     Status2Reg            0x08      //包含接收器、发送器和数据模式检测器的状态标志

#define     FIFODataReg           0x09      //64字节FIFO缓冲的输出和输入
#define     FIFOLevelReg          0x0A      //指示FIFO中保存的字节数

#define     WaterLevelReg         0x0B     //定义FIFO下溢和上溢报警的FIFO深度
#define     ControlReg            0x0C     //包含不同的控制位
#define     BitFramingReg         0x0D     //面向位的帧的调节
#define     CollReg               0x0E     //定义在RF接口上检测到的第一个冲突
#define     RFU0F                 0x0F     //RFU 保留为将来用的寄存器


// PAGE 1     
#define     RFU10                 0x10   //RFU 保留为将来用的寄存器
#define     ModeReg               0x11   //定义发送和接收的常用模式
#define     TxModeReg             0x12   //定义发送过程的数据速率
#define     RxModeReg             0x13   //定义接收过程的数据速率

#define     TxControlReg          0x14  //控制天线驱动器管脚TX1和TX2的逻辑操作

#define     TxAutoReg             0x15   //RFU 保留为将来用的寄存器


#define     TxSelReg              0x16   //选择模拟部分的内部源
#define     RxSelReg              0x17     //选择内部接收器的设置
#define     RxThresholdReg        0x18    //选择位译码器的阈值
#define     DemodReg              0x19    //定义解调器的设置

//RFU //保留为将来用的寄存器
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C


//RFU //保留为将来用的寄存器
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E  

#define     SerialSpeedReg        0x1F     //选择串行UART接口的速率

//PAGE 2    
#define     RFU20                 0x20    //RFU //保留为将来用的寄存器

//显示CRC计算的实际MSB和LSB值
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22


#define     RFU23                 0x23   //RFU
#define     ModWidthReg           0x24   //控制调制宽度的设置
#define     RFU25                 0x25    //保留为将来用的寄存器
#define     RFCfgReg              0x26     //配置接收器增益
#define     GsNReg                0x27    //选择天线驱动器管脚TX1和TX2的N驱动器的电导
#define     CWGsCfgReg            0x28    //定义P驱动器的电导
#define     ModGsCfgReg           0x29   //定义驱动器P输出电导,便于时间调制

//内部定时器配置
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B

//描述16位长的定时器重装值
#define     TReloadRegH           0x2C    //  高位
#define     TReloadRegL           0x2D    // 低位
                 
//定义定时器的当前值								 
#define     TCounterValueRegH     0x2E    //定时器的当前值,高八位
#define     TCounterValueRegL     0x2F    //定时器的当前值,低八位
// PAGE 3      
#define     RFU30                 0x30   //保留寄存器
#define     TestSel1Reg           0x31   //常用测试信号配置
#define     TestSel2Reg           0x32   //常用测试信号配置和PRBS控制
#define     TestPinEnReg          0x33   //使能测试总线的管脚输出驱动器
#define     TestPinValueReg       0x34   //定义测试端口用作I/O时的值
#define     TestBusReg            0x35   //使能测试总线的管脚输出驱动器
#define     AutoTestReg           0x36   //控制数字自测试
#define     VersionReg            0x37    // 显示版本

#define     AnalogTestReg         0x38    //estReg  描述位   

#define     TestDAC1Reg           0x39    //bit5-0  定义TestDAC1的测试值
#define     TestDAC2Reg           0x3A     //bit5-0  定义TestDAC2的测试值  

#define     TestADCReg            0x3B   //bit7-4 显示adc_I通道 3-0 显示 adc_Q通道

4.其它
关于他们具体通信代码,就不做讲解了,一般百度或者买模块的淘宝卖家会提供。下文主要讲解如何修改密码和写入扇区数据。
扇区3为例,一般扇区的初始A和初始密码B 都是6个0XFF字节,修改密码和写入块数据如下操作。

unsigned char buf[16]={0x01,0x02,0x03,0x04,0x05,0x06,0xff
,0x07,0x80,0x69,0x18,0x17,0x16,0x15,0x14,0x13};  //要写入的密码,中间0XFF,0X07,0X80,0X69 为控制字节
unsigned char  DefaultKey[6] ={0x01,0x02,0x03,0x04,0x05,0x06};//密码A
unsigned char  DefaultKey1[6]={0x18,0x17,0x16,0x15,0x14,0x13}; //密码B
unsigned  char DefaultKey2[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0XFF};//初始密码

while(1)
 {
  status= PcdRequest(REQ_ALL,TagType);
 if(!status)
  {
	status = PcdAnticoll(SelectedSnr);
    if(!status)
	  {
		status=PcdSelect(SelectedSnr);
		 if(!status)
		  {
			snr = 3;  //扇区号3
		status = PcdAuthState(PICC_AUTHENT1A, (snr*4+3), DefaultKey2, SelectedSnr);// 校验3扇区密码A
         if(!status)
		  { 
		  status = PcdAuthState(PICC_AUTHENT1B, (snr*4+3), DefaultKey2, SelectedSnr);// 校验3扇区密码B
				 
			 if(!status)
			   {			
                  LED=~LED;							 
				 status = PcdWrite((snr*4+3), buf);  // 写卡,写新密码 将buf[0]-buf[16]写入1扇区0块
//				 status = PcdRead((snr*4+1), buf2);  // 读卡,读取3扇区0块数据到buf[0]-buf[16] 
				 if(!status)
					{
						 WaitCardOff();
					 }
					}		 
				 }
					
			 }

		}				
	}
}
/*****************************
如上代码,验证密码A和密码B后,将新密码写入扇区3块3中,如果下次在想进入扇区3,就要用新的密码A和密码B,写数据也一样只要操作写函数,就能写入新的数据。
******************************/




标签:status,addr,门禁卡,扇区,RC522,寄存器,define,stm32F1,PICC
来源: https://blog.csdn.net/qq_38716551/article/details/110678001