我是靠谱客的博主 无心丝袜,最近开发中收集的这篇文章主要介绍RFID防伪设计(物联网工程课程设计)DAY2---RFID标签读写,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

RFID标签读写

同样是重点内容
今天比较累了,不太想写太多

RFID读写器和RFID标签
程序仍然为野火的例程进行移植

例程中使用的是 SPI 通信协议进行RFID标签读写
但是并未使用硬件 SPI
而是直接使用 软件模拟SPI

里面打开了7个GPIO引脚
硬件连接如下在这里插入图片描述

stm32cubemx

对应上面打开这几个引脚的GPIO
其中有作为输出的 GPIO_OUTPUT
有作为输入的 GPIO_INPUT 注意分别

在这里插入图片描述
直接打开对应引脚就行了
不要硬件上做SPI
软件来实现

由于外设对时序要求比较严格,所以我们这里采用TIM定时器
实现us级别的延迟
ms延迟,可以直接调用 HAL_Delay()函数进行实现
在这里插入图片描述
选用定时器1
clock source选 内部时钟
下面的配置就是需要有一点基本定时器的知识
这里不解释了

keil5

直接上代码,不解释了
同样新建一下文件夹,顺便新建一下延迟函数的文件
在这里插入图片描述
同样是 .c文件和对应的 .h文件

delay.c

#include "delay.h"

extern TIM_HandleTypeDef htim1;

//us延迟
void Delay_us(uint32_t nus)
{
	uint16_t differ = 0xffff - nus - 5;
	//设置定时器2的技术初始值
	__HAL_TIM_SetCounter(&htim1, differ);
	//开启定时器
	HAL_TIM_Base_Start(&htim1);
	while (differ < 0xffff - 5)
	{
		differ = __HAL_TIM_GetCounter(&htim1);
	};
	//关闭定时器
	HAL_TIM_Base_Stop(&htim1);
}


delay.h

#ifndef __DELAY_H
#define __DELAY_H

#include "bsp_system.h"

void Delay_us(uint32_t nus);

#endif /* __DELAY_H */

rc522_config.h

#ifndef __RC522_CONFIG_H
#define	__RC522_CONFIG_H


#include "bsp_system.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

 
 
/*********************************** RC522 引脚定义 *********************************************/
//RC522模块有除了电源还有6个数据引脚,其中IRQ不需要使用,悬空即可,剩下的5个数据引脚连接如下:
//如果RC522需要修改与STM32的连接,则修改这些IO即可,但必须连接到STM32的SPI引脚
//片选,即RC522模块的SDA引脚,PA4 output pp
//#define               RC522_GPIO_CS_CLK_FUN                  RCC_APB2PeriphClockCmd
//#define               RC522_GPIO_CS_CLK                      RCC_APB2Periph_GPIOA
#define               RC522_GPIO_CS_PORT    	                GPIOA			   
#define               RC522_GPIO_CS_PIN		                  GPIO_PIN_4
//#define               RC522_GPIO_CS_Mode		                  GPIO_Mode_Out_PP

//时钟,即RC522模块的SCK引脚,接STM32的SPI的SCK引脚 PA5 output pp
//#define               RC522_GPIO_SCK_CLK_FUN                 RCC_APB2PeriphClockCmd
//#define               RC522_GPIO_SCK_CLK                     RCC_APB2Periph_GPIOA
#define               RC522_GPIO_SCK_PORT    	              GPIOA			   
#define               RC522_GPIO_SCK_PIN		                  GPIO_PIN_5
//#define               RC522_GPIO_SCK_Mode		                GPIO_Mode_Out_PP

// 数据输入,即即RC522模块的MOSI引脚,接STM32的SPI的MOSI引脚 PA7 output pp
//#define               RC522_GPIO_MOSI_CLK_FUN                RCC_APB2PeriphClockCmd
//#define               RC522_GPIO_MOSI_CLK                    RCC_APB2Periph_GPIOA
#define               RC522_GPIO_MOSI_PORT    	              GPIOA			   
#define               RC522_GPIO_MOSI_PIN		                GPIO_PIN_7
//#define               RC522_GPIO_MOSI_Mode		                GPIO_Mode_Out_PP

// 数据输出,即即RC522模块的MISO引脚,接STM32的SPI的MISO引脚 PA6 input floating
//#define               RC522_GPIO_MISO_CLK_FUN                RCC_APB2PeriphClockCmd
//#define               RC522_GPIO_MISO_CLK                    RCC_APB2Periph_GPIOA
#define               RC522_GPIO_MISO_PORT    	              GPIOA			   
#define               RC522_GPIO_MISO_PIN		                GPIO_PIN_6
//#define               RC522_GPIO_MISO_Mode		                GPIO_Mode_IN_FLOATING

//复位,即即RC522模块的RST引脚,接STM32的普通IO即可 PB0 output pp
//#define               RC522_GPIO_RST_CLK_FUN                 RCC_APB2PeriphClockCmd
//#define               RC522_GPIO_RST_CLK                     RCC_APB2Periph_GPIOB
#define               RC522_GPIO_RST_PORT    	              GPIOB		   
#define               RC522_GPIO_RST_PIN		                  GPIO_PIN_0
//#define               RC522_GPIO_RST_Mode		                GPIO_Mode_Out_PP




/*********************************** RC522 函数宏定义*********************************************/
#define          RC522_CS_Enable()         HAL_GPIO_WritePin ( RC522_GPIO_CS_PORT, RC522_GPIO_CS_PIN , GPIO_PIN_RESET)
#define          RC522_CS_Disable()        HAL_GPIO_WritePin ( RC522_GPIO_CS_PORT, RC522_GPIO_CS_PIN , GPIO_PIN_SET)

#define          RC522_Reset_Enable()      HAL_GPIO_WritePin( RC522_GPIO_RST_PORT, RC522_GPIO_RST_PIN, GPIO_PIN_RESET )
#define          RC522_Reset_Disable()     HAL_GPIO_WritePin( RC522_GPIO_RST_PORT, RC522_GPIO_RST_PIN, GPIO_PIN_SET )

#define          RC522_SCK_0()             HAL_GPIO_WritePin( RC522_GPIO_SCK_PORT, RC522_GPIO_SCK_PIN, GPIO_PIN_RESET )
#define          RC522_SCK_1()             HAL_GPIO_WritePin( RC522_GPIO_SCK_PORT, RC522_GPIO_SCK_PIN, GPIO_PIN_SET )

#define          RC522_MOSI_0()            HAL_GPIO_WritePin( RC522_GPIO_MOSI_PORT, RC522_GPIO_MOSI_PIN, GPIO_PIN_RESET )
#define          RC522_MOSI_1()            HAL_GPIO_WritePin( RC522_GPIO_MOSI_PORT, RC522_GPIO_MOSI_PIN, GPIO_PIN_SET )

#define          RC522_MISO_GET()          HAL_GPIO_ReadPin ( RC522_GPIO_MISO_PORT, RC522_GPIO_MISO_PIN )



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



#endif /* __RC522_CONFIG_H */


rc522_config.c

#include "rc522_config.h"

/**
  * @brief  RC522_Init
  * @param  无
  * @retval 无
  */
void RC522_Init(void)
{

  RC522_Reset_Disable();
  RC522_CS_Disable();
}

rc522function.h

#ifndef __RC522_FUNCTION_H
#define	__RC522_FUNCTION_H


//#include "stm32f10x_it.h"
#include "bsp_system.h"
#include "rc522_config.h"

#define          macDummy_Data              0x00
#define 				 RC522_DELAY() 							Delay_us(2)


void IC_test ( void );
void             PcdReset                   ( void );                       //复位
void             M500PcdConfigISOType       ( u8 type );                    //工作方式
char             PcdRequest                 ( u8 req_code, u8 * pTagType ); //寻卡
char             PcdAnticoll                ( u8 * pSnr);                   //读卡号
char             PcdHalt                      ( void );
char             PcdSelect                    ( uint8_t * pSnr );
char             PcdAuthState                 ( uint8_t ucAuth_mode, uint8_t ucAddr, uint8_t * pKey, uint8_t * pSnr );
char             WriteAmount                  ( uint8_t ucAddr, uint32_t pData );
char             ReadAmount                   ( uint8_t ucAddr, uint32_t *pData );
#endif /* __RC522_FUNCTION_H */


rc522_function.c

#include "rc522_function.h"

extern UART_HandleTypeDef huart1;
extern unsigned char temp;

uint8_t KeyValue[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 卡A密钥
uint32_t writeValue = 100;

void IC_test(void)
{
  uint32_t readValue = 0;
  uint8_t send_value[64] = {0};
  uint8_t cStr[30] = {0};
  uint8_t ucArray_ID[4] = {0}; /*先后存放IC卡的类型和UID(IC卡序列号)*/
  uint8_t ucStatusReturn = 0;  /*返回状态*/
  if( temp == 'A')
  {
    /*寻卡*/
    if ((ucStatusReturn = PcdRequest(PICC_REQIDL, ucArray_ID)) != MI_OK)
      /*若失败再次寻卡*/
      ucStatusReturn = PcdRequest(PICC_REQIDL, ucArray_ID);

    if (ucStatusReturn == MI_OK)
    {
      /*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
      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((char *)cStr, "The Card ID is: %02X%02X%02X%02Xn", ucArray_ID[0], ucArray_ID[1], ucArray_ID[2], ucArray_ID[3]);

          HAL_UART_Transmit(&huart1, cStr, sizeof(cStr), 100);
          //printf ( "%srn",cStr );  //打印卡片ID

          //printf ("余额为:%drn",readValue);

          sprintf((char *)send_value, "余额为:%dn", readValue);
          HAL_UART_Transmit(&huart1, send_value, sizeof(send_value), 100);

          PcdHalt();
        }
      }
    }	
  }
	//HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
	//HAL_Delay(200);
}

/**
  * @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); //定义内部定时器的设置

  WriteRawRC(TPrescalerReg, 0x3E); //设置定时器分频系数

  WriteRawRC(TxAutoReg, 0x40); //调制发送信号为100%ASK
}

/**
  * @brief  设置RC522的工作方式
  * @param  ucType,工作方式
  * @retval 无
  */
void M500PcdConfigISOType(uint8_t ucType)
{
  if (ucType == 'A') //ISO14443_A
  {
    ClearBitMask(Status2Reg, 0x08);

    WriteRawRC(ModeReg, 0x3D); //3F

    WriteRawRC(RxSelReg, 0x86); //84

    WriteRawRC(RFCfgReg, 0x7F); //4F

    WriteRawRC(TReloadRegL, 30);

    WriteRawRC(TReloadRegH, 0);

    WriteRawRC(TModeReg, 0x8D);

    WriteRawRC(TPrescalerReg, 0x3E);

    Delay_us(2);

    PcdAntennaOn(); //开天线
  }
}

/**
  * @brief  通过RC522和ISO14443卡通讯
  * @param  ucCommand,RC522命令字
  * @param  pInData,通过RC522发送到卡片的数据
  * @param  ucInLenByte,发送数据的字节长度
  * @param  pOutData,接收到的卡片返回数据
  * @param  pOutLenBit,返回数据的位长度
  * @retval 状态值= MI_OK,成功
  */
char PcdComMF522(uint8_t ucCommand,
                 uint8_t *pInData,
                 uint8_t ucInLenByte,
                 uint8_t *pOutData,
                 uint32_t *pOutLenBit)
{
  char cStatus = MI_ERR;
  uint8_t ucIrqEn = 0x00;
  uint8_t ucWaitFor = 0x00;
  uint8_t ucLastBits;
  uint8_t ucN;
  uint32_t 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;
  }
  //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反
  WriteRawRC(ComIEnReg, ucIrqEn | 0x80);
  //Set1该位清零时,CommIRqReg的屏蔽位清零
  ClearBitMask(ComIrqReg, 0x80);
  //写空闲命令
  WriteRawRC(CommandReg, PCD_IDLE);

  //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
  SetBitMask(FIFOLevelReg, 0x80);

  for (ul = 0; ul < ucInLenByte; ul++)
    WriteRawRC(FIFODataReg, pInData[ul]); //写数据进FIFOdata

  WriteRawRC(CommandReg, ucCommand); //写命令

  if (ucCommand == PCD_TRANSCEIVE)

    //StartSend置位启动数据发送 该位与收发命令使用时才有效
    SetBitMask(BitFramingReg, 0x80);

  ul = 1000; //根据时钟频率调整,操作M1卡最大等待时间25ms

  do //认证 与寻卡等待时间
  {
    ucN = ReadRawRC(ComIrqReg); //查询事件中断
    ul--;
  } while ((ul != 0) && (!(ucN & 0x01)) && (!(ucN & ucWaitFor)));

  ClearBitMask(BitFramingReg, 0x80); //清理允许StartSend位

  if (ul != 0)
  {
    //读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
    if (!(ReadRawRC(ErrorReg) & 0x1B))
    {
      cStatus = MI_OK;

      if (ucN & ucIrqEn & 0x01) //是否发生定时器中断
        cStatus = MI_NOTAGERR;

      if (ucCommand == PCD_TRANSCEIVE)
      {
        //读FIFO中保存的字节数
        ucN = ReadRawRC(FIFOLevelReg);

        //最后接收到得字节的有效位数
        ucLastBits = ReadRawRC(ControlReg) & 0x07;

        if (ucLastBits)

          //N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
          *pOutLenBit = (ucN - 1) * 8 + ucLastBits;
        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;
}

/**
  * @brief 寻卡
  * @param  ucReq_code,寻卡方式 = 0x52,寻感应区内所有符合14443A标准的卡;
            寻卡方式= 0x26,寻未进入休眠状态的卡
  * @param  pTagType,卡片类型代码
             = 0x4400,Mifare_UltraLight
             = 0x0400,Mifare_One(S50)
             = 0x0200,Mifare_One(S70)
             = 0x0800,Mifare_Pro(X))
             = 0x4403,Mifare_DESFire
  * @retval 状态值= MI_OK,成功
  */
char PcdRequest(uint8_t ucReq_code, uint8_t *pTagType)
{
  char cStatus;
  uint8_t ucComMF522Buf[MAXRLEN];
  uint32_t ulLen;

  //清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
  ClearBitMask(Status2Reg, 0x08);
  //发送的最后一个字节的 七位
  WriteRawRC(BitFramingReg, 0x07);
  //TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
  SetBitMask(TxControlReg, 0x03);

  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;
}

/**
  * @brief  防冲撞
  * @param  pSnr,卡片序列号,4字节
  * @retval 状态值= MI_OK,成功
  */
char PcdAnticoll(uint8_t *pSnr)
{
  char cStatus;
  uint8_t uc, ucSnr_check = 0;
  uint8_t ucComMF522Buf[MAXRLEN];
  uint32_t ulLen;

  //清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
  ClearBitMask(Status2Reg, 0x08);
  //清理寄存器 停止收发
  WriteRawRC(BitFramingReg, 0x00);
  //清ValuesAfterColl所有接收的位在冲突后被清除
  ClearBitMask(CollReg, 0x80);

  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;
}

/**
  * @brief  用RC522计算CRC16
  * @param  pIndata,计算CRC16的数组
  * @param  ucLen,计算CRC16的数组字节长度
  * @param  pOutData,存放计算结果存放的首地址
  * @retval 无
  */
void CalulateCRC(uint8_t *pIndata,
                 uint8_t ucLen,
                 uint8_t *pOutData)
{
  uint8_t 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);
}

/**
  * @brief  选定卡片
  * @param  pSnr,卡片序列号,4字节
  * @retval 状态值= MI_OK,成功
  */
char PcdSelect(uint8_t *pSnr)
{
  char ucN;
  uint8_t uc;
  uint8_t ucComMF522Buf[MAXRLEN];
  uint32_t 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;
}

/**
  * @brief  验证卡片密码
  * @param  ucAuth_mode,密码验证模式= 0x60,验证A密钥,
            密码验证模式= 0x61,验证B密钥
  * @param  uint8_t ucAddr,块地址
  * @param  pKey,密码 
  * @param  pSnr,卡片序列号,4字节
  * @retval 状态值= MI_OK,成功
  */
char PcdAuthState(uint8_t ucAuth_mode,
                  uint8_t ucAddr,
                  uint8_t *pKey,
                  uint8_t *pSnr)
{
  char cStatus;
  uint8_t uc, ucComMF522Buf[MAXRLEN];
  uint32_t 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;
}

/**
  * @brief  写数据到M1卡一块
  * @param  uint8_t ucAddr,块地址
  * @param  pData,写入的数据,16字节
  * @retval 状态值= MI_OK,成功
  */
char PcdWrite(uint8_t ucAddr, uint8_t *pData)
{
  char cStatus;
  uint8_t uc, ucComMF522Buf[MAXRLEN];
  uint32_t 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;
}

/**
  * @brief  读取M1卡一块数据
  * @param  ucAddr,块地址
  * @param  pData,读出的数据,16字节
  * @retval 状态值= MI_OK,成功
  */
char PcdRead(uint8_t ucAddr, uint8_t *pData)
{
  char cStatus;
  uint8_t uc, ucComMF522Buf[MAXRLEN];
  uint32_t 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;
}

/**
  * @brief  命令卡片进入休眠状态
  * @param  无
  * @retval 状态值= MI_OK,成功
  */
char PcdHalt(void)
{
  uint8_t ucComMF522Buf[MAXRLEN];
  uint32_t ulLen;

  ucComMF522Buf[0] = PICC_HALT;
  ucComMF522Buf[1] = 0;

  CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
  PcdComMF522(PCD_TRANSCEIVE,
              ucComMF522Buf,
              4,
              ucComMF522Buf,
              &ulLen);

  return MI_OK;
}

/
//功    能:写入钱包金额
//参数说明: ucAddr[IN]:块地址
//          pData:写入的金额
//返    回: 成功返回MI_OK
/
char WriteAmount(uint8_t ucAddr, uint32_t pData)
{
  char status;
  uint8_t ucComMF522Buf[16];
  ucComMF522Buf[0] = (pData & ((uint32_t)0x000000ff));
  ucComMF522Buf[1] = (pData & ((uint32_t)0x0000ff00)) >> 8;
  ucComMF522Buf[2] = (pData & ((uint32_t)0x00ff0000)) >> 16;
  ucComMF522Buf[3] = (pData & ((uint32_t)0xff000000)) >> 24;

  ucComMF522Buf[4] = ~(pData & ((uint32_t)0x000000ff));
  ucComMF522Buf[5] = ~(pData & ((uint32_t)0x0000ff00)) >> 8;
  ucComMF522Buf[6] = ~(pData & ((uint32_t)0x00ff0000)) >> 16;
  ucComMF522Buf[7] = ~(pData & ((uint32_t)0xff000000)) >> 24;

  ucComMF522Buf[8] = (pData & ((uint32_t)0x000000ff));
  ucComMF522Buf[9] = (pData & ((uint32_t)0x0000ff00)) >> 8;
  ucComMF522Buf[10] = (pData & ((uint32_t)0x00ff0000)) >> 16;
  ucComMF522Buf[11] = (pData & ((uint32_t)0xff000000)) >> 24;

  ucComMF522Buf[12] = ucAddr;
  ucComMF522Buf[13] = ~ucAddr;
  ucComMF522Buf[14] = ucAddr;
  ucComMF522Buf[15] = ~ucAddr;
  status = PcdWrite(ucAddr, ucComMF522Buf);
  return status;
}

/
//功    能:读取钱包金额
//参数说明: ucAddr[IN]:块地址
//          *pData:读出的金额
//返    回: 成功返回MI_OK
/
char ReadAmount(uint8_t ucAddr, uint32_t *pData)
{

  char status = MI_ERR;
  uint8_t j;
  uint8_t ucComMF522Buf[16];
  status = PcdRead(ucAddr, ucComMF522Buf);
  if (status != MI_OK)
    return status;
  for (j = 0; j < 4; j++)
  {
    if ((ucComMF522Buf[j] != ucComMF522Buf[j + 8]) && (ucComMF522Buf[j] != ~ucComMF522Buf[j + 4])) //验证一下是不是钱包的数据
      break;
  }
  if (j == 4)
  {
    status = MI_OK;
    *pData = ucComMF522Buf[0] + (ucComMF522Buf[1] << 8) + (ucComMF522Buf[2] << 16) + (ucComMF522Buf[3] << 24);
  }
  else
  {
    status = MI_ERR;
    *pData = 0;
  }
  return status;
}

main.c

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_system.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

uint8_t send_date[64] = "test123n";
extern unsigned char temp;




/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_I2C1_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
	OLED_Init();
  OLED_CLS();
  //OLED_ShowStr(0,0,(unsigned char*)"Hello world",2);
 	OLED_ON(); 
	
	RC522_Init ();  
	//复位RC522
	PcdReset ();
  /*设置工作方式*/
	M500PcdConfigISOType ( 'A' );
	
  while (1)
  {
		//Key_Scan();
		//Display_Change();
		IC_test ();
		
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

bsp_system.h

#ifndef __BSP_SYSTEM_H
#define __BSP_SYSTEM_H


#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_exti.h"
#include "stm32f1xx_hal_gpio.h"
#include "stm32f1xx_hal_i2c.h"
#include "stm32f1xx_hal_tim.h"
#include "stm32f1xx_hal_uart.h"
#include "stm32f1xx_hal_dma.h"


#include "stdio.h"
#include "OLED_I2C.h"
#include "keyboard.h"

#include "rc522_config.h"
#include "rc522_function.h"

#include "delay.h"

#endif /* __BSP_SYSTEM_H */

效果图

7
在这里插入图片描述

这样贴代码确实很蠢
所以后面代码会全部开源在github上
这样做只是为了给大家提供一点思路而已
点个赞吧

最后

以上就是无心丝袜为你收集整理的RFID防伪设计(物联网工程课程设计)DAY2---RFID标签读写的全部内容,希望文章能够帮你解决RFID防伪设计(物联网工程课程设计)DAY2---RFID标签读写所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部