基于STM32F103C8T6的RC522 RFID模块调试(已调)

欢迎大家关注博主的公众号 大海电子,在大海电子公众号里会和大家分享我的一些看法和知识。

不定期的会发布一些有趣的硬件作品及电路分析、软件源码分享。

基于STM32F103C8T6的RC522 RFID模块调试(已调)_第1张图片

需要以下源码工程请扫码关注大海电子,回复“基于STM32F103C8T6的RC522 RFID模块调试”,建议直接复制双引号里面的内容。(免费)

一、所需材料

整个工程文件(淘宝购买):https://item.taobao.com/item.htm?spm=a2126o.11854294.0.0.2aa64831R4YacQ&id=583069400742

 

1、面包板:

https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.942e3961LSzalG&id=566952992749

2、STM32F103C8T6核心板

https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.69693961YaTulR&id=567200541464

3、串口工具

https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.21.7dd33961iRVAkv&id=567201073239

5、STlink 下载程序,或用串口下载亦可

https://item.taobao.com/item.htm?spm=a1z10.3-c.w4002-17409464480.9.fff43961mPmMrt&id=573084876537

 

二、RFID工作原理(待补充)

 

三、MFRC522与STM32接线图

硬件连接
STM32F103C8T6       RC522模块
PA4(SPI1_NSS)          SDA
PA5(SPI1_SCK)                SCK
PA6(SPI1_MISO)            MISO
PA7(SPI1_MOSI)            MOSI
PB0(RST)                        RST
PB1(IRQ)                        IRQ

供电:3.3V

四、MFRC522源码

main文件

#include "usart.h"
#include "stm32f10x_spi.h"
#include "RC522.h"
#include "delay.h"
#include "string.h"
#include "spi_driver.h"
#include "stdio.h"

/******************************************************************************
大海电子专营各种电子模块,欢迎光临

功能:只返回卡号

硬件连接
STM32F103C8T6       RC522模块
PA4(SPI1_NSS)          SDA
PA5(SPI1_SCK)                SCK
PA6(SPI1_MISO)            MISO
PA7(SPI1_MOSI)            MOSI
PB0(RST)                        RST
PB1(IRQ)                        IRQ

备注:以下代码非原创,只是经过修改适配成STM32F103C8T6
若侵权,请告知。
此代码是融合了战舰开发板程序+网上RFID RC522(Author: wdluo)模块进行适配的。
******************************************************************************/

uint8_t Card_Type1[2];  
uint8_t Card_ID[4]; 
uint8_t Card_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};    //{0x11,0x11,0x11,0x11,0x11,0x11};   //密码
uint8_t Card_Data[16];
uint8_t status;

int main(void)
{
    uint8_t i;
    Card_Type1[0]=0x04;
    Card_Type1[1]=0x00;
    delay_init();             //延时函数初始化      
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);     //串口初始化为115200    
     
     printf("\r\n***************************** 大海电子串口测试 *****************************\r\n");
 
    delay_init();
    RC522_IO_Init();
    PcdReset();  //复位RC522
    PcdAntennaOff();  //关闭天线
    delay_ms(100);
    PcdAntennaOn();  //开启天线
    
    printf("\r\n***************************** 大海电子串口测试 *****************************\r\n");
    while(1)
    {
        delay_ms(10);
        if(MI_OK==PcdRequest(0x52, Card_Type1))  //寻卡函数,如果成功返回MI_OK  打印多次卡号
//        if(MI_OK==PcdRequest(0x26, Card_Type1))  //寻卡函数,如果成功返回MI_OK   打印1次卡号
        {
            uint16_t cardType = (Card_Type1[0]<<8)|Card_Type1[1];//读不同卡的类型
            printf("卡类型:(0x%04X)\r\n",cardType);  //"Card Type(0x%04X):"
            switch(cardType){
            case 0x4400:
                    printf("Mifare UltraLight\r\n");
                    break;
            case 0x0400:
                    printf("Mifare One(S50)\r\n");
                    break;
            case 0x0200:
                    printf("Mifare One(S70)\r\n");
                    break;
            case 0x0800:
                    printf("Mifare Pro(X)\r\n");
                    break;
            case 0x4403:
                    printf("Mifare DESFire\r\n");
                    break;
            default:
                    printf("Unknown Card\r\n");
                    break;
            }
            
            status = PcdAnticoll(Card_ID);//防冲撞 如果成功返回MI_OK
            if(status != MI_OK){
                    printf("Anticoll Error\r\n");
            }else{
                    printf("Serial Number:%02X%02X%02X%02X\r\n",Card_ID[0],Card_ID[1],Card_ID[2],Card_ID[3]);
            }
            
            status = PcdSelect(Card_ID);  //选卡 如果成功返回MI_OK
            if(status != MI_OK){
                    printf("Select Card Error\r\n");
            }
            else
                printf("Select Card OK\r\n");
            
//            status = PcdAuthState(PICC_AUTHENT1A,5,Card_KEY,Card_ID);//验证卡密码 如果成功返回MI_OK
//            if(status != MI_OK){
//                    printf("Auth State Error\r\n");
//                    continue;
//            }
//            
//            memset(Card_ID,1,4);  //函数用于为变量开辟空间,或将变量都赋值为一个值
//            memset(Card_Data,1,16);
//            Card_Data[0]=0xaa;
//            status = PcdWrite(5,Card_Data);                   //写入0XAA,0X01,0X01……选择块地址写入数据,成功则返回MI_OK
//            if(status != MI_OK){
//                    printf("Card Write Error\r\n");
//                    continue;
//            }
//            memset(Card_Data,0,16);  //清零
//            delay_us(8);
//            
//            
//            status = PcdRead(5,Card_Data);                    //再一次把它读取出来16字节的卡片数据,选择块地址读出数据,成功则返回MI_OK
//            if(status != MI_OK){
//                    printf("Card Read Error\r\n");
//                    continue;
//            }else{
//                for(i=0;i<16;i++){
//                    printf("%02X ",Card_Data[i]);
//                }
//                printf("\r\n");
//            }
//            
//            memset(Card_Data,2,16);
//            Card_Data[0]=0xbb;
//            delay_us(8);
//            status = PcdWrite(5,Card_Data);                   //写入0Xbb,0X02,0X02……
//            if(status != MI_OK){
//                    printf("Card Write Error\r\n");
//                    continue;
//            }
//            delay_us(8);
//            
//            status = PcdRead(5,Card_Data);                    //再一次把它读取出来16字节的卡片数据
//            if(status != MI_OK){
//                    printf("Card Read Error\r\n");
//                    continue;
//            }else{
//                for(i=0;i<16;i++){
//                    printf("%02X ",Card_Data[i]);
//                }
//                printf("\r\n");
//            }
            
            //memset(Card_Data,0,16);
        //    PcdHalt();  //卡片进入休眠状态
            
            status = PcdHalt();  //卡片进入休眠状态
            if(status != MI_OK){
                    printf("PcdHalt Error\r\n");            
            }
            else
            {
                    printf("PcdHalt OK\r\n");    
            }
        }
    }
}

RC522.c


#include "stm32f10x.h"
#include "rc522.h"
#include "delay.h"
#include "spi_driver.h"
#include "stm32f10x_spi.h"

void RC522_IO_Init(void) 
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);   //开启AFIO时钟
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG因为要使用PB3和4
    
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_4;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);    
    
    SPI_Configuration(SPI1); 
}

/*
/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char i, ucAddr;

    RC522_SCK_RESET();   //MF522_SCK = 0;
    RC522_NSEL_RESET();  //MF522_NSS = 0;
    ucAddr = ((Address<<1)&0x7E);
    RC522_Delay(10);
    for(i=8;i>0;i--)
    {
        //MF522_SI = ((ucAddr&0x80)==0x80);
              if((ucAddr&0x80)==0x80)
                {
                    RC522_MOSI_SET();
                }
                else
                {
                    RC522_MOSI_RESET();
                }
        RC522_SCK_SET();  //MF522_SCK = 1;
        ucAddr <<= 1;
                RC522_Delay(10);
        RC522_SCK_RESET();  //MF522_SCK = 0;
                RC522_Delay(10);
    }

    for(i=8;i>0;i--)
    {
        //MF522_SI = ((value&0x80)==0x80);
              if((value&0x80)==0x80)
                {
                    RC522_MOSI_SET();
                }
                else
                {
                    RC522_MOSI_RESET();
                }
                RC522_SCK_SET();  //MF522_SCK = 1;
        value <<= 1;
                RC522_Delay(10);
        RC522_SCK_RESET();  //MF522_SCK = 0;
                RC522_Delay(10);
//         MF522_SCK = 1;
//         value <<= 1;
//         MF522_SCK = 0;
    }
    RC522_NSEL_SET();  //MF522_NSS = 1;
    RC522_SCK_SET();    //MF522_SCK = 1;
}
/////////////////////////////////////////////////////////////////////
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
     unsigned char i, ucAddr;
     unsigned char ucResult=0;

     RC522_SCK_RESET();   //MF522_SCK = 0;
     RC522_NSEL_RESET();  //MF522_NSS = 0;
     ucAddr = ((Address<<1)&0x7E)|0x80;
     RC522_Delay(10);
     for(i=8;i>0;i--)
     {
//          MF522_SI = ((ucAddr&0x80)==0x80);
//          MF522_SCK = 1;
//          ucAddr <<= 1;
//          MF522_SCK = 0;
             
              if((ucAddr&0x80)==0x80)
                {
                    RC522_MOSI_SET();
                }
                else
                {
                    RC522_MOSI_RESET();
                }
        RC522_SCK_SET();  //MF522_SCK = 1;
        ucAddr <<= 1;
                RC522_Delay(10);
        RC522_SCK_RESET();  //MF522_SCK = 0;
                RC522_Delay(10);
     }
     for(i=8;i>0;i--)
     {
         RC522_SCK_SET();  //MF522_SCK = 1;
         ucResult <<= 1;
               RC522_Delay(10);
         //ucResult|=(bit)MF522_SO;
             
//                   if(RC522_MISO_STATUS==1)
//                  {
//                      ucResult|=0x01;
//                  }
//                  else
//                  {
//                      ucResult&=~0x01;
//                  }
               ucResult |=RC522_MISO_STATUS;
             
         RC522_SCK_RESET();  //MF522_SCK = 0;
               RC522_Delay(10);
     }

    RC522_NSEL_SET();   //MF522_NSS = 1;
    RC522_SCK_SET();    //MF522_SCK = 1;
     return ucResult;
}
*/
//#define MAXRLEN 18
                              
/////////////////////////////////////////////////////////////////////
//功    能:寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]:卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
   char status;  
   unsigned int  unLen;
   unsigned char ucComMF522Buf[MAXRLEN]; 

   ClearBitMask(Status2Reg,0x08); //清RC522寄存位
   WriteRawRC(BitFramingReg,0x07); //写RC623寄存器
   SetBitMask(TxControlReg,0x03); //置RC522寄存位
//   
   ucComMF522Buf[0] = req_code;

   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
//   UART_send_byte(status);
   if ((status == MI_OK) && (unLen == 0x10))
   {    
       *pTagType     = ucComMF522Buf[0];
       *(pTagType+1) = ucComMF522Buf[1];
   }
   else
   {   status = MI_ERR;   }
   
   return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr)
{
    char status;
    unsigned char i,snr_check=0;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    

    ClearBitMask(Status2Reg,0x08);
    WriteRawRC(BitFramingReg,0x00);
    ClearBitMask(CollReg,0x80);
 
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)
    {
         for (i=0; i<4; i++)
         {   
             *(pSnr+i)  = ucComMF522Buf[i];
             snr_check ^= ucComMF522Buf[i];
         }
         if (snr_check != ucComMF522Buf[i])
         {   status = MI_ERR;    }
    }
    
    SetBitMask(CollReg,0x80);
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdSelect(unsigned char *pSnr)
{
    char status;
    unsigned char i;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
        ucComMF522Buf[i+2] = *(pSnr+i);
        ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   status = MI_OK;  }
    else
    {   status = MI_ERR;    }

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥 
//          addr[IN]:块地址
//          pKey[IN]:密码
//          pSnr[IN]:卡片序列号,4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////                   
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
    char status;
    unsigned int  unLen;
    unsigned char i,ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = auth_mode;
    ucComMF522Buf[1] = addr;
    for (i=0; i<6; i++)
    {    ucComMF522Buf[i+2] = *(pKey+i);   }
    for (i=0; i<6; i++)
    {    ucComMF522Buf[i+8] = *(pSnr+i);   }
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    {   status = MI_ERR;   }
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
//          p [OUT]:读出的数据,16字节
//返    回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////// 
char PcdRead(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int  unLen;
    unsigned char i,ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_READ;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
   
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    if ((status == MI_OK) && (unLen == 0x90))
    {
        for (i=0; i<16; i++)
        {    *(pData+i) = ucComMF522Buf[i];   }
    }
    else
    {   status = MI_ERR;   }
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
//          p [IN]:写入的数据,16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////                 
char PcdWrite(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int  unLen;
    unsigned char i,ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_WRITE;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   status = MI_ERR;   }
        
    if (status == MI_OK)
    {
        for (i=0; i<16; i++)
        {    ucComMF522Buf[i] = *(pData+i);   }
        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        {   status = MI_ERR;   }
    }
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:扣款和充值
//参数说明: dd_mode[IN]:命令字
//               0xC0 = 扣款
//               0xC1 = 充值
//          addr[IN]:钱包地址
//          pValue[IN]:4字节增(减)值,低位在前
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////                
char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)
{
    char status;
    unsigned int  unLen;
    unsigned char i,ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = dd_mode;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   status = MI_ERR;   }
        
    if (status == MI_OK)
    {
        for (i=0; i<16; i++)
        {    ucComMF522Buf[i] = *(pValue+i);   }
        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
        unLen = 0;
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
        if (status != MI_ERR)
        {    status = MI_OK;    }
    }
    
    if (status == MI_OK)
    {
        ucComMF522Buf[0] = PICC_TRANSFER;
        ucComMF522Buf[1] = addr;
        CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 
   
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        {   status = MI_ERR;   }
    }
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:备份钱包
//参数说明: sourceaddr[IN]:源地址
//          goaladdr[IN]:目标地址
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
{
    char status;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_RESTORE;
    ucComMF522Buf[1] = sourceaddr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   status = MI_ERR;   }
    
    if (status == MI_OK)
    {
        ucComMF522Buf[0] = 0;
        ucComMF522Buf[1] = 0;
        ucComMF522Buf[2] = 0;
        ucComMF522Buf[3] = 0;
        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
 
        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
        if (status != MI_ERR)
        {    status = MI_OK;    }
    }
    
    if (status != MI_OK)
    {    return MI_ERR;   }
    
    ucComMF522Buf[0] = PICC_TRANSFER;
    ucComMF522Buf[1] = goaladdr;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   status = MI_ERR;   }

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:命令卡片进入休眠状态
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
    //char status;
    unsigned int  unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_HALT;
    ucComMF522Buf[1] = 0;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    //status = 
      PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    return MI_OK;
}

/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
    unsigned char i,n;
    ClearBitMask(DivIrqReg,0x04);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);
    for (i=0; i     {   WriteRawRC(FIFODataReg, *(pIndata+i));   }
    WriteRawRC(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do 
    {
        n = ReadRawRC(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));
    pOutData[0] = ReadRawRC(CRCResultRegL);
    pOutData[1] = ReadRawRC(CRCResultRegM);
}

/////////////////////////////////////////////////////////////////////
//功    能:复位RC522
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdReset(void)
{
    RC522_RESET_SET();     //RST522_1;
    delay_us(10);  //_NOP();
    RC522_RESET_RESET();   //RST522_0;
    delay_ms(60);  //_NOP();_NOP();
    RC522_RESET_SET();     //RST522_1;RST522_1;
    delay_us(500);  //_NOP();_NOP();
    WriteRawRC(CommandReg,PCD_RESETPHASE);
    delay_ms(2);  //_NOP();_NOP();
  
  WriteRawRC(ModeReg,0x3D);            //?Mifare???,CRC???0x6363
  WriteRawRC(TReloadRegL,30);         //?30?????           
  WriteRawRC(TReloadRegH,0);          
  WriteRawRC(TModeReg,0x8D);
  WriteRawRC(TPrescalerReg,0x3E);
  WriteRawRC(TxAutoReg,0x40);
  
  ClearBitMask(TestPinEnReg, 0x80);//off MX and DTRQ out
  WriteRawRC(TxAutoReg,0x40);
   
  return MI_OK;
}

/////////////////////////////////////////////////////////////////////
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
    unsigned char ucAddr;
    unsigned char ucResult=0;
    ucAddr = ((Address<<1)&0x7E)|0x80;
    delay_ms(1);
    RC522_ENABLE;
    SPI_WriteNBytes(SPI1,&ucAddr,1);  //向总线写多个数据
    SPI_ReadNBytes(SPI1,&ucResult,1);  //向总线读多个数据
    RC522_DISABLE;
    return ucResult;
}

/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{  
    unsigned char ucAddr;
    uint8_t write_buffer[2]={0};
    ucAddr = ((Address<<1)&0x7E);
    write_buffer[0] = ucAddr;
    write_buffer[1] = value;
    delay_ms(1);
    RC522_ENABLE;
    SPI_WriteNBytes(SPI1,write_buffer,2);
    RC522_DISABLE;
}

/////////////////////////////////////////////////////////////////////
//功    能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);  //读RC632寄存器
    WriteRawRC(reg,tmp | mask);  // set bit mask
}

/////////////////////////////////////////////////////////////////////
//功    能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
//          mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask

/////////////////////////////////////////////////////////////////////
//功    能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
//          pIn [IN]:通过RC522发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOut [OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command, 
                 unsigned char *pInData, 
                 unsigned char InLenByte,
                 unsigned char *pOutData, 
                 unsigned int  *pOutLenBit)
{
    char status = MI_ERR;
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    switch (Command)
    {
       case PCD_AUTHENT:
          irqEn   = 0x12;
          waitFor = 0x10;
          break;
       case PCD_TRANSCEIVE:
          irqEn   = 0x77;
          waitFor = 0x30;
          break;
       default:
         break;
    }
   
    WriteRawRC(ComIEnReg,irqEn|0x80);
    ClearBitMask(ComIrqReg,0x80);
    WriteRawRC(CommandReg,PCD_IDLE);
    SetBitMask(FIFOLevelReg,0x80);
    
    for (i=0; i     {   WriteRawRC(FIFODataReg, pInData[i]);    }
    WriteRawRC(CommandReg, Command);
   
    
    if (Command == PCD_TRANSCEIVE)
    {    SetBitMask(BitFramingReg,0x80);  }
    
    i = 800 ; //600;//????????,??M1???????25ms
    do 
    {
         n = ReadRawRC(ComIrqReg);
         i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));
    ClearBitMask(BitFramingReg,0x80);
          
    if (i!=0)
    {    
         if(!(ReadRawRC(ErrorReg)&0x1B))
         {
             status = MI_OK;
             if (n & irqEn & 0x01)
             {   status = MI_NOTAGERR;   }
             if (Command == PCD_TRANSCEIVE)
             {
                   n = ReadRawRC(FIFOLevelReg);
                  lastBits = ReadRawRC(ControlReg) & 0x07;
                if (lastBits)
                {   *pOutLenBit = (n-1)*8 + lastBits;   }
                else
                {   *pOutLenBit = n*8;   }
                if (n == 0)
                {   n = 1;    }
                if (n > MAXRLEN)
                {   n = MAXRLEN;   }
                for (i=0; i                 {   pOutData[i] = ReadRawRC(FIFODataReg);    }
            }
         }
         else
         {   status = MI_ERR;   }
        
   }
   

   SetBitMask(ControlReg,0x80);           // stop timer now
   WriteRawRC(CommandReg,PCD_IDLE); 
   return status;
}


/////////////////////////////////////////////////////////////////////
//开启天线  
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void)
{
    unsigned char i;
    i = ReadRawRC(TxControlReg);
    if (!(i & 0x03))
    {
        SetBitMask(TxControlReg, 0x03);
    }
}


/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
    ClearBitMask(TxControlReg, 0x03);
}

void RC522_Config(unsigned char Card_Type)
{
       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);
//       WriteRawRC(TxAutoReg,0x40);//???
       delay_ms(5);//delay_10ms(1);
    
    
     PcdAntennaOn();
}

 

SPI.c

#include "stm32f10x.h"
#include "spi_driver.h"

static void SPI_RCC_Configuration(SPI_TypeDef* SPIx)
{
    if(SPIx==SPI1){
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);
    }else{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
    }
}
/**
  * @brief  配置指定SPI的引脚
  * @param  SPIx 需要使用的SPI
  * @retval None
  */
static void SPI_GPIO_Configuration(SPI_TypeDef* SPIx)  //D哥的板子用PB13,PB14,PB15
{
    GPIO_InitTypeDef GPIO_InitStruct;
       if(SPIx==SPI1){                                          
        GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; 
        GPIO_Init(GPIOA, &GPIO_InitStruct);
        //初始化片选输出引脚
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &GPIO_InitStruct);
        GPIO_SetBits(GPIOA,GPIO_Pin_4);
    }else{
        GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; 
        GPIO_Init(GPIOB, &GPIO_InitStruct);
        //初始化片选输出引脚
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStruct);
        GPIO_SetBits(GPIOB,GPIO_Pin_12);
    } 
}
/**
  * @brief  根据外部SPI设备配置SPI相关参数
  * @param  SPIx 需要使用的SPI
  * @retval None
  */
void SPI_Configuration(SPI_TypeDef* SPIx)
{
    SPI_InitTypeDef SPI_InitStruct;

    SPI_RCC_Configuration(SPIx);

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStruct.SPI_CRCPolynomial = 7;
    SPI_Init(SPIx, &SPI_InitStruct);
    
    SPI_GPIO_Configuration(SPIx);

    SPI_SSOutputCmd(SPIx, ENABLE);
    SPI_Cmd(SPIx, ENABLE);
}
/**
  * @brief  写1字节数据到SPI总线
  * @param  SPIx 需要使用的SPI
  * @param  TxData 写到总线的数据
  * @retval 数据发送状态
  *        @arg 0 数据发送成功
  *     @arg -1 数据发送失败
  */
int32_t SPI_WriteByte(SPI_TypeDef* SPIx, uint16_t TxData)
{
    uint8_t retry=0;                 
    while((SPIx->SR&SPI_I2S_FLAG_TXE)==0);                //等待发送区空    
    {
        retry++;
        if(retry>200)return -1;
    }              
    SPIx->DR=TxData;                           //发送一个byte 
    retry=0;
    while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0);                 //等待接收完一个byte  
    {
        retry++;
        if(retry>200)return -1;
    }  
    SPIx->DR;                            
    return 0;                          //返回收到的数据
}
/**
  * @brief  从SPI总线读取1字节数据
  * @param  SPIx 需要使用的SPI
  * @param  p_RxData 数据储存地址
  * @retval 数据读取状态
  *        @arg 0 数据读取成功
  *     @arg -1 数据读取失败
  */
int32_t SPI_ReadByte(SPI_TypeDef* SPIx, uint16_t *p_RxData)
{
    uint8_t retry=0;                 
    while((SPIx->SR&SPI_I2S_FLAG_TXE)==0);                //等待发送区空    
    {
        retry++;
        if(retry>200)return -1;
    }              
    SPIx->DR=0xFF;                           //发送一个byte 
    retry=0;
    while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0);                 //等待接收完一个byte  
    {
        retry++;
        if(retry>200)return -1;
    }
    *p_RxData = SPIx->DR;                              
    return 0;                          //返回收到的数据
}
/**
  * @brief  向SPI总线写多字节数据
  * @param  SPIx 需要使用的SPI
  * @param  p_TxData 发送数据缓冲区首地址
  * @param    sendDataNum 发送数据字节数
  * @retval 数据发送状态
  *        @arg 0 数据发送成功
  *     @arg -1 数据发送失败
  */
int32_t SPI_WriteNBytes(SPI_TypeDef* SPIx, uint8_t *p_TxData,uint32_t sendDataNum)
{
    uint8_t retry=0;
    while(sendDataNum--){
        while((SPIx->SR&SPI_I2S_FLAG_TXE)==0);                //等待发送区空    
        {
            retry++;
            if(retry>20000)return -1;
        }              
        SPIx->DR=*p_TxData++;                           //发送一个byte 
        retry=0;
        while((SPIx->SR&SPI_I2S_FLAG_RXNE)==0);                 //等待接收完一个byte  
        {
            SPIx->SR = SPIx->SR;
            retry++;
            if(retry>20000)return -1;
        } 
        SPIx->DR;
    }
    return 0;
}
/**
  * @brief  从SPI总线读取多字节数据
  * @param  SPIx 需要使用的SPI
  * @param  p_RxData 数据储存地址
  * @param    readDataNum 读取数据字节数
  * @retval 数据读取状态
  *        @arg 0 数据读取成功
  *     @arg -1 数据读取失败
  */
int32_t SPI_ReadNBytes(SPI_TypeDef* SPIx, uint8_t *p_RxData,uint32_t readDataNum)
{
    uint8_t retry=0;
    while(readDataNum--){
        SPIx->DR = 0xFF;
        while(!(SPIx->SR&SPI_I2S_FLAG_TXE)){
            retry++;
            if(retry>20000)return -1;
        }
        retry = 0;
        while(!(SPIx->SR&SPI_I2S_FLAG_RXNE)){
            retry++;
            if(retry>20000)return -1;
        }
        *p_RxData++ = SPIx->DR;
    }    
    return 0;
}

/*********************************END OF FILE**********************************/

你可能感兴趣的:(嵌入式,硬件)