打印
[STM32F0]

基于STM32F030实现RFID射频识别

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
41
个百zz分点个|  楼主 | 2022-9-29 15:43 | 只看该作者 回帖奖励 |倒序浏览
int8_t Card_Find(uint8_t Findway, uint8_t *Cardtype)
{
RC522_ClearReg(Status2Reg, 0x08); // 该位表示MIFARE®Crypto1单元已打开,因此与该卡的所有数据通信都已加密
          RC522_WriteData(BitFramingReg, 0x07); // 不启动数据发送
          RC522_SetReg(TxControlReg, 0x03);// TX1、TX2输出信号将传递经发送数据调制的13.56MHz的能量载波信号。

          uint32_t OutLen;
          uint8_t RC522_DataBuffer[MAXRLEN] = {Findway}; // 将寻卡命令填入到数组
       
          int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 1, RC522_DataBuffer, &OutLen); // 发送命令并获取返回数据
       
          if((status == MI_OK) && (OutLen == 0x10)) // 状态正确,并且返回16位数据
          {   
         Cardtype[0] = RC522_DataBuffer[0]; // 获取卡类型
         Cardtype[1] = RC522_DataBuffer[1];
          }
        else
          {  
         status = MI_ERR;  
          }
          return status;
}

使用特权

评论回复
42
个百zz分点个|  楼主 | 2022-9-29 15:43 | 只看该作者
在sensor_rfid.c文件中添加Card_Anticoll()函数,这个函数用于防冲突操作。防冲突操作就是将防冲突命令通过PcdComMF522()函数与PICC卡进行交互。防冲突命令是两个字节,其中第一字节为Mifare_One卡的防冲突命令字PICC_ANTICOLL1 (0x93),第二个字节为0x20。对于多个卡片同时进入有效区域的防冲突操作:由于是非接触式的,同一时间天线作用范围内可能不只一张卡时,即有多于一张的IC卡发回了卡序列号应答,则发生了冲突。函数如下

使用特权

评论回复
43
个百zz分点个|  楼主 | 2022-9-29 15:44 | 只看该作者
// 防冲撞        
int8_t Card_Anticoll(uint8_t *card_sn)
{
// 该位表示MIFARE®Crypto1单元已打开,因此与该卡的所有数据通信都已加密
    RC522_ClearReg(Status2Reg, 0x08);
// 不启动数据发送,接收的LSB位存放在位0,接收到的第二位放在位1,定义发送的最后一个字节的位数为8
    RC522_WriteData(BitFramingReg, 0x00);
// 所有接收的位在冲突后将被清除。106kbit/s 有效。其他速率应该置1
    RC522_ClearReg(CollReg, 0x80);
    uint32_t OutLen;
    uint8_t RC522_DataBuffer[MAXRLEN] = {0};

    RC522_DataBuffer[0] = PICC_ANTICOLL1;        // 0x93表明串联级别1
    RC522_DataBuffer[1] = 0x20; // 表明PCD发送字节数为整两个字节

    int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 2, RC522_DataBuffer, &OutLen);

    if(status == MI_OK)
    {
uint8_t sn_check = 0;
       for(uint8_t i=0; i<4; i++)
       {  
          card_sn[i]  = RC522_DataBuffer[i];
          sn_check ^= RC522_DataBuffer[i];
       }
       if(sn_check != RC522_DataBuffer[4]) // 返回四个字节,最后一个字节为校验位
       {  
          status = MI_ERR;
       }
    }
    RC522_SetReg(CollReg, 0x80); // 关闭冲撞检测
    return status;
}

使用特权

评论回复
44
个百zz分点个|  楼主 | 2022-9-29 15:45 | 只看该作者
在sensor_rfid.c文件中添加CalulateCRC()函数,实现用MF522计算CRC16

使用特权

评论回复
45
个百zz分点个|  楼主 | 2022-9-29 15:45 | 只看该作者
// 用MF522计算CRC16函数
void CalulateCRC(uint8_t *Indata, uint8_t len, uint8_t *OutData)
{
    RC522_ClearReg(DivIrqReg, 0x04); // 清除CRC中断
    RC522_WriteData(CommandReg, PCD_IDLE); // 进入IDLE模式
RC522_SetReg(FIFOLevelReg, 0x80); // 清楚缓冲区
                               
    for (uint8_t i=0; i<len; i++)
    {
            RC522_WriteData(FIFODataReg, Indata[i]); // 写入FIFO
        }
        RC522_WriteData(CommandReg, PCD_CALCCRC); // 计算CRC模式
       
        for(uint8_t i = 0xFF; i>0; i--)
        {
            if(RC522_ReadData(DivIrqReg) & 0x04) // 等待CRC计算完成中断
            {
                break;
            }
        }
    OutData[0] = RC522_ReadData(CRCResultRegL); // 读CRC计算结果
    OutData[1] = RC522_ReadData(CRCResultRegM);
}

使用特权

评论回复
46
个百zz分点个|  楼主 | 2022-9-29 15:46 | 只看该作者
在sensor_rfid.c文件中添加Card_Select()函数,实现选定卡片功能,函数实现方法与寻卡、防冲撞类似,向RF522寄存器发送数据并等待应答
int8_t Card_Select(uint8_t *card_sn)
{
    uint8_t RC522_DataBuffer[MAXRLEN] = {0};
   
    RC522_DataBuffer[0] = PICC_ANTICOLL1; // 选卡命令
    RC522_DataBuffer[1] = 0x70; // 表明PCD发送字节数为整7个字节
               
    for(uint8_t i=0; i<4; i++) // 卡ID(4字节)及校验位(1字节)
    {
                RC522_DataBuffer[i+2] = card_sn[i];
            RC522_DataBuffer[6] ^= card_sn[i];
    }
               
    CalulateCRC(RC522_DataBuffer, 7, &RC522_DataBuffer[7]); // 计算CRC16
  
    RC522_ClearReg(Status2Reg, 0x08); // 该位表示MIFARE®Crypto1单元已打开,因此与该卡的所有数据通信都已加密
               
    uint32_t OutLen;
    int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 9, RC522_DataBuffer, &OutLen); // 返回值共24位, 0x08 0xB6 0xDD
   
    if((status == MI_OK)&&(OutLen == 0x18))
        {
            status = MI_OK;
        }
    else
        {
            status = MI_ERR;
        }               
    return status;
}

使用特权

评论回复
47
个百zz分点个|  楼主 | 2022-9-29 15:47 | 只看该作者
在sensor_rfid.c文件中添加Card_Validation()函数,实现验证卡的密钥

使用特权

评论回复
48
个百zz分点个|  楼主 | 2022-9-29 15:48 | 只看该作者
int8_t Card_Validation(const uint8_t verifymode, const uint8_t address, const uint8_t *key, const uint8_t *cardseries)
{
    uint8_t RC522_DataBuffer[MAXRLEN] = {0};

    RC522_DataBuffer[0] = verifymode; // 密码验证模式
    RC522_DataBuffer[1] = address; //
               
    for (uint8_t i=0; i<6; i++)
    {
            RC522_DataBuffer[i+2] = key[i]; // 填入密码
        }
    for (uint8_t i=0; i<4; i++)
    {
            RC522_DataBuffer[i+8] = cardseries[i]; // 填入卡片序列号
        }
        uint32_t  OutLen;
    int8_t status = RC522_CardCom(PCD_AUTHENT, RC522_DataBuffer, 12, RC522_DataBuffer, &OutLen);
    if((status != MI_OK) || (!(RC522_ReadData(Status2Reg) & 0x08))) // 该位表示MIFARE®Crypto1单元已打开,因此与该卡的所有数据通信都已加密
    {
            status = MI_ERR;
        }
    return status;
}

使用特权

评论回复
49
个百zz分点个|  楼主 | 2022-9-29 15:48 | 只看该作者
在sensor_rfid.c文件中添加Card_Read()函数,实现读取卡中的数据

使用特权

评论回复
50
个百zz分点个|  楼主 | 2022-9-29 15:49 | 只看该作者
int8_t Card_Read(uint8_t address, uint8_t *Data)
{
    uint8_t RC522_DataBuffer[MAXRLEN] = {0};

    RC522_DataBuffer[0] = PICC_READ;
    RC522_DataBuffer[1] = address;
    CalulateCRC(RC522_DataBuffer, 2, &RC522_DataBuffer[2]);
   
        uint32_t OutLen;
    int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 4, RC522_DataBuffer, &OutLen);
    if((status == MI_OK) && (OutLen == 0x90))
    {
        for (uint8_t i=0; i<16; i++)
        {
                Data[i] = RC522_DataBuffer[i];
            }
    }
    else
    {
            status = MI_ERR;
        }   
    return status;
}

使用特权

评论回复
51
个百zz分点个|  楼主 | 2022-9-29 15:50 | 只看该作者
在sensor_rfid.c文件中添加Card_Write()函数,实现写数据到IC卡

使用特权

评论回复
52
个百zz分点个|  楼主 | 2022-9-29 15:51 | 只看该作者
int8_t Card_Write(uint8_t address, const uint8_t *Data)
{
        uint32_t OutLen;
        uint8_t RC522_DataBuffer[MAXRLEN] = {0};
       
        RC522_DataBuffer[0] = PICC_WRITE;
        RC522_DataBuffer[1] = address;
       
        CalulateCRC(RC522_DataBuffer, 2, &RC522_DataBuffer[2]);

        int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 4, RC522_DataBuffer, &OutLen);

        if((status != MI_OK) || (OutLen != 4) || ((RC522_DataBuffer[0] & 0x0F) != 0x0A))
        {   
            status = MI_ERR;
        }
                       
        if(status == MI_OK)
        {
            for(uint8_t i=0; i<16; i++)
            {
                RC522_DataBuffer[i] = Data[i];
            }
               
            CalulateCRC(RC522_DataBuffer, 16, &RC522_DataBuffer[16]);

            status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 18, RC522_DataBuffer, &OutLen);
            if((status != MI_OK) || (OutLen != 4) || ((RC522_DataBuffer[0] & 0x0F) != 0x0A))
            {   
                status = MI_ERR;
            }
        }
        return status;
}

使用特权

评论回复
53
个百zz分点个|  楼主 | 2022-9-29 15:52 | 只看该作者
在sensor_rfid.c文件中添加RC522_Read_ID()函数,这个函数用于识别IC卡的ID。函数中首先调用PcdRequest()实现寻卡操作,然后调用PcdAnticoll()函数进行防冲撞并将卡ID存储到Card_ID,最后返回状态

使用特权

评论回复
54
个百zz分点个|  楼主 | 2022-9-29 15:53 | 只看该作者
// 读ID函数
int8_t RC522_Read_ID(uint8_t *Card_ID)
{
        int8_t status = 0;
        uint8_t count = CARD_INIT_RETRY_COUNT;
        while(Card_Find(PICC_REQALL, Card_ID) != MI_OK && --count);
        if(count==0) status = MI_FIND_ERR;
        count = CARD_INIT_RETRY_COUNT;
        while(Card_Anticoll(Card_ID) != MI_OK && --count);
        if(count==0) status = MI_ANTICOLL_ERR;
        return status;
}

使用特权

评论回复
55
个百zz分点个|  楼主 | 2022-9-29 15:53 | 只看该作者
在sensor_rfid.c文件中添加Card_Adjust()函数,实现数据块的自增自减功能

使用特权

评论回复
56
个百zz分点个|  楼主 | 2022-9-29 15:54 | 只看该作者
int8_t Card_Adjust(uint8_t Command, uint8_t block_num, uint32_t value)
{
uint32_t OutLen;
          uint8_t RC522_DataBuffer[MAXRLEN] = {0};
  
          RC522_DataBuffer[0] = Command;
          RC522_DataBuffer[1] = block_num;
          CalulateCRC(RC522_DataBuffer, 2, &RC522_DataBuffer[2]);

        // 写入命令和地址
          int8_t status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 4, RC522_DataBuffer, &OutLen);

          if((status != MI_OK) || (OutLen != 4) || ((RC522_DataBuffer[0] & 0x0F) != 0x0A))
          {
            status = MI_ERR;
          }
      
          if(status == MI_OK)
          {
            RC522_DataBuffer[0] = ((uint8_t*)&value)[0];
            RC522_DataBuffer[1] = ((uint8_t*)&value)[1];
            RC522_DataBuffer[2] = ((uint8_t*)&value)[2];
            RC522_DataBuffer[3] = ((uint8_t*)&value)[3];
            CalulateCRC(RC522_DataBuffer, 4, &RC522_DataBuffer[4]);
            OutLen = 0;
            status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 6, RC522_DataBuffer, &OutLen);
            if(status != MI_ERR)
            {
                status = MI_OK;   
            }
                       
            if(status == MI_OK)
            {
                RC522_DataBuffer[0] = PICC_TRANSFER; // 保存缓冲区数据
                RC522_DataBuffer[1] = block_num;
                CalulateCRC(RC522_DataBuffer, 2, &RC522_DataBuffer[2]);
               
                status = RC522_CardCom(PCD_TRANSCEIVE, RC522_DataBuffer, 4, RC522_DataBuffer, &OutLen);
       
                if ((status != MI_OK) || (OutLen != 4) ||((RC522_DataBuffer[0] & 0x0F) != 0x0A))
                {  
                    status = MI_ERR;
                }
            }
  }
     return status;
}

使用特权

评论回复
57
个百zz分点个|  楼主 | 2022-9-29 15:55 | 只看该作者
在sensor_rfid.c文件中添加Card_Init()函数,实现寻卡、防冲撞、选卡以及验证密钥

使用特权

评论回复
58
个百zz分点个|  楼主 | 2022-9-29 15:57 | 只看该作者
// 寻卡 防冲撞  选卡 验证密钥
static int8_t Card_Init(const uint8_t block_num, const uint8_t* passwd)
{       
        uint8_t Data_Buffer[4] = {0};
        uint8_t count = CARD_INIT_RETRY_COUNT;
        while(Card_Find(PICC_REQALL, Data_Buffer) != MI_OK && --count);
        if(count==0) return MI_FIND_ERR;
        count = CARD_INIT_RETRY_COUNT;
        while(Card_Anticoll(Data_Buffer) != MI_OK && --count);
        if(count==0) return MI_ANTICOLL_ERR;
        count = CARD_INIT_RETRY_COUNT;
        while(Card_Select(Data_Buffer) != MI_OK && --count);
        if(count==0) return MI_SELECT_ERR;
        count = CARD_INIT_RETRY_COUNT;
        while(Card_Validation(PICC_AUTHENT1A, block_num / 4 * 4 + 3, passwd, Data_Buffer) != MI_OK && --count);
        if(count==0) return MI_VALIDATION_ERR;
        return MI_OK;
}

使用特权

评论回复
59
个百zz分点个|  楼主 | 2022-9-29 15:59 | 只看该作者
在sensor_rfid.c文件中添加RFID_Write()函数,实现向卡中写入数据。函数首先调用Card_Init()实现寻卡、防冲撞、选卡以及验证密钥,然后调用RFID_Write()函数实现写数据功能

使用特权

评论回复
60
个百zz分点个|  楼主 | 2022-9-29 16:02 | 只看该作者
int8_t RFID_Write(const uint8_t block_num, const uint8_t* passwd, const uint8_t* buffer)
{       
        if(block_num < 1 || block_num > 63 || block_num % 4 == 3)
        {
            return MI_PARAM_ERR;
        }
        int8_t state = Card_Init(block_num, passwd);
        if(state != MI_OK)
        {
            return state;
        }
        return Card_Write(block_num, buffer);
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则