STM32F103-RFID RC522射频识别

STM32F1 RFID RC522射频识别    ,正点原子的精英板实现。

只有读卡的功能  ,直接建立对应文件即可直接使用。

main.c


#include "stm32f10x.h"
#include "oled.h"
#include "rc522.h"
#include "delay.h"//主函数
int main()
{u8 RC522_ID[4];   //存放IC卡的类型u8 RC522_NUM[4];  //存放IC卡的卡号u8 RC522_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};  //存放密码u8 RC522_return;  //返回的状态delay_init();LED_init();OLED_init();RC522_Init();  //  **RC522初始化**OLED_ShowCharString(0,0,"RC522 TEST:",16);OLED_RESET_Gram();LED1 = 0;Pcd_Reset();   //  **复位RC522 ,此处容易卡死 ,LED1指示**LED1 = 1;M500PcdConfigISOType('A');  //设置工作方式while(1){//  **首先寻卡**RC522_return = PcdRequest(PICC_REQALL,RC522_ID);if( RC522_return != MI_OK){OLED_ShowNum(90,20,999,3,16);OLED_RESET_Gram();//  **失败再次寻卡 ,次数不可过多 , 时间太长**//RC522_return = PcdRequest(PICC_REQALL,RC522_ID);}//  **成功寻到卡**if(RC522_return == MI_OK){OLED_ShowNum(0,20,100,3,16);OLED_RESET_Gram();//  **防冲撞,防止多卡同时检测**if( (PcdAnticoll(RC522_NUM) == MI_OK) )  //确认选择刚才检测到的IC卡{OLED_ShowNum(30,20,200,3,16);OLED_RESET_Gram();//  **选卡成功**if( PcdSelect(RC522_NUM)== MI_OK){OLED_ShowNum(60,20,300,3,16);OLED_RESET_Gram();//if(PcdAuthState(0x61,0x06,RC522_KEY,RC522_NUM)==MI_OK){OLED_ShowNum(25,40,RC522_ID[0],3,16);OLED_ShowNum(50,40,RC522_ID[1],3,16);OLED_ShowNum(75,40,RC522_ID[2],3,16);OLED_ShowNum(100,40,RC522_ID[3],3,16);OLED_RESET_Gram();}}}}LED0=!LED0;}
}
//

rc522.h


#ifndef     __RC522_H__
#define     __RC522_H__
#include "stm32f10x.h"
#include "sys.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                 0x07   //  **可以自行设置**
#define 	MI_ERR                0x08
#define 	MI_NOTAGERR           0x09
// ************************************************************************************************************** //// ************************************************************************************************************** //
//GPIO_ResetBits(GPIOB,GPIO_Pin_x);  //设置为0
//GPIO_SetBits(GPIOB,GPIO_Pin_x);    //设置为1
#define RC522_RST  PBout(10)   //RST  0为使能 ,1为失能
#define RC522_CS   PBout(11)   //SDA  0为使能 ,1为失能
#define RC522_SCK  PBout(13)   //SCK
#define RC522_MOSI PBout(15)   //MOSI
#define RC522_MISO PBin (14)   //MISO// ************************************************************************************************************** //
void Delay_ns(u32 ns);
void RC522_SPI_SendData(u8 data);u8 RC522_SPI_ReadData(void);u8 RC522_Read_Reg(u8 regaddr);
void RC522_Write_Reg(u8 regaddr,u8 regvalue);
void RC522_SetBit(u8 reg_add, u8 reg_val);
void RC522_ClearBit(u8 reg_add,u8 reg_val);
void PcdAntenna_On(void);
void PcdAntenna_Off(void);
void Pcd_Reset(void);
void M500PcdConfigISOType(u8 Type);
char PcdComMF522(u8 ucCommand,u8 *pInData,u8 ucInLenByte,u8 *pOutData,u32 *pOutLenBit);
char PcdRequest(u8 ucReq_code,u8 *pTagType);
char PcdAnticoll(u8 *pSnr);
void CalulateCRC(u8 *pIndata,u8 ucLen,u8 *pOutData);
char PcdSelect(u8 *pSnr);
char PcdAuthState(u8 ucAuth_mode,u8 ucAddr,u8 *pKey,u8 *pSnr);
char PcdWrite(u8 ucAddr,u8 *pData);
char PcdRead(u8 ucAddr,u8 *pData);
char PcdHalt(void);
void RC522_Init(void);
void SPI_init(void);#endif

rc522.c


#include "rc522.h"
#include "delay.h"//  **使用正点原子的延时 ,大概率程序卡死在 222行do-while循环 寻卡与认证等待时间**
#define   RC522_DELAY()  Delay_ns(200)
// ************************************************************************************************************** //
void Delay_ns(u32 ns)  //可以自行Debug调试时间
{while(ns--){__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();}
}
// ************************************************************************************************************** //
//向RC522发送一字节数据
void RC522_SPI_SendData(u8 data)
{u8 i;for(i=0;i<8;i++){if (data & 0x80)RC522_MOSI = 1;else RC522_MOSI = 0;RC522_DELAY();RC522_SCK = 0;RC522_DELAY();RC522_SCK = 1;RC522_DELAY();data <<= 1; }
}
// ************************************************************************************************************** //
//读取RC522的值
u8 RC522_SPI_ReadData()
{u8 t;u8 Data;for(t=0;t<8;t++){Data <<= 1;RC522_SCK = 0;RC522_DELAY();if(RC522_MISO ==1) // // //Data |= 0x01;RC522_DELAY();RC522_SCK = 1;RC522_DELAY();}return Data;
}
// ************************************************************************************************************** //
//读RC522寄存器的值
//addr 寄存器地址
u8 RC522_Read_Reg(u8 regaddr)
{u8 ucaddr;  //寄存器有效地址u8 return_value; //寄存器返回值ucaddr = ((regaddr<<1) & 0x7E) | 0x80;	 //  **变成有效地址形式,最低位为0,最高位为1 从RC522中读出数据RC522_CS = 0;  //0为使能RC522_SPI_SendData(ucaddr);  //发送有效地址return_value = RC522_SPI_ReadData();  //收到寄存去返回值RC522_CS = 1;  //1为失能return return_value;
}
// ************************************************************************************************************** //
//写RC522寄存器的值
//regaddr  寄存器地址
//regvalue  寄存器中的值
void RC522_Write_Reg(u8 regaddr,u8 regvalue)
{u8 ucaddr;  //寄存器有效地址ucaddr = (regaddr<<1) & 0x7E;	   //  **变成有效地址形式,最低位为0,最高位为0 从EC522中写入数据RC522_CS = 0;RC522_SPI_SendData(ucaddr);   //发送地址RC522_SPI_SendData(regvalue);  //发送数据RC522_CS = 1;	
}
// ************************************************************************************************************** //
//对RC522寄存器置位,相当于对MF522中的地址写数据,控制不同的操作
//reg_add 寄存器地址
//w_val  置位值
void RC522_SetBit(u8 reg_add, u8 reg_val)  
{u8 ucTemp;ucTemp=RC522_Read_Reg(reg_add);  //读取当前地址寄存器的值RC522_Write_Reg(reg_add,ucTemp | reg_val);         // set bit mask
}
// ************************************************************************************************************** //
//对RC522寄存器清位,清除MF522寄存器中的值  还原之前数据,或者换为无用值
//reg_add 寄存器地址
//w_val  清位值
void RC522_ClearBit(u8 reg_add,u8 reg_val)
{u8 ucTemp;ucTemp=RC522_Read_Reg(reg_add);   //读取当前地址寄存器的值RC522_Write_Reg(reg_add,ucTemp & (~reg_val));  // clear bit mask
}
// ************************************************************************************************************** //
//开启天线 
void PcdAntenna_On()
{u8 uc;uc=RC522_Read_Reg(TxControlReg);  //读取 TxControlReg 的值if (!(uc & 0x03))                 //盘丢按是否为正确值RC522_SetBit(TxControlReg,0x03); //否则写入正确值
}
// ************************************************************************************************************** //
//关闭天线
void PcdAntenna_Off()
{RC522_ClearBit(TxControlReg,0x03);	 //清除写入值
}
// ************************************************************************************************************** //
//复位RC522 
void Pcd_Reset()
{RC522_RST = 1;//delay_us(1);Delay_ns(10);RC522_RST = 0;//delay_us(1);Delay_ns(10);RC522_RST = 1;//delay_us(1);Delay_ns(10);RC522_Write_Reg(CommandReg,0x0f);RC522_Write_Reg(CommandReg,0x0f);   //  **写入两遍 ,防止出错**//while(RC522_Read_Reg(CommandReg) & 0x10); //  **使用等待 ,可能出错 ,初始化不通过**//delay_us(1);Delay_ns(10);RC522_Write_Reg(ModeReg,0x3D);           //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363RC522_Write_Reg(TReloadRegL,30);         //16位定时器低位RC522_Write_Reg(TReloadRegH,0);			     //16位定时器高位RC522_Write_Reg(TModeReg,0x8D);				   //定义内部定时器的设置RC522_Write_Reg(TPrescalerReg,0x3E);		 //设置定时器分频系数RC522_Write_Reg(TxAutoReg,0x40);				 //调制发送信号为100%ASK
}
// ************************************************************************************************************** //
//设置RC522的工作方式
//Type 工作方式选择
void M500PcdConfigISOType(u8 Type)
{if (Type=='A')                     //ISO14443_A{RC522_ClearBit(Status2Reg,0x08);  //状态2寄存器RC522_Write_Reg(ModeReg,0x3D);    //3F  和Mifare卡通讯,CRC初始值0x6363RC522_Write_Reg(RxSelReg,0x86);   //84  选择内部接收器设置,内部模拟部分调制信号,发送数据后延迟6个位时钟接收RC522_Write_Reg(RFCfgReg,0x7F);   //4F  配置接收器 48dB最大增益RC522_Write_Reg(TReloadRegL,30);  //tmoLength);// TReloadVal = 'h6a =tmoLength(dec) RC522_Write_Reg(TReloadRegH,0);RC522_Write_Reg(TModeReg,0x8D);RC522_Write_Reg(TPrescalerReg,0x3E);//delay_us(2);Delay_ns(1000);PcdAntenna_On();//开天线}	 
}
// ************************************************************************************************************** //
//通过RC522和ISO14443卡通讯
//ucCommand  RC522命令字
//pInData  通过RC522发送到卡片的数据
//ucInLenByte  发送数据的字节长度
//pOutData  接收到的卡片返回数据
//pOutLenBit  返回数据的位长度
//状态值= MI_OK  成功
char PcdComMF522(u8 ucCommand,u8 *pInData,u8 ucInLenByte,u8 *pOutData,u32 *pOutLenBit)
{char cStatus = MI_ERR;u8 ucIrqEn   = 0x00;u8 ucWaitFor = 0x00;u8 ucLastBits;u8 ucN;u32 ul;switch(ucCommand){case PCD_AUTHENT:		  //Mifare认证ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEnucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位break;case PCD_TRANSCEIVE:		//接收发送 发送接收ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEnucWaitFor = 0x30;		//寻卡等待时候 查询接收中断标志位与 空闲中断标志位break;default:break;     }RC522_Write_Reg(ComIEnReg,ucIrqEn | 0x80);		//IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 RC522_ClearBit(ComIrqReg,0x80);			//Set1该位清零时,CommIRqReg的屏蔽位清零RC522_Write_Reg(CommandReg,PCD_IDLE);		//写空闲命令RC522_SetBit(FIFOLevelReg,0x80);			//置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除for(ul=0;ul MAXRLEN)ucN = MAXRLEN;   for(ul=0;ul

个人见解,感谢阅读。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部