一、硬件设计
硬件接线:
SPI_NSS(CS) -- PA4
SPI_SCK-- PA5
SPI_MISO -- PA6
SPI_MOSI -- PA7
SPI_RST -- PD2
二、软件设计
本项目用到的是IO口模拟SPI,STM32Cubemx直接将PA4、PA5、PA7、PD2配置为推挽输出,PA6配置为输入即可。
RC522.c
#include "rc522.h"
#define RC522_DELAY() delay_us ( 2 )
#define fac_us 72 //时钟频率,单位MHZ
uint32_t RC522_ID1 = 0xED0B562D; //小圆球ID
void Get_RC522(void)
{
uint32_t writeValue = 100;
uint32_t readValue;
char cStr [ 30 ];
uint8_t ucArray_ID [ 4 ]; /*先后存放IC卡的类型和UID(IC卡序列号)*/
uint8_t ucStatusReturn; /*返回状态*/
static uint8_t Rc_Timeout;
uint8_t status;
uint8_t Card_ID[4];
HAL_Delay(100);
/*寻卡*/
while( (ucStatusReturn = PcdRequest ( PICC_REQIDL, ucArray_ID )) != MI_OK )
{
/*若失败再次寻卡*/
Rc_Timeout++;
HAL_Delay(100);
//printf ( "寻卡失败\n" );
ucStatusReturn = PcdRequest ( PICC_REQIDL, ucArray_ID ); //PICC_REQALL PICC_REQIDL
if(Rc_Timeout >= 10)
{
Rc_Timeout = 0;
break;
}
}
if ( ucStatusReturn == MI_OK )
{
printf ( "寻卡成功\n" );
status = PcdAnticoll(Card_ID);
//判断读取的ID是否为的小圆球ID,是的话再做操作。
if(status)
{
if(Card_ID[0] == ((RC522_ID1 & 0xFF000000) >> 24) )
if(Card_ID[1] == ((RC522_ID1 & 0x00FF0000) >> 16))
if(Card_ID[2] == ((RC522_ID1 & 0x0000FF00) >> 8))
if(Card_ID[3] == ((RC522_ID1 & 0x000000FF) >>0 ))
printf("小圆球\n");
}
}
}
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us; //需要的节拍数
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
}
}
/**
* @brief RC522_Init
* @param 无
* @retval 无
*/
void RC522_Init ( void )
{
// RC522_Reset_Disable();
// RC522_CS_Disable();
PcdReset ();/*RC522相关*/
HAL_Delay(50);
PcdReset();//复位RC522读卡器
HAL_Delay(10);
PcdReset();//复位RC522读卡器
HAL_Delay(10);
PcdAntennaOff();//关闭天线发射
HAL_Delay(10);
PcdAntennaOn();//开启天线发射
// M500PcdConfigISOType ( 'A' );/*RC52射频模 设置工作方式*/
printf("RFID-MFRC522 初始化完成\r\nFindCard Starting ...\r\n");
}
/**
* @brief IC测试函数
* @param 无
* @retval 无
*/
extern uint8_t KeyValue[]; // 卡A密钥
void IC_test ( void )
{
uint32_t writeValue = 100;
uint32_t readValue;
char cStr [ 30 ];
uint8_t ucArray_ID [ 4 ]; /*先后存放IC卡的类型和UID(IC卡序列号)*/
uint8_t ucStatusReturn; /*返回状态*/
static uint8_t Rc_Timeout;
while ( 1 )
{
/*寻卡*/
if ( ( ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ) ) != MI_OK )
{
/*若失败再次寻卡*/
Rc_Timeout++;
HAL_Delay(1000);
printf ( "寻卡失败\n" );
ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ); //PICC_REQALL PICC_REQIDL
if(Rc_Timeout >= 10)
{
Rc_Timeout = 0;
break;
}
}
if ( ucStatusReturn == MI_OK )
{
printf ( "寻卡成功\n" );
//Voice_Send("RC522 OK");
//delay_ms(2000);
HAL_Delay(2000);
break;
// /*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
// if ( PcdAnticoll ( ucArray_ID ) == MI_OK )
// {
// PcdSelect(ucArray_ID);
//
// PcdAuthState( PICC_AUTHENT1A, 0x11, KeyValue, ucArray_ID );//校验密码
// WriteAmount(0x11,writeValue); //写入金额
// if(ReadAmount(0x11,&readValue) == MI_OK) //读取金额
// {
// writeValue +=100;
// sprintf ( cStr, "The Card ID is: %02X%02X%02X%02X",ucArray_ID [0], ucArray_ID [1], ucArray_ID [2],ucArray_ID [3] );
// printf ( "%s\r\n",cStr ); //打印卡片ID
//
// printf ("余额为:%d\r\n",readValue);
// sprintf ( cStr, "TThe residual amount: %d", readValue);
// PcdHalt();
// }
// }
}
}
}
/**
* @brief 向RC522发送1 Byte 数据
* @param byte,要发送的数据
* @retval RC522返回的数据
*/
void SPI_RC522_SendByte ( uint8_t byte )
{
uint8_t counter;
for(counter=0;counter<8;counter++)
{
if ( byte & 0x80 )
RC522_MOSI_1 ();
else
RC522_MOSI_0 ();
RC522_DELAY();
RC522_SCK_0 ();
RC522_DELAY();
RC522_SCK_1();
RC522_DELAY();
byte <<= 1;
}
}
/**
* @brief 从RC522发送1 Byte 数据
* @param 无
* @retval RC522返回的数据
*/
uint8_t SPI_RC522_ReadByte ( void )
{
uint8_t counter;
uint8_t SPI_Data;
for(counter=0;counter<8;counter++)
{
SPI_Data <<= 1;
RC522_SCK_0 ();
RC522_DELAY();
if ( RC522_MISO_GET() == 1)
SPI_Data |= 0x01;
RC522_DELAY();
RC522_SCK_1 ();
RC522_DELAY();
}
return SPI_Data;
}
/**
* @brief 读RC522寄存器
* @param ucAddress,寄存器地址
* @retval 寄存器的当前值
*/
uint8_t ReadRawRC ( uint8_t ucAddress )
{
uint8_t ucAddr, ucReturn;
ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;
RC522_CS_Enable();
SPI_RC522_SendByte ( ucAddr );
ucReturn = SPI_RC522_ReadByte ();
RC522_CS_Disable();
return ucReturn;
}
/**
* @brief 写RC522寄存器
* @param ucAddress,寄存器地址
* @param ucValue,写入寄存器的值
* @retval 无
*/
void WriteRawRC ( uint8_t ucAddress, uint8_t ucValue )
{
uint8_t ucAddr;
ucAddr = ( ucAddress << 1 ) & 0x7E;
RC522_CS_Enable();
SPI_RC522_SendByte ( ucAddr );
SPI_RC522_SendByte ( ucValue );
RC522_CS_Disable();
}
/**
* @brief 对RC522寄存器置位
* @param ucReg,寄存器地址
* @param ucMask,置位值
* @retval 无
*/
void SetBitMask ( uint8_t ucReg, uint8_t ucMask )
{
uint8_t ucTemp;
ucTemp = ReadRawRC ( ucReg );
WriteRawRC ( ucReg, ucTemp | ucMask ); // set bit mask
}
/**
* @brief 对RC522寄存器清位
* @param ucReg,寄存器地址
* @param ucMask,清位值
* @retval 无
*/
void ClearBitMask ( uint8_t ucReg, uint8_t ucMask )
{
uint8_t ucTemp;
ucTemp = ReadRawRC ( ucReg );
WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) ); // clear bit mask
}
/**
* @brief 开启天线
* @param 无
* @retval 无
*/
void PcdAntennaOn ( void )
{
uint8_t uc;
uc = ReadRawRC ( TxControlReg );
if ( ! ( uc & 0x03 ) )
SetBitMask(TxControlReg, 0x03);
}
/**
* @brief 关闭天线
* @param 无
* @retval 无
*/
void PcdAntennaOff ( void )
{
ClearBitMask ( TxControlReg, 0x03 );
}
/**
* @brief 复位RC522
* @param 无
* @retval 无
*/
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 );
//定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
WriteRawRC ( ModeReg, 0x3D );
WriteRawRC ( TReloadRegL, 30 ); //16位定时器低位
WriteRawRC ( TReloadRegH, 0 ); //16位定时器高位
WriteRawRC ( TModeReg, 0x8D ); //