5-W806-RC522-SPI

这篇具有很好参考价值的文章主要介绍了5-W806-RC522-SPI。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

main.c

#include <stdio.h>
#include "wm_hal.h"
#include "rc522.h"

int main(void)
{
	SystemClock_Config(CPU_CLK_160M);
	printf("enter main\r\n");
	HAL_Init();

	RC522_Init();

	PcdReset();
	M500PcdConfigISOType ( 'A' );//设置工作方式
	
	IC_test();
	
	return 0;
}

rc522.c

#include "rc522.h"

#define   macRC522_DELAY()  SPI_Delay_Us(160,200)

/*
 * 函数名:SPI_RC522_SendByte
 * 描述  :向RC522发送1 Byte 数据
 * 输入  :byte,要发送的数据
 * 返回  : RC522返回的数据
 * 调用  :内部调用
 */
void SPI_RC522_SendByte ( unsigned char byte )
{
    unsigned char counter;
    for(counter=0;counter<8;counter++)
    {
			if ( byte & 0x80 )
				MOSI_H();
			else
				MOSI_L();
//			SPI_Delay_Us(160, 3 );
			macRC522_DELAY();
			SCK_L ();
//			SPI_Delay_Us(160, 1 );
//			SPI_Delay_Us(160, 3 );
			macRC522_DELAY();
			SCK_H();
//			SPI_Delay_Us(160, 3 );
			macRC522_DELAY();
			byte <<= 1;
    }
}


/*
 * 函数名:SPI_RC522_ReadByte
 * 描述  :从RC522发送1 Byte 数据
 * 输入  :无
 * 返回  : RC522返回的数据
 * 调用  :内部调用
 */
unsigned char SPI_RC522_ReadByte ( void )
{
	unsigned char counter;
	unsigned char SPI_Data=0;
	for(counter=0;counter<8;counter++)
	{
		SPI_Data <<= 1;
		SCK_L ();
//			SPI_Delay_Us(160, 3 );
		macRC522_DELAY();
		if ( MISO() == 1)
		SPI_Data |= 0x01;
//			SPI_Delay_Us(160, 2 );
//			SPI_Delay_Us(160, 3 );
		macRC522_DELAY();
		SCK_H ();
//			SPI_Delay_Us(160, 3 );
		macRC522_DELAY();
	}
	return SPI_Data;
}


/*
 * 函数名:ReadRawRC
 * 描述  :读RC522寄存器
 * 输入  :ucAddress,寄存器地址
 * 返回  : 寄存器的当前值
 * 调用  :内部调用
 */
unsigned char ReadRawRC ( unsigned char ucAddress )
{
	unsigned char ucAddr, ucReturn;
	ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;
	NSS_L();
	SPI_RC522_SendByte ( ucAddr );
	ucReturn = SPI_RC522_ReadByte ();
	NSS_H();
	return ucReturn;
}


/*
 * 函数名:WriteRawRC
 * 描述  :写RC522寄存器
 * 输入  :ucAddress,寄存器地址
 *         ucValue,写入寄存器的值
 * 返回  : 无
 * 调用  :内部调用
 */
void WriteRawRC ( unsigned char ucAddress, unsigned char ucValue )
{
	unsigned char ucAddr;
	ucAddr = ( ucAddress << 1 ) & 0x7E;
	NSS_L();
	SPI_RC522_SendByte ( ucAddr );
	SPI_RC522_SendByte ( ucValue );
	NSS_H();
}


/*
 * 函数名: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 );
}


/*
 * 函数名:PcdRese
 * 描述  :复位RC522
 * 输入  :无
 * 返回  : 无
 * 调用  :外部调用
 */
void PcdReset ( void )
{
	RST_H();
	SPI_Delay_Us(160, 1 );
	RST_L();
	SPI_Delay_Us(160, 1 );
	RST_H();
	SPI_Delay_Us(160, 1 );
	WriteRawRC ( CommandReg, 0x0f );
	while ( ReadRawRC ( CommandReg ) & 0x10 );
	SPI_Delay_Us(160, 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
}


/*
 * 函数名:M500PcdConfigISOType
 * 描述  :设置RC522的工作方式
 * 输入  :ucType,工作方式
 * 返回  : 无
 * 调用  :外部调用
 */
void M500PcdConfigISOType ( unsigned char ucType )
{
	if ( ucType == 'A')                     //ISO14443_A
  {
		ClearBitMask ( Status2Reg, 0x08 );
    WriteRawRC ( ModeReg, 0x3D );//3F
		WriteRawRC ( RxSelReg, 0x86 );//84
		WriteRawRC( RFCfgReg, 0x7F );   //4F
		WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
		WriteRawRC ( TReloadRegH, 0 );
		WriteRawRC ( TModeReg, 0x8D );
		WriteRawRC ( TPrescalerReg, 0x3E );
		SPI_Delay_Us(160, 2 );
		PcdAntennaOn ();//开天线
   }
}


/*
 * 函数名: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 long * pOutLenBit )
{
    char cStatus = MI_ERR;
    unsigned char ucIrqEn   = 0x00;
    unsigned char ucWaitFor = 0x00;
    unsigned char ucLastBits;
    unsigned char ucN;
    unsigned long 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 long 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 long 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 );
}


/*
 * 函数名:PcdSelect
 * 描述  :选定卡片
 * 输入  :pSnr,卡片序列号,4字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdSelect ( unsigned char * pSnr )
{
    char ucN;
    unsigned char uc;
	unsigned char ucComMF522Buf [ MAXRLEN ];
    unsigned long  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 long 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;
}

/*
 * 函数名: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 long 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;
}


/*
 * 函数名: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 long 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 long  ulLen;
	ucComMF522Buf [ 0 ] = PICC_HALT;
	ucComMF522Buf [ 1 ] = 0;
	CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
	PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
	return MI_OK;
}

void IC_CMT ( unsigned char * UID, unsigned char * KEY, unsigned char RW, unsigned char * Dat )
{
  unsigned char ucArray_ID [ 4 ] = { 0 };//先后存放IC卡的类型和UID(IC卡序列号)
  PcdRequest ( 0x52, ucArray_ID );//寻卡
  PcdAnticoll ( ucArray_ID );//防冲撞
  PcdSelect ( UID );//选定卡
  PcdAuthState ( 0x60, 0x10, KEY, UID );//校验
  if ( RW )//读写选择,1是读,0是写
	  PcdRead ( 0x10, Dat );
  else
	  PcdWrite ( 0x10, Dat );
PcdHalt ();
}


void RC522_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};											//初始化GPIO结构体
	
	__HAL_RCC_GPIO_CLK_ENABLE();													//打开GPIO时钟

	GPIO_InitStruct.Pin = SPI_SCK_PIN | SPI_MOSI_PIN | SPI_MISO_PIN | SPI_NSS_PIN | SPI_RST_PIN;									//配置引脚
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;										//配置成输出模式
	GPIO_InitStruct.Pull = GPIO_NOPULL;												//不拉
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);											//引脚初始化

	RST_H();

	NSS_H();
	
}


void IC_test ( void )
{
	unsigned char ucArray_ID [ 4 ];                                                                                             //先后存放IC卡的类型和UID(IC卡序列号)
	unsigned char ucStatusReturn;                                                                                               //返回状态

	while ( 1 )
	{
		if ((ucStatusReturn = PcdRequest(PICC_REQALL,ucArray_ID)) != MI_OK )                                    //寻卡
			ucStatusReturn = PcdRequest (PICC_REQALL,ucArray_ID);		                                                 //若失败再次寻卡
		if ( ucStatusReturn == MI_OK  )
		{
			if ( PcdAnticoll (ucArray_ID) == MI_OK )                                                                   //防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)
			{
					printf("id correct\r\n");
			}
		}
	}
}

rc522.h

#include "spi_ctrl.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                 0x26
#define 	MI_NOTAGERR           0xcc
#define 	MI_ERR                0xbb



#define          macDummy_Data              0x00


void             PcdReset                   ( void );                       //复位
void             M500PcdConfigISOType       ( unsigned char type );                    //工作方式
char             PcdRequest                 ( unsigned char req_code, unsigned char * pTagType ); //寻卡
char             PcdAnticoll                ( unsigned char * pSnr);                   //读卡号

/*********************************** 函数 *********************************************/
void RC522_Init(void);
void IC_test ( void );

spi_crtl.c

/**
 * Copyright (c) 2022-2023£¬HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#include "spi_ctrl.h"

/* CPOL = 0, CPHA = 0, MSB first */
uint8_t SOFT_SPI_RW_MODE0(uint8_t write_dat)
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
        if( write_dat & 0x80 )
            MOSI_H();
        else
            MOSI_L();
        write_dat <<= 1;
        SPI_Delay_Us(160,1);
        SCK_H();
        read_dat <<= 1;
        if( MISO() )
            read_dat++;
        SPI_Delay_Us(160,1);
        SCK_L();
        SPI_Delay_Us(160,1);
    }
    return read_dat;
}

/* CPOL=0£¬CPHA=1, MSB first */
uint8_t SOFT_SPI_RW_MODE1(uint8_t write_dat)
{
    uint8_t i, read_dat;

    for( i = 0; i < 8; i++ )
    {
        SCK_H();
        if( write_dat & 0x80 )
            MOSI_H();
        else
            MOSI_L();
        write_dat <<= 1;
        SPI_Delay_Us(160,100);
        SCK_L();
        read_dat <<= 1;
        if(MISO())
            read_dat++;
        SPI_Delay_Us(160,100);
	}
    return read_dat;
}

/* CPOL=1£¬CPHA=0, MSB first */
uint8_t SOFT_SPI_RW_MODE2(uint8_t write_dat)
{
    uint8_t i, read_dat;

    for( i = 0; i < 8; i++ )
    {
        if( write_dat & 0x80 )
            MOSI_H();
        else
            MOSI_L();
        write_dat <<= 1;
        SPI_Delay_Us(160,1);
        SCK_L();
        read_dat <<= 1;
        if(MISO())
            read_dat++;
        SPI_Delay_Us(160,1);
        SCK_H();
	}
	return read_dat;
}

/* CPOL = 1, CPHA = 1, MSB first */
uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
        SCK_L();
        if( write_dat & 0x80 )
            MOSI_H();
        else
            MOSI_L();
        write_dat <<= 1;
        SPI_Delay_Us(160,1);
        SCK_H();
        read_dat <<= 1;
        if( MISO() )
            read_dat++;
        SPI_Delay_Us(160,1);
    }
    return read_dat;
}

spi_crtl.h

/**
 * Copyright (c) 2022-2023,HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __SPI_CTRL_H__
#define __SPI_CTRL_H__

#include "spi_io.h"

#define SPI_START_COMMUNICATION     NSS_L()
#define SPI_STOP_COMMUNICATION      NSS_H()

/**
 * CPOL 配置 SPI 总线的极性
 * CPHA 配置 SPI 总线的相位
 *
 * 模式0:CPOL=0,CPHA =0  MSB first
 *      SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据)
 * 模式1:CPOL=0,CPHA =1  MSB first
 *      SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据)
 * 模式2:CPOL=1,CPHA =0  MSB first
 *      SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据)
 * 模式3:CPOL=1,CPHA =1  MSB first
 *      SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据)
 */

/* CPOL = 0, CPHA = 0,  MSB first*/
uint8_t SOFT_SPI_RW_MODE0(uint8_t write_dat);
/* CPOL=0,CPHA=1, MSB first */
uint8_t SOFT_SPI_RW_MODE1(uint8_t write_dat);
/* CPOL=1,CPHA=0, MSB first */
uint8_t SOFT_SPI_RW_MODE2(uint8_t write_dat);
/* CPOL = 1, CPHA = 1, MSB first */
uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat );

#endif

spi_io.c

/**
 * Copyright (c) 2022-2023£¬HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#include "spi_io.h"

static void SET_PIN_OUT(uint32_t PIN)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};											//初始化GPIO结构体
	
	__HAL_RCC_GPIO_CLK_ENABLE();													//打开GPIO时钟

	GPIO_InitStruct.Pin = PIN;														//配置引脚
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;										//配置成输出模式
	GPIO_InitStruct.Pull = GPIO_NOPULL;												//不拉
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);											//引脚初始化
}

void MOSI_H(void)
{
    SET_PIN_OUT(SPI_MOSI_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_MOSI_PIN, GPIO_PIN_SET);
}
void MOSI_L(void)
{
    SET_PIN_OUT(SPI_MOSI_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_MOSI_PIN, GPIO_RESET);
}
void SCK_H(void)
{
    SET_PIN_OUT(SPI_SCK_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_SCK_PIN, GPIO_PIN_SET);
}
void SCK_L(void)
{
    SET_PIN_OUT(SPI_SCK_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_SCK_PIN, GPIO_RESET);
}
uint32_t MISO(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};											//初始化GPIO结构体
	
	__HAL_RCC_GPIO_CLK_ENABLE();													//打开GPIO时钟

	GPIO_InitStruct.Pin = SPI_MISO_PIN;														//配置引脚
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;										//配置成
	GPIO_InitStruct.Pull = GPIO_NOPULL;												//不拉
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);											//引脚初始化

    return HAL_GPIO_ReadPin(GPIOA, SPI_MISO_PIN);
}
void NSS_H(void)
{
    SET_PIN_OUT(SPI_NSS_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_NSS_PIN, GPIO_PIN_SET);
}
void NSS_L(void)
{
    SET_PIN_OUT(SPI_NSS_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_NSS_PIN, GPIO_RESET);
}
void RST_H(void)
{
    SET_PIN_OUT(SPI_RST_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_RST_PIN, GPIO_PIN_SET);
}
void RST_L(void)
{
    SET_PIN_OUT(SPI_RST_PIN);
    HAL_GPIO_WritePin(GPIOA, SPI_RST_PIN, GPIO_RESET);
}

void SPI_Delay_Us(uint8_t freq,uint32_t time)
{
    uint32_t i;
    uint16_t num = 90;
    switch(freq)
    {
        case 240: num = 80;break;
        case 160: num = 53;break;
        default: printf("delay input freq err...default set 240MHZ us time \r\n ");break;
    }
    
    for (i = 0; i < (num)*time; i++)
    {
        __NOP();
    }
}

void SPI_Delay_Ms(uint8_t freq,uint32_t time)
{
    uint32_t i;
    uint16_t num = 90;
    switch(freq)
    {
        case 240: num = 80;break;
        case 160: num = 53;break;
        default: printf("delay input freq err...default set 240MHZ us time \r\n ");break;
    }
    
    for (i = 0; i < (num)*time*1000; i++)
    {
        __NOP();
    }
}

spi_io.h文章来源地址https://www.toymoban.com/news/detail-674425.html

/**
 * Copyright (c) 2022-2023£¬HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */

#include "wm_hal.h"

#define SPI_SCK_PIN             GPIO_PIN_0		//SCL
#define SPI_MOSI_PIN            GPIO_PIN_1		//MOSI
#define SPI_MISO_PIN            GPIO_PIN_2		//MISO
#define SPI_NSS_PIN             GPIO_PIN_3		//SDA
#define SPI_RST_PIN             GPIO_PIN_4		//RST,可不接

#define GPIO_MODEL_INPUT        0
#define GPIO_MODEL_OUTPUT       1

#define GPIO_OUTPUT_DISABLE     0
#define GPIO_OUTPUT_ENABLE      1

#define GPIO_RESET              0
#define GPIO_SET                1

void MOSI_H(void);
void MOSI_L(void);
void SCK_H(void);
void SCK_L(void);
uint32_t MISO(void);
void NSS_H(void);
void NSS_L(void);
void RST_H(void);
void RST_L(void);
void SPI_Delay_Us(uint8_t freq,uint32_t time);
void SPI_Delay_Ms(uint8_t freq,uint32_t time);

到了这里,关于5-W806-RC522-SPI的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32--RFID无线射频技术(RC522刷卡模块)

    1、RFID的概念  射频识别,即RFID是Radio Frequency Ident ificat ion的缩写,又称无线射频识别,是一.种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需识别系统与特定目标之间建立机械或光学接触。一套完整RFID硬件统由Reader 与Transponder 两部份组成,其动作原理

    2024年01月19日
    浏览(39)
  • ESP8266 对接RFID RC522 设备读取门禁卡

    在本篇文章中,您将 使用ESP8266,连接到RFID RC522 设备上,读取门禁卡上的设备信息。本文提供了一个实用示例,以帮助您更好地学习它。 ESP8266开发板 rfid-rc522 杜邦线 面包板 实物图 接线图: 想要驱动RC522模块对IC卡(这里用的是M1卡型号是S50)进行读写操作,一定要有以下

    2024年02月05日
    浏览(127)
  • micropython,esp32,RFID-RC522的使用

    一、RFID 射频技术(RF)是Radio Frequency的缩写。较常见的应用有无线射频识别(Radio Frequency Identification,RFID),常称为感应式电子晶片或近接卡、感应卡、非接触卡、电子标签、电子条码等。其原理为由扫描器发射一特定频率之无线电波能量给接收器,用以驱动接收器电路将

    2024年02月13日
    浏览(44)
  • STM32+RC522(实现对ic卡的增删改查)

    这是基于STM32F103C8T6和RFID识别模块,实现的对ic卡的增删改查,能够读取卡号,对卡内指定的区域进行数据修改。 感谢 物联网小菜鸟一枚 大佬代码思路 https://blog.csdn.net/m0_69428059/article/details/124259091 1.1STM32F103C8T6 1.2RFID-RC522识别模块 1.3按键模块 接线部分 STM32F103C8T6 RC522 PB12 SDA

    2024年02月13日
    浏览(45)
  • 基础篇010.1 STM32驱动RC522 RFID模块之一:基础知识

    目录 1. RFID概述 1.1 RFID工作原理 1.2 RFID分类 1.3 RFID模块 1.4 RFID卡片 1.5 IC卡和ID卡介绍 1.6 IC卡和ID的区分 2. Mifare卡结构原理 2.1 Mifare卡概述 2.2 Mifare非接触式 IC 卡性能简介(M1) 2.2.1 Mifare S50与Mifare S70 2.2.2 S50存储结构 2.2.3 M1射频卡工作原理 2.2.4 M1射频卡与读写器的通讯 2.3 MRF52

    2024年02月09日
    浏览(47)
  • ESP32C3 LuatOS RC522①写入数据并读取M1卡

    LuatOS RC522官方示例  ESP32C3-CORE开发板    程序在数据块8中写入数据{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}

    2024年02月10日
    浏览(50)
  • STM32F103+RFID-RC522模块 实现简单读卡写卡demo

    本仓库发布的程序,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。 本人对任何脚本问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害。 间接使用脚本的任何用户,包括但不限于建立VPS或

    2023年04月09日
    浏览(47)
  • 【XR806开发板试用】简单点灯-- 基于SPI控制W2812矩阵幻彩动图和字幕显示系统

    使用指南 自己踩过的坑 必须app开头 鸿蒙hb 依赖python 环境。建议使用conda虚拟环境 下载开启硬件校验和烧录重启 不是科普文,自行百度 `/*WS2812B Timing sequence ________ | | T0L | 0 code |------|--------------| | T0H |________________| 1 code |---------|--------- --| | T1H |______________| RET code | Treset | |--

    2024年04月13日
    浏览(26)
  • RFID课程设计--基于STM32F103RCT6的智能门禁系统,STM32RCT6+RC522+OLED+DHT11+4*4矩阵键盘

      本次课程设计要求如下,我们团队两人完成了90%的功能。   其中我们设置的是刷卡错误3次不报警,密码输入错3次报警(原理相同,大家根据需要自行修改)   然后暂时只能显示卡号和卡是第几个录入到系统中的,想到身份证号和电话(身份信息)输进去有点长就没

    2024年01月16日
    浏览(78)
  • STM32的SPI硬件CRC校验(个人学习记录)

    一、功能实现         为了保证SPI通信数据的准确性,需要通过对每个数据进行CRC校验,保证设备运行正常。 二、基本原理 SPI通信可以通过以下步骤使用CRC: ● 设置CPOL、CPHA、LSBFirst、BR、SSM、SSI和MSTR的值; ● 在SPI_CRCPR寄存器输入多项式; ● 通过设置SPI_CR1寄存器CRCEN位使

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包