stm32驱动RFID高频读卡器读取IC卡

简介: stm32驱动RFID高频读卡器读取IC卡

1.介绍RFID

RFID(Radio-Frequency Identification)高频读卡器是一种设备,用于读取和解析高频(13.56 MHz)频段上的RFID标签信息。这种读卡器通过无线射频技术与标签进行通信,并从标签中获取存储的数据。

RFID高频读卡器通常包括以下主要组件:

读卡器天线:用于发射和接收射频信号,与标签进行通信。

处理器:负责解析和处理从标签接收到的数据,以及将数据传输给相应的应用程序。

电源和接口:提供电力和连接读卡器与其他设备/系统的接口。

控制单元:用于控制读卡器的操作和配置。

RFID高频读卡器常用于各种场景,如物流管理、库存跟踪、门禁控制、资产管理等。它们可以与其他设备(如计算机、智能手机、门禁系统)进行通信,以便实现各种应用需求。

需要注意的是,RFID技术还有其他频段,如低频(LF)和超高频(UHF),每个频段的读卡器具有不同的特点和应用领域。

我们这里介绍的是RFID高频读卡器。

2.RFID控制指令

2.1 读IC卡号

发送十六进制命令: 01 08 A1 20 00 01 00 76

成功, 读写器返回十六进制数据: 01 0C A1 20 00 04 00 0A DC EF F9 B7, 其中 04 00 为卡类型, 0A DC

EF F9 为卡号

失败, 读写器返回十六进制数据: 01 08 A1 20 01 00 00 76

2.2 读IC卡数据块

假如块 2 中的数据为: 78 56 34 12 87 A9 CB ED 78 56 34 12 02 FD 02 FD

例 1: 验证卡的 KEYA, 读数据块 2 的数据, LED 和蜂鸣器不提示, 命令与返回包如下:

上位机发送十六进制命令: 01 08 A3 20 02 00 00 77

成功, 读写器返回十六进制数据: 01 16 A3 20 00 78 56 34 12 87 A9 CB ED 78 56 34 12 02 FD 02 FD 63

失败, 读写器返回十六进制数据: 01 08 A3 20 01 00 00 74

例 2: 验证卡的 KEYB, 读数据块 2 的数据, LED 和蜂鸣器不提示, 命令与返回包如下:

上位机发送十六进制命令: 01 08 5C 20 02 00 00 88

成功, 读写器返回十六进制数据: 01 16 5C 20 00 78 56 34 12 87 A9 CB ED 78 56 34 12 02 FD 02 FD 9C

失败, 读写器返回十六进制数据: 01 08 5C 20 01 00 00 8B

2.3 写数据到IC卡数据块

写 16 字节数据 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 到块 2

例 1: 验证卡的 KEYA, 写数据块 2, LED 与蜂鸣器的状态提示开启, 命令与返回包如下:

上位机发送十六进制命令: 01 17 A4 20 02 01 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 6E

成功, 读写器返回十六进制数据: 01 08 A4 20 00 00 00 72

失败, 读写器返回十六进制数据: 01 08 A4 20 01 00 00 73

例 2: 验证卡的 KEYB , 写数据块 2, LED 与蜂鸣器的状态提示开启, 命令与返回包如下:

上位机发送十六进制命令: 01 17 5B 20 02 01 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 91

成功, 读写器返回十六进制数据: 01 08 5B 20 00 00 00 8D

失败, 读写器返回十六进制数据: 01 08 5B 20 01 00 00 8C

2.4 读取RFID读卡器用户数据

例 :用户在从地址 03 开始存储了 6 个字节的数据, 分别是 01 02 03 04 05 06, 查询这个 6 个字节数据, 命令与

返回包如下:

上位机发送十六进制命令: 02 08 B5 20 03 06 00 65

读写器返回十六进制数据: 02 0C B5 20 00 01 02 03 04 05 06 63

每次读用户内存的字节数不超过 16 字节, 地址空间从 0x00-0x1F,总共 32 字节。

2.5 向RFID读卡器写入用户数据

读写器提供 32 字节的内存空间, 地址空间 0-1F, 供用户存储数据, 当内存使用(比如存储用户自己的序列号,

验证码, 用于跟自己的设备或者上位机管理软件验证, 是否为合法读写设备) ; 用户可以简单的通过命令对读写

器提供的存储空间进行存取。 可以将数据存储在指定的地址空间。 每次存储数据字节数不能大于 16 字节。

例 1:如在地址 05 开始处顺序存储 5 个字节:0x12 0x34,0x56,0x78,0x09 , 令与返回包如下:

上位机发送十六进制命令: 03 0B C5 20 05 12 34 56 78 09 16

成功, 读写器返回十六进制数据: 03 08 C5 20 00 00 00 11

失败, 读写器返回十六进制数据: 03 08 C5 20 01 00 00 10

3.代码实例

这里我写了以上操作指令代码,这些代码可移植性强,方便调用。你们可以结合自己的需要去使用。

比如搞一个门禁系统,校园卡等

3.1 rfid.c 源文件

这里就是串口代码没提供,代码太多了,贴不下,你们可以用你们自己的串口代码。

不过我也会提供完成源码。

#include "stm32f10x.h"
#include "usart3.h"
#include "usart.h"
#include "rfid.h"
#include "stdio.h"
unsigned char Uart3RxBuf[UART3_RX_BUF_LEN];
unsigned char Uart3RxDataConut = 0;
unsigned char Rx3Flag = 0;
unsigned char Cmd_Read_Id[8] = {0x01,0x08,0xa1,0x20,0x00,0x00,0x00,0x00};
unsigned char Cmd_Read_Block[8] = {0x01,0x08,0xa3,0x20,0x00,0x00,0x00,0x00};
unsigned char Cmd_Write_Block[23] = {0x01,0x17,0xa4,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char WBlockData[16] = {0x11,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
//CircularBuffer *Uart2_Circular_Buffer;
unsigned char Cmd_Write_RFID[0x0B]={0x03, 0x0B, 0xC5, 0x20, 0x05, 0x12, 0x34, 0x56, 0x78, 0x09, 0x16};
 //                          命令类型  包长度  命令  设备地址  起始地址  数据长度   保留  校验和
unsigned char Cmd_Read_RFID[]={0x02,   0x08,   0xB5,  0x20,    0x03,      0x06,     0x00,  0x65};
//延时,10000000大约为1S
void Delay(__IO unsigned int nCount)
{
  for (; nCount != 0; nCount--);
}
void Uart3_Send_Data(unsigned char *buf,unsigned char num)
{
  unsigned char i;
  for(i=0;i<num;i++)
  { 
    USART_SendData(USART3, buf[i]);
    while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
  } 
}
unsigned char RxCheckSum(unsigned char *ptr,unsigned char len) //计算校验值 
{
  unsigned char i;
  unsigned char checksum;
  checksum = 0;
  for(i=0;i<(len-1);i++)
  {
       checksum ^= ptr[i];
  }
  checksum = ~checksum;
  if(ptr[len-1] == checksum)
    return  STATUS_OK;
  else 
    return  STATUS_ERR;
}
void TxCheckSum(unsigned char *ptr,unsigned char len)
{
  unsigned char i;
  unsigned char checksum;
  checksum = 0;
  for(i=0;i<(len-1);i++)
  {
       checksum ^= ptr[i];
  }
  checksum = ~checksum;
  ptr[len-1] = checksum;
}
//ReadId():读IC卡ID号(卡号)
//参数:*idout,读取的卡号保存到它所指向的存储空间
//返回值:0:成功读取卡号,1:读卡号失败
unsigned char ReadId(void)
{
  unsigned char status;
  unsigned char i;
  unsigned char idout[6];
  Cmd_Read_Id[5] = 0x01;//开启蜂鸣器提示
  //Cmd_Read_Id[5] = 0x00;//关闭蜂鸣器提示
  TxCheckSum(Cmd_Read_Id,Cmd_Read_Id[1]);   //计算校验和
  Uart3_Send_Data(Cmd_Read_Id,Cmd_Read_Id[1]);     //发送读卡号ID命令
  Delay(2000000);//等待模块返回数据,大于150MS
  if(Rx3Flag == 1)
  { 
    Rx3Flag = 0;
    status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
    if(status != STATUS_OK)  //判断校验和是否正确
    {
      return STATUS_ERR;
    }
    status = Uart3RxBuf[4];
    if(status != STATUS_OK) //判断是否正确的读到卡
    {
      return STATUS_ERR;
    }
    if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa1))//判断是否为读卡号返回的数据包
    {
      for(i=0;i<6;i++)//获取卡号ID,6字节     
      {
        idout[i] = Uart3RxBuf[i+5];//从数组的第5个字节开始为卡号,长度为6字节
      }
      for(i=0;i<6;i++)
    {
      while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
      USART_SendData(USART1,idout[i]); 
    }
      return STATUS_OK;    //成功返回0
    }
  } 
  return STATUS_ERR;      //失败返回1
}
//ReadId():读IC卡数据块
//参数:*idout,读取的数据保存到它所指向的存储空间
//参数:block,块号
//返回值:0:成功读取,1:读读取失败
unsigned char ReadDataFromBlock(unsigned char *dataout,unsigned char block)
{
  unsigned char status;
  unsigned char i;
  Cmd_Read_Block[4] = block;
  Cmd_Read_Block[5] = 0x01;//开启蜂鸣器提示
//  Cmd_Read_Block[5] = 0x00;//关闭蜂鸣器提示
  TxCheckSum(Cmd_Read_Block,Cmd_Read_Block[1]); //数据校验
  Uart3_Send_Data(Cmd_Read_Block,Cmd_Read_Block[1]);     //发送读数据块命令
  Delay(2000000);//等待模块返回数据,大于150MS
  if(Rx3Flag == 1)
  { 
    Rx3Flag = 0;
    status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
    if(status != STATUS_OK)    //判断校验和是否正确
    {
      return  STATUS_ERR;
    }
    status = Uart3RxBuf[4];   //获取返回包状态
    if(status != STATUS_OK) //判断是否正确的读到卡
    {
      return STATUS_ERR;
    }
    if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa3))//判断是否为读块数据返回的数据包
    {
      for(i=0;i<16;i++)//获取块数据,16字节 ,一个数据块的大小为16字节   
      {
        dataout[i] = Uart3RxBuf[i+5];//从数组的第5个字节开始为数据,长度为16字节
      }
      return STATUS_OK;    //成功返回0
    }
  }
  return STATUS_ERR;      //失败返回1
}
//ReadId():写数据到指定的数据块
//参数:*idout,指向要写入数据的缓冲区
//参数:block,块号
//返回值:0:写入成功,1:写入失败
unsigned char WriteDataToBlock(unsigned char *datain,unsigned char block)
{
  unsigned char status;
  unsigned char i;
  Cmd_Write_Block[4] = block;
  for(i=0;i<16;i++)
  {
    Cmd_Write_Block[6+i] = datain[i];
  }
  TxCheckSum(Cmd_Write_Block,Cmd_Write_Block[1]); //数据校验
  Uart3_Send_Data(Cmd_Write_Block,Cmd_Write_Block[1]);     //发送写命令
  Delay(2000000);//等待模块返回数据,大于150MS
  if(Rx3Flag == 1)
  { 
    Rx3Flag = 0;
    status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对返回的数据进行校验
    if(status != STATUS_OK) //判断校验是否通过
    {
      return STATUS_ERR;
    }
    status = Uart3RxBuf[4];
    if(status != STATUS_OK) //判断校验是否通过
    {
      return STATUS_ERR;
    }
    if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa4))//判断是否为写块数据返回的数据包
    {
        return STATUS_OK;    //成功返回0
    }
  } 
  return STATUS_ERR;      //失败返回1
}
//读RFID用户空间
unsigned char Read_RFID(unsigned char addr,unsigned char len)
{
  unsigned char status;
  unsigned char i;
    Cmd_Read_RFID[4]=addr;
    Cmd_Read_RFID[5]=len;
  TxCheckSum(Cmd_Read_RFID,Cmd_Read_RFID[1]);   //计算校验和
  Uart3_Send_Data(Cmd_Read_RFID,Cmd_Read_RFID[1]);     //发送读用户数据命令
  Delay(2000000);//等待模块返回数据,大于150MS
  if(Rx3Flag == 1)
  { 
    Rx3Flag = 0;
    status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
    if(status != STATUS_OK)  //判断校验和是否正确
    {
      return STATUS_ERR;
    }
    status = Uart3RxBuf[4];
    if(status != STATUS_OK) //判断是否正确的读到卡
    {
      return STATUS_ERR;
    }
    if((Uart3RxBuf[0] == 0x02)&&(Uart3RxBuf[2] == 0xB5))//判断是否为读RFID用户信息返回的数据包
    {
      for(i=0;i<Cmd_Read_RFID[5];i++)   //将读取的RFID打印到串口
    {
      while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
      USART_SendData(USART1,Uart3RxBuf[i+5]); 
    }
      return STATUS_OK;    //成功返回0
    }
  } 
  return STATUS_ERR;  
}
//写RFID 用户空间
unsigned char Write_RFID(unsigned char addr,unsigned char * data,unsigned char len)
{ 
    unsigned char status;
  unsigned char i;
    unsigned char cmd[22]={0x03, 0x0B, 0xC5, 0x20};
  cmd[4] =addr;//地址
    cmd[1]=6+len;//长度
  for(i=0;i<len;i++)
  {
    cmd[5+i] = data[i];
  }
  TxCheckSum(cmd,cmd[1]); //数据校验
  Uart3_Send_Data(cmd,cmd[1]);   //发送写命令
  Delay(2000000);//等待模块返回数据,大于150MS
  if(Rx3Flag == 1)
  { 
    Rx3Flag = 0;
    status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对返回的数据进行校验
    if(status != STATUS_OK) //判断校验是否通过
    {
      return STATUS_ERR;
    }
    status = Uart3RxBuf[4];
    if(status != STATUS_OK) //判断校验是否通过
    {
      return STATUS_ERR;
    }
    if((Uart3RxBuf[0] == 0x03)&&(Uart3RxBuf[2] == 0xc5))//判断是否为写块数据返回的数据包
    {        
             for(i=0;i<len;i++)   //将写入的数据打印到串口
    {
      while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
      USART_SendData(USART1,cmd[i+5]); 
    }
        return STATUS_OK;    //成功返回0
    }
  } 
  return STATUS_ERR;      //失败返回1
}

3.2 rfid 头文件

#ifndef _RFID_H
#define _RFID_H
#define STATUS_OK     0x00
#define STATUS_ERR    0x01
#define UART3_RX_BUF_LEN 30
extern unsigned char Uart3RxBuf[];
extern unsigned char Uart3RxDataConut ;
extern unsigned char Rx3Flag;
unsigned char ReadId(void);
unsigned char Write_RFID(unsigned char addr,unsigned char * data,unsigned char len);
unsigned char Read_RFID(unsigned char addr,unsigned char len);
#endif

4. 结语

以上就说指令集以及实现代码了。你们可以拿去使用,改造成你项目中所需要的。

最后如果想要串口代码或者完整工程的可以评论区或者私信我哦!


目录
相关文章
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
584 14
STM32Cubemx PWM驱动SG90舵机
STM32Cubemx PWM驱动SG90舵机
1481 13
STM32CubeMX mpu6050驱动
STM32CubeMX mpu6050驱动
563 10
STM32CubeMX EC11旋转编码器驱动
STM32CubeMX EC11旋转编码器驱动
2632 10
STM32CubeMX OLED驱动
STM32CubeMX OLED驱动
519 10
|
芯片
STM32CubeMX TM1637驱动数码管
STM32CubeMX TM1637驱动数码管
1965 6
STM32CubeMX WS2812B灯驱动
STM32CubeMX WS2812B灯驱动
3069 1
STM32CubeMX ULN2003步进电机驱动
STM32CubeMX ULN2003步进电机驱动
685 0
|
传感器
手把手在STM32F103C8T6上构建可扩展可移植的DHT11驱动
【8月更文挑战第29天】本文详细介绍在STM32F103C8T6上构建可扩展且可移植的DHT11温湿度传感器驱动的步骤,包括硬件与软件准备、硬件连接、驱动代码编写及测试。通过这些步骤,可根据实际项目需求优化和扩展代码。
1015 0
STM32Cubemx TB6612直流电机驱动
STM32Cubemx TB6612直流电机驱动
2405 0