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' );//设置工作方式
	
}
 
  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该充值消费一体机主要基于miniSTM32和RC522模块制作完成。 功能解析: (1)充值 充值的前提是要管理员先刷卡才能进入充值界面,本设计的程序中设定蓝色S50射频卡为管理员身份(如需要可设定多张管理员身份的卡),若不是管理员刷卡则进入不了充值界面,此前提限制了消费者不能随便进入充值模式,既方便了管理员对打卡机的管理,又增加了打卡机的安全性。进入了充值界面后,先由管理员输入相应的充值金额,再到消费者刷卡即可成功充值并显示充值后的余额。 (2)消费 进入消费界面后,管理员输入相应的消费金额,然后消费者刷卡消费,系统先判断此卡是否已解锁,若是未解锁(已挂失)则消费失败返回菜单栏,若是已解锁(已解挂)则进入余额判断,若是余额足够便能成功消费并显示消费后的余额,若是余额不足则会消费失败并显示余额。 (3)查询 查询功能的作用是让消费者查询卡内的信息,包括:卡的身份、是否解锁(挂失)、姓名、学会、卡号、卡内余额。消费者拿到卡后需要记住自己的卡号,因为若是自己的卡不慎丢失了需要输入卡号和密码才能挂失和解挂。 (4)挂失/解挂 消费者进入挂失/解挂界面,输入卡号后按确定,再输入6位密码后按确定,接着选择挂失或者解挂,若是挂失,输入卡号和密码正确即可成功挂失,否则挂失失败;若是解挂,除了需要输入卡号和密码正确之外,还要再拿该卡刷卡进行卡号确认,就是说,消费者需要输入和刷卡的卡号一致并且密码正确才能解挂成功,否则解挂失败。已挂失的卡是不能进行消费操作的。 硬件连接: /************************************* *硬件连接说明: *RC522 <----->MINISTM32 * *1--SDA <----->PB0 *2--SCK <----->PB13 *3--MOSI<----->PB15 *4--MISO<----->PB14 *5--悬空 *6--GND <----->GND *7--RST <----->PB1 *8--3.3V<----->3.3V * *DS18B20与MINISTM32开发板的PA0要连接上 **************************************/ 视频演示: 部分操作界面图: MINISTM32 +RFID程序展示:
这是基于JAVAweb的宠物管理系统完整源码。 一、任务书设计需求 本系统主要是由RFID自动识别技术,通过无线射频方式对宠物的电子标签进行读取,获取宠物的基本信息和在店内的所有消费,然后将数据通过网络传输至服务器。在应用层开发一个管理系统,对宠物信息、店内消费等各种行为进行管理。同时系统需有登录注册功能,宠物信息管理,店内消费管理等功能。 宠物店管理系统主要分为以下模块: 1.RFID模块:由天线和射频电路组成,通过自动识别电子标签,采集数据,采用RFID封装技术将其封装,并传输给服务器。 2.电子标签模块:接收外部信号和发送信号 3.店铺管理模块:管理员可以对店铺商品进行增删改操作,修改、删除顾客宠物信息以及店内消费行为。 4.登录注册模块:新用户可以进行注册和登录5.用户管理模块:对注册用户进行管理 二、设计需求总结 整个系统的设计: (1). 宠物店每来一个新的宠物,就在软件端进行注册、注册时填入宠物的名称,宠物的类型,主人的电话号码、选择一张宠物的图片方便后面展示(图片可以预存几张猫、狗即可)、如果宠物后面在店里有消费也会记录包含时间,这些数据都保存在软件端的数据库里。 (2). 开卡: 新宠物注册之后,需要为这个宠物办理一张电子标签卡,这个卡里存放着这个宠物主人的电话号码,后面要查询这个宠物的信息,就读取整个电子标签里的电话号码,到数据库里查询。 (3). 开卡和查询的数据传输: 设备端与软件端采用 TCP网络方式进行通信;设备端当做TCP客户端,软件端当做TCP服务器;当设备端查询宠物的电子标签时,设备端读取电话号码之后,会通过约定的数据格式通过网络传递给软件端。 当软件端开卡注册时,也会用约定好的数据格式传递给设备端,如果设备端收到数据,开发板上的LED会点亮;这时把IC拿到RC522射频模块上刷一下即可;如果成功写入LED灯就会关闭。 (4). 软件端的设计(这个软件是给店家用的,功能都是针对店家这边方向开发): 有注册界面、登录界面; 主界面上显示店内有所有注册过的宠物信息,每个宠物有图片进行显示、宠物图片下面就显示宠物的名称; 商品界面: 展示一些狗粮、猫粮、药剂、一些宠物周边物品。 用于演示消费功能。 可以预定几个商品即可。 用户可以自己动态添加修改。 管理员界面: 可以对店内的商品进行添加、设计价格、修改宠物的信息等。 查询页面: 输入宠物信息可以查询这个宠物在店里的所有详细信息。 ---根据实际情况动态修改、设计---- 软件端与硬件端的数据格式: (1). 开卡注册数据格式-字符串(软件--->设备): register:13800138000 (2). 设备查询上传的数据格式-字符串(设备--->软件): query:13800138000 如果在设计过程中有问题会进行适当调整。 设备硬件部分: 1. RC522刷卡模块负责对卡进行读写。 2. ESP8266WIFI初始化工作在STA模式,连接到指定WIFI,与软件所在的电脑处于同一个局域网,方便连接软件端的服务器进行数据通信,每次设备开机将会自动连接到程序里设置好WIFI热点和服务器。 3. 设备端上有一个LED灯,用来显示刷卡的状态—成功与否。
项目简介: 本项目采用IDT无线充电3W模块充电,附加外部电压电流采集电路,蓝牙通信和OLED显示屏显示;项目采用易上手的uon开发板,使用两片LG9110驱动芯片驱动电机;并且使用卡片识别快速启动小车无线充电系统,手机蓝牙通信处理控制小车行迹。 硬件说明: 硬件包括基本的DIY小车套件、uon开发板、RC-06蓝牙模块、LG9110驱动芯片、RC522读卡器和主要的IDT无线充电模块; Rc-06蓝牙模块只要是用于手机之间的数据通信,当物体做出相应反应的时候,数据处理回传; IDT及采集电路主要是为充电宝供电和OLED显示充电电压和电流和充电状况; LG9110驱动芯片主要是驱动马达使用,采用本IC主要是电流通过能力在800MA的持续电流,能力较强,外部电路简单; RC522读卡器主要识别卡片,并启动小车内部系统; 软件说明: 软件使用了Fritzing(开源)绘制示意图,使用ArduinoIDE进行代码编译下载,手机使用SPP APP与蓝牙进行通信,相关文档资料和程序代码会以附录的形式上传,欢迎交流学习和提出建议! 视频展示: 点击查看 视频补充: 视频中测试充电电流在330MA左右,由于是充满状态,电压在5.1V左右,否则会小于5V;OLED显示屏由于刷新频率小于50HZ,所以从手机视频中能看到画面刷新的过程。 视频内容顺序简介: 1、 整体效果,包括外部IDT无线充电部分; 2、 刷卡启动小车供电充电系统 3、 IDT无线充电测试,OLED显示当前充电电压电流 4、 蓝牙控制小车动作及app界面 【转载自电子发烧友】

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值