RC522刷卡电路设计及程序

一、RC522刷卡电路组成

RC522 刷卡电路
基于RC522的刷卡电路如上图所示。该电路组成主要分为三部分:
Receiving Circuit:接收电路,接收卡发送的数据。
Filtering Impedence-Transtorm circuit:滤波和阻抗变换电路,抑制高次谐波并优化到读卡器天线的功率传输。
Matching Circuit:天线匹配电路。
在这里插入图片描述

二、RC522天线电路参数设计

1、天线电路参数

MF RC500 是一个单独的读卡器集成电路,它在没有外部放大器的情况下工作距离最大可达到 10cm,两侧最大5cm。为了得到最大的刷卡距离,需要合理设计天线电路和接收电路的元件参数。
在这里插入图片描述
如上图所示为MF RC522推荐的天线电路和接收电路的结构。
其中L0、C0组成了LC滤波电路,对应图一中的L1、L2、C5、C6;
Cs、Cp对应图一中的C8、C9、C11、C12;
R1、R2、C3、C4对应图一中的R3、R2、R7、R10;
滤波和接收电路的元件L0、C0、Cs、Cp、R1、R2、R3、R4的参数是固定的。在这里插入图片描述
Tx11和Tx12之间的整个天线线圈电感用Lant表示、天线所有电阻损耗可以用 Rant 来表示、天线的电容损耗可以用Cant来表示。建议用阻抗分析仪测量天线的等效电路,
在这里插入图片描述
如果没有阻抗分析仪 将计算的电感和电容值作为起始值。
天线线圈等效电阻的估算:RANT=5*RDC
式中,RDC为天线线圈的导线电阻,RANT为考虑集肤效应的天线线圈等效电阻。
天线线圈电感的估算:
在这里插入图片描述

2、天线品质因子计算

获取了天线电感 LANT 和电阻 RANT 的值之后,计算天线的品质因子。
在这里插入图片描述
在这里插入图片描述

2、天线外部电阻计算

由于元件的容差和对温度的依靠 我们建议 Q 因子的值取 35 要降低原始的 Q 因子 要求增加一个外部电阻 REXT 。图 3.10 显示了如何连接外部电阻 REXT。
在这里插入图片描述
REXT 的值用下面的公式算出:
在这里插入图片描述

3、天线匹配电路电容的计算

图 3.11 显示了推荐使用的将天线线圈匹配到 50Ω 的电路 匹配用一个串联和一个并联电容来实现输入电阻 Z 要等于 50Ω。
在这里插入图片描述
在这里插入图片描述
Cs 和 Cp 应当是 NP0 电介质的 SMD 类型 有很好的温度稳定性 我们建议将 Cp 分裂成一个固定的值和一个最大值是 10~20pF 的可变值 Cp’。
Cp 固定值对应图一中的C11、C12, Cp 可变值 Cp’对应图1中的C11 ~ C18。

4、环境对天线的影响

任何变化磁场都会在靠近读卡器天线的金属元件上感应出电压 这个感应电压会在金属平面上产生涡流,而涡流会导致天线去调并减弱磁场。结果是减少工作距离以及可能产生传输出错。
天线和大量金属元件的距离对于长距离 R/W 至少是 10cm 短距离 R/W 至少是 3cm 而且必须使
用密封的金属铁屏蔽。
5、电子屏蔽对天线的影响(天线PCB绘制)
电子屏蔽用于减少天线线圈本身产生的电场 要在 PCB 上获得屏蔽的天线 PCB 要有 4 层而且在顶
层和低层都有屏蔽环 shielding loop 这些环必须不能重合 闭合 它不仅提供电子屏蔽 还能改良EMC性能。
在这里插入图片描述

三、程序设计步骤

通讯协议代码
1、RC522初始化 :RST引脚拉低硬复位、SPI接口初始化、RC522寄存器配置和模式设置初始化
2、寻卡:发送寻卡命令给RC522模块、RC522模块开始搜索附件的卡片,并返回卡片信息。
3、防冲突:如果同时存在多张卡片,RC522模块执行防冲突算法,以保证选中的只是某一张卡
4、选择卡片:根据卡片的唯一序列号,选择要与之通信的特定卡片。
5、验证和通信:对选定的卡片进行身份验证,需要提供密钥和扇区号等参数,通信成功可对卡片进行读写操作。(只需要读唯一ID的话,不需要验证)
6、通信结束:将RC522置于空闲状体或关闭RC522模块。

/*
 * 函数名:SetBitMask
 * 描述  :对RC522寄存器置位
 * 输入  :ucReg,寄存器地址
 *         ucMask,置位值
 * 返回  : 无
 * 调用  :内部调用
 */
void SetBitMask ( unsigned char ucReg, unsigned char ucMask )  
{
    unsigned char ucTemp;
    ucTemp = ReadRawRC ( ucReg );
    WriteRawRC ( ucReg, ucTemp | ucMask );         // set bit mask
}
 
 
/*
 * 函数名:ClearBitMask
 * 描述  :对RC522寄存器清位
 * 输入  :ucReg,寄存器地址
 *         ucMask,清位值
 * 返回  : 无
 * 调用  :内部调用
 */
void ClearBitMask ( unsigned char ucReg, unsigned char ucMask )  
{
    unsigned char ucTemp;
    ucTemp = ReadRawRC ( ucReg );
    WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) );  // clear bit mask
}
/*
 * 函数名:PcdAntennaOn
 * 描述  :开启天线 
 * 输入  :无
 * 返回  : 无
 * 调用  :内部调用
 */
void PcdAntennaOn ( void )
{
    unsigned char uc;
    uc = ReadRawRC ( TxControlReg );
    if ( ! ( uc & 0x03 ) )
			SetBitMask(TxControlReg, 0x03);
}
 
 
/*
 * 函数名:PcdAntennaOff
 * 描述  :开启天线 
 * 输入  :无
 * 返回  : 无
 * 调用  :内部调用
 */
void PcdAntennaOff ( void )
{
    ClearBitMask ( TxControlReg, 0x03 );
}
 
 
/*
 * 函数名:M500PcdConfigISOType
 * 描述  :设置RC522的工作方式
 * 输入  :ucType,工作方式
 * 返回  : 无
 * 调用  :外部调用
 */
void M500PcdConfigISOType ( unsigned char ucType )
{
	if ( ucType == 'A')                     //ISO14443_A
  {
		ClearBitMask ( Status2Reg, 0x08 );
        WriteRawRC ( ModeReg, 0x3d );//3F 3d
		WriteRawRC ( RxSelReg, 0x84 );//84 86
		WriteRawRC( RFCfgReg, 0x4F );   //4F
		WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
		WriteRawRC ( TReloadRegH, 0 );
		WriteRawRC ( TModeReg, 0x8D );
		WriteRawRC ( TPrescalerReg, 0x3E );
		_delay_us ( 2 );
		PcdAntennaOn ();//开天线
   }
 
}
 
/*
 * 函数名:PcdRese
 * 描述  :复位RC522 
 * 输入  :无
 * 返回  : 无
 * 调用  :外部调用
 */
void PcdReset ( void )
{
    RC522_Reset_Disable();
    _delay_us ( 1 );
    RC522_Reset_Enable();
    _delay_us ( 1 );
    RC522_Reset_Disable();
    _delay_us ( 1 );
    WriteRawRC ( CommandReg, 0x0f );
    while ( ReadRawRC ( CommandReg ) & 0x10 )
    {
		;
    }
    _delay_us ( 1 );
    WriteRawRC ( ModeReg, 0x3D );   //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
    WriteRawRC ( TReloadRegL, 30 );          //16位定时器低位    
    WriteRawRC ( TReloadRegH, 0 );			     //16位定时器高位
    WriteRawRC ( TModeReg, 0x8D );				   //定义内部定时器的设置
    WriteRawRC ( TPrescalerReg, 0x3E );			 //设置定时器分频系数
    WriteRawRC ( TxAutoReg, 0x40 );				   //调制发送信号为100%ASK	
}
 
/*
 * 函数名:PcdComMF522
 * 描述  :通过RC522和ISO14443卡通讯
 * 输入  :ucCommand,RC522命令字
 *         pInData,通过RC522发送到卡片的数据
 *         ucInLenByte,发送数据的字节长度
 *         pOutData,接收到的卡片返回数据
 *         pOutLenBit,返回数据的位长度
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :内部调用
 */
char PcdComMF522 ( unsigned char ucCommand, unsigned char * pInData, unsigned char ucInLenByte, unsigned char * pOutData, unsigned int * pOutLenBit )		
{
    char cStatus = MI_ERR;
    unsigned char ucIrqEn   = 0x00;
    unsigned char ucWaitFor = 0x00;
    unsigned char ucLastBits;
    unsigned char ucN;
    unsigned int 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;
			 
    }
    WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );//IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
    ClearBitMask ( ComIrqReg, 0x80 );			//Set1该位清零时,CommIRqReg的屏蔽位清零
    WriteRawRC ( CommandReg, PCD_IDLE );		//写空闲命令
    SetBitMask ( FIFOLevelReg, 0x80 );//置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
    for ( ul = 0; ul < ucInLenByte; ul ++ )
		  WriteRawRC ( FIFODataReg, pInData [ ul ] );    		//写数据进FIFOdata	
    WriteRawRC ( CommandReg, ucCommand );					//写命令
    if ( ucCommand == PCD_TRANSCEIVE )
			SetBitMask(BitFramingReg,0x80); //StartSend置位启动数据发送 该位与收发命令使用时才有效
    ul = 1000;//根据时钟频率调整,操作M1卡最大等待时间25ms
    do 														//认证 与寻卡等待时间	
    {
         ucN = ReadRawRC ( ComIrqReg );							//查询事件中断
         ul --;
    } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );		//退出条件i=0,定时器中断,与写空闲命令
    ClearBitMask ( BitFramingReg, 0x80 );					//清理允许StartSend位
    if ( ul != 0 )
    {
		if ( ! (( ReadRawRC ( ErrorReg ) & 0x1B )) )			//读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
		{
			cStatus = MI_OK;
			if ( ucN & ucIrqEn & 0x01 )					//是否发生定时器中断
			  cStatus = MI_NOTAGERR;   
				
			if ( ucCommand == PCD_TRANSCEIVE )
			{
				ucN = ReadRawRC ( FIFOLevelReg );			//读FIFO中保存的字节数
				
				ucLastBits = ReadRawRC ( 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 ] = ReadRawRC ( FIFODataReg );   
			}		
        }
			else
				cStatus = MI_ERR;   
    }
   
   SetBitMask ( ControlReg, 0x80 );           // stop timer now
   WriteRawRC ( CommandReg, PCD_IDLE ); 
	
   return cStatus;
 
}
 
 
/*
 * 函数名:PcdRequest
 * 描述  :寻卡
 * 输入  :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 ( unsigned char ucReq_code, unsigned char * pTagType )
{
    char cStatus;  
    unsigned char ucComMF522Buf [ MAXRLEN ]; 
    unsigned int ulLen;
 
    ClearBitMask ( Status2Reg, 0x08 );	//清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
    WriteRawRC ( BitFramingReg, 0x07 );	//	发送的最后一个字节的 七位
    SetBitMask ( 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;
 
}
 
 
/*
 * 函数名:PcdAnticoll
 * 描述  :防冲撞
 * 输入  :pSnr,卡片序列号,4字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdAnticoll ( unsigned char * pSnr )
{
    char cStatus;
    unsigned char uc, ucSnr_check = 0;
    unsigned char ucComMF522Buf [ MAXRLEN ]; 
	unsigned int ulLen;
                      
    ClearBitMask ( Status2Reg, 0x08 );		//清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
    WriteRawRC ( BitFramingReg, 0x00);		//清理寄存器 停止收发
    ClearBitMask ( 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;    
				 
    }
    SetBitMask ( CollReg, 0x80 );
    return cStatus;
	
}
 
 
/*
 * 函数名:CalulateCRC
 * 描述  :用RC522计算CRC16
 * 输入  :pIndata,计算CRC16的数组
 *         ucLen,计算CRC16的数组字节长度
 *         pOutData,存放计算结果存放的首地址
 * 返回  : 无
 * 调用  :内部调用
 */
void CalulateCRC ( unsigned char * pIndata, unsigned char ucLen, unsigned char * pOutData )
{
    unsigned char uc, ucN;
    ClearBitMask(DivIrqReg,0x04);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);
	
    for ( uc = 0; uc < ucLen; uc ++)
	    WriteRawRC ( FIFODataReg, * ( pIndata + uc ) );   
 
    WriteRawRC ( CommandReg, PCD_CALCCRC );
	
    uc = 0xFF;
	
    do 
    {
        ucN = ReadRawRC ( DivIrqReg );
        uc --;
    } while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
		
    pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );
    pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );
	
}
 
 
/*
 * 函数名:PcdWrite
 * 描述  :写数据到M1卡一块
 * 输入  :unsigned char ucAddr,块地址
 *         pData,写入的数据,16字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdWrite ( unsigned char ucAddr, unsigned char * pData )
{
    char cStatus;
	unsigned char uc, ucComMF522Buf [ MAXRLEN ];
    unsigned int 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;
}
 

/*
 * 函数名:PcdSelect
 * 描述  :选定卡片
 * 输入  :pSnr,卡片序列号,4字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdSelect ( unsigned char * pSnr )
{
    char ucN;
    unsigned char uc;
	unsigned char ucComMF522Buf [ MAXRLEN ]; 
    unsigned int  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 ] );
    ClearBitMask ( 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;
}
 
 
/*
 * 函数名:PcdAuthState
 * 描述  :验证卡片密码
 * 输入  :ucAuth_mode,密码验证模式
 *                     = 0x60,验证A密钥
 *                     = 0x61,验证B密钥
 *         unsigned char ucAddr,块地址
 *         pKey,密码
 *         pSnr,卡片序列号,4字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdAuthState ( unsigned char ucAuth_mode, unsigned char ucAddr, unsigned char * pKey, unsigned char * pSnr )
{
    char cStatus;
	  unsigned char uc, ucComMF522Buf [ MAXRLEN ];
    unsigned int 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 );   
 
    cStatus = PcdComMF522 ( PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, & ulLen );
    if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) )
	{
		cStatus = MI_ERR; 
    }
    return cStatus;
		
}
 
/*
 * 函数名:PcdIncrement
 * 描述  :增加数据到M1卡一块
 * 输入  :unsigned char ucAddr,块地址
 *         pData,写入的数据,16字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdIncrement ( unsigned char ucAddr, unsigned char * pData )
{
    char cStatus;
    unsigned char uc, ucComMF522Buf [ MAXRLEN ];
    unsigned int ulLen;
 
    ucComMF522Buf [ 0 ] = PICC_INCREMENT;
    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 )
    {
      for ( uc = 0; uc < 4; uc ++ )
			  ucComMF522Buf [ uc ] = * ( pData + uc );  
      CalulateCRC ( ucComMF522Buf, 4, & ucComMF522Buf [ 4 ] );
      cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, & ulLen );
    if( cStatus != MI_ERR )
    {
    	cStatus = MI_OK;
    }
    }
    if( cStatus == MI_OK )
    {
    ucComMF522Buf [ 0 ] = PICC_TRANSFER;
    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;   
    } 
    return cStatus;
	
}



/*
 * 函数名:PcdRead
 * 描述  :读取M1卡一块数据
 * 输入  :unsigned char ucAddr,块地址
 *         pData,读出的数据,16字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdRead ( unsigned char ucAddr, unsigned char * pData )
{
    char cStatus;
	  unsigned char uc, ucComMF522Buf [ MAXRLEN ]; 
    unsigned int 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;
 
}
 
 
/*
 * 函数名:PcdHalt
 * 描述  :命令卡片进入休眠状态
 * 输入  :无
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdHalt( void )
{
    unsigned char ucComMF522Buf [ MAXRLEN ]; 
    unsigned int  ulLen;
 
    ucComMF522Buf [ 0 ] = PICC_HALT;
    ucComMF522Buf [ 1 ] = 0;
    CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
    	PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
    return MI_OK;
	
}
 
 
char IC_CMT ( unsigned char * UID, unsigned char * KEY, unsigned char RW, unsigned char addr, unsigned char * Dat )
{
    unsigned char ucArray_ID [ 4 ] = { 0 };//先后存放IC卡的类型和UID(IC卡序列号)
    unsigned char ICstate=MI_ERR;
 
    ICstate=PcdRequest ( 0x52, ucArray_ID );//寻卡
    if(ICstate==MI_OK)
    {
	    UID[1]=ucArray_ID[0];
	    UID[2]=ucArray_ID[1];
	    UID[3]=ucArray_ID[2];
	    UID[4]=ucArray_ID[3];
    }
    if(ICstate==MI_OK)
    {
      ICstate=MI_ERR;
      ICstate=PcdAnticoll ( UID+1 );//防冲撞
    }
    if(ICstate==MI_OK)
    {
      ICstate=MI_ERR;
      ICstate=PcdSelect ( UID+1 );//选定卡
    }
	/*
    if(ICstate==MI_OK)
    {
      ICstate=MI_ERR;
      ICstate=PcdAuthState ( 0x60, addr, KEY, UID );//校验
    }
    if(ICstate==MI_OK)
    {
        ICstate=MI_ERR;
        if ( RW==1 )//读写选择,1是读,0是写,2是增,3是减
            ICstate=PcdRead( addr, Dat );
        else if(RW==2)
            ICstate=PcdIncrement( addr, Dat );
        else 
            ICstate=PcdWrite( addr, Dat );
    }*/
    if(ICstate==MI_OK)
    {
      ICstate=MI_ERR;
      ICstate=PcdHalt ();
    }
    return ICstate;
	 
}
 
/*
 * 函数名:RC522_Init
 * 描述  :初始化RC522 
 * 输入  :无
 * 返回  : 无
 * 调用  :外部调用
 */
void RC522_Init ( void )
{
	RC522_Reset_Disable();
	RC522_CS_Disable();
	PcdReset ();
	M500PcdConfigISOType ( 'A' );//设置工作方式
	
}
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/455294.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

POS 之 验证者如何才能提议区块

验证者提议区块 验证者帐户提议区块。 验证者帐户由节点运营商(可以是AWS等待云服务商)管理&#xff0c;节点运营商运行验证者软件作为其执行和共识客户端的一部分&#xff0c;并且已经向存款合约中存入了至少 32 个以太币 然而&#xff0c;每个验证者只是偶尔负责提议一个区块…

imagemagick深度系统(deepin)安装

背景&#xff1a; 为了试用MoneyPrinter&#xff0c;需要配置imagemagick软件。但是没有适配深度系统的软件包。需要自己编译后安装。 安装&#xff1a; 下载源码 解压(tar xvfz ImageMagick.tar.gz)后进入目录&#xff08;cd ImageMagick-7.1.1&#xff09;&#xff0c;使用…

第十四届蓝桥杯省赛真题 Java B 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 阶乘求和试题 B: 幸运数字试题 C: 数组分割试题 D: 矩形总面积试题 E: 蜗牛试题 F: 合并区域试题 G : \mathrm{G}: G: 买二赠一试题 H \mathrm{H} H : 合并石子试题 I&#xff1a;最大开支试题 J : \mathrm{J}: J: 魔法阵 发现宝藏 前…

Pytorch学习 day14(模型的验证步骤)

如何利用已经训练好的模型&#xff0c;验证它的结果&#xff0c;步骤如下&#xff1a; 步骤一&#xff1a;加载测试输入并更改为合适尺寸 保存图片到指定文件夹下&#xff0c;注意是否为同级目录注意&#xff1a;返回上一级目录为“…/xxx"有时&#xff0c;我们自己的输…

WRF模型运行教程(ububtu系统)--II.ARWpost安装

一、ARWpost简介 ARWpost 是一个把 WRF 结果转为 GrADS 或 Vis5D 可以辨识的数据格式的软件&#xff0c;就是WRF运行结束以后&#xff0c;把WRF的结果变成咱们平时比较常用的数据格式。 二、下载和安装ARWpos_V3 1.ARWpos_V3安装前准备 # 进入Build_WRF文件夹 cd Build_WRF …

Devin,第一位AI软件工程师

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

已经连接过的网络的密码忘记了,怎么快速找回?

使用笔记本电脑曾经连接过一些无线路由器&#xff0c;时间久了&#xff0c;密码可能就忘记了。再使用其他设备连接时&#xff0c;就需要尝试去找到这个密码。本片文章就是通过几个命令快速找到之前使用笔记本电脑曾经连接过的无线网络的密码。 第一步、查看曾经连接过哪些无线网…

Django框架的全面指南:从入门到高级【第128篇—Django框架】

Django框架的全面指南&#xff1a;从入门到高级 Django是一个高效、功能强大的Python Web框架&#xff0c;它被广泛用于构建各种规模的Web应用程序。无论是初学者还是有经验的开发人员&#xff0c;都可以从入门到掌握Django的高级技巧。在本指南中&#xff0c;我们将带你逐步了…

软考高级:面向对象分析概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Celery知识

celery介绍 # celery 的概念&#xff1a; * 翻译过来是芹菜 * 官网&#xff1a;https://docs.celeryq.dev/en/stable/ # 是分布式的异步任务框架&#xff1a; 分布式&#xff1a;一个任务&#xff0c;拆成多个任务在不同机器上做 异步任务&#xff1a;后台执行…

【AI大模型应用开发】【LangChain系列】9. 实用技巧:大模型的流式输出在 OpenAI 和 LangChain 中的使用

大家好&#xff0c;我是同学小张&#xff0c;日常分享AI知识和实战案例欢迎 点赞 关注 &#x1f44f;&#xff0c;持续学习&#xff0c;持续干货输出。v: jasper_8017 一起交流&#x1f4ac;&#xff0c;一起进步&#x1f4aa;。微信公众号也可搜【同学小张】 &#x1f64f; 本…

六 超级数据查看器 讲解稿 详情1 概述

六 超级数据查看器 讲解稿 详情1 概述 点此此处 以新界面 打开B站 当前视频教程 APP下载地址 百度 下载地址 ​ 讲解稿全文&#xff1a; 大家好&#xff0c;今天我们讲解一下超级数据查看器详情界面。由于内容较多&#xff0c;讲解要分为7集&#xff0c;这是第一集 首…

Python导入类说一说

要在Python中导入一个类&#xff0c;需要使用import关键字。 详细去看下面的代码 1、多例类 class Restaurant:餐馆类def __init__(self,restaurant_name,cuisine_type):#类的属性self.restaurant_name restaurant_nameself.cuisine_type cuisine_type# self.stregth_leve…

如何利用ChatGPT联系英语口语和听写!分享一些Prompt!

参考文章 ChatGPT4升级方法 namecheap购买方法 sora namecheap 支付 首先先看ChatGPT修改英语作文的能力 足以证明ChatGPT的能力 ChatGPT英语练习 口语&#xff1a; 实时交谈纠错发音纠错语句 写作&#xff1a; 写作建议构思文本 模拟考试&#xff1a; 雅思、托福和…

论文阅读——Vision Transformer with Deformable Attention

Vision Transformer with Deformable Attention 多头自注意力公式化为&#xff1a; 第l层transformer模块公式化为&#xff1a; 在Transformer模型中简单地实现DCN是一个non-trivial的问题。在DCN中&#xff0c;特征图上的每个元素都单独学习其偏移&#xff0c;其中HWC特征图上…

BUGKU-WEB never_give_up

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; 解题思路 F12查看请求和响应&#xff0c;查找线索 相关工具 base64解码URL解码Burp Suit抓包 解题步骤 F12查看请求和响应&#xff0c;发现一行注释包含一个文件名称【1p.html】&#xff0c;这应该就是提…

操作系统内功篇:使用说明

本专栏是我阅览大佬小林coding写的电子书《图解系统》的一些总结并参杂一些我个人学习的补充&#xff0c;博客大纲是用的大佬的纲要。 暂时打算更新这么多&#xff0c;在以后的学习的过程中再慢慢更新......... 此文章会实时更新更新进程...........

什么是Ipython

IPython&#xff08;Interactive Python&#xff09;是一个增强版的Python交互式解释器。它在标准Python解释器的基础上添加了许多有用的功能&#xff0c;旨在提高你编程时的效率和体验。IPython的核心特性包括但不限于以下几点&#xff1a; 增强的交互性&#xff1a;IPython提…

18. 查看帖子详情

文章目录 一、建立路由二、开发GetPostDetailHandler三、编写logic四、编写dao层五、编译测试运行 一、建立路由 router/route.go v1.GET("/post/:id", controller.GetPostDetailHandler)二、开发GetPostDetailHandler controller/post.go func GetPostDetailHand…

linux命令深入研究——cat

cat命令&#xff0c;“猫”&#xff0c;可以理解为瞄一眼文件内容&#xff0c;其中可以用重定向符号对文件进行一些修改&#xff0c;如增加&#xff0c;删除文件内容&#xff0c;其命令参数如-n&#xff0c;-s&#xff0c;-b可以输出带有行号的行 如果想要快速删除文件内容&…