⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rc522.c

📁 这是一个单片机与MFRC522通信的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
//#include <intrins.h>
#include <intrins.h>
#include "lpcreg.h"
#include "main.h"
#include "mfrc522.h"
#define MAXRLEN 18
#define nop _nop_()
    sbit     SDA=P1^1;
    sbit     SCL=P1^0;
//SDA					BIT     P1.1        ;SERIEL BYTE OF DS1302/IC       I/O
//SCL					BIT		P1.0            ;CLOCK OF DS1302/IC             O

/*----------------------------------------------------------------------------*/
//	内部函数----启动I2C通信
/*----------------------------------------------------------------------------*/
void I2CStart(void)
{
	SDA=1;		/*发送起始条件的数据信号*/
//	nop;nop;nop;nop;nop;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
	SCL=1;		/*发送起始条件的时钟信号*/	
	//Delay(3);
//	nop;nop;nop;nop;nop;   //起始条件建立时间大于4.7us
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
//	nop;nop;nop;nop;nop;   //起始条件建立时间大于4.7us
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();

//	nop;nop;   //起始条件建立时间大于4.7us
    _nop_();
    _nop_();
    
	SDA=0;		/*发送起始信号*/
	//Delay(3);
//	nop;nop;nop;nop;nop; //起始条件锁定时间大于4us
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();

//	nop;nop;nop;nop;nop; //起始条件锁定时间大于4us
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
	//nop;nop;nop;nop;nop; //起始条件锁定时间大于4us
	SCL=0;		/*钳住I2C总线,准备发送或接收*/
//	nop;nop;nop;nop;nop;nop;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();

}

/*----------------------------------------------------------------------------*/
//	内部函数----停止I2C通信
/*----------------------------------------------------------------------------*/
void I2CStop(void) //释放I2C总线*/
{
	SDA=0;		/*发送停止条件的数据信号*/
	nop;nop;nop;nop;nop;
	SCL=1;		//发送停止条件的时钟信号
	//Delay(3);
	nop;nop;nop;nop;nop; //起始条件建立时间大于4us
	nop;nop;nop;nop;nop; //起始条件建立时间大于4us
   	//nop;nop;nop;nop;nop; //起始条件建立时间大于4us
	SDA=1;		/*发送I2C总线停止信号*/
	//Delay(3);
	nop;nop;nop;nop;nop;/*停止条件锁定时间大于4us*/
	nop;nop;nop;nop;nop;/*停止条件锁定时间大于4us*/
}


/*-------------------------------------------------
内部函数--------SendAck(unsigned AckBit) 输出ACK 
 		AckBit=0 为发送应答信号 
		AckBit=1 为发送非应答信号 
---------------------------------------------------*/
void SendAck(bit AckBit)
{
	SDA=AckBit;		/*发送的应答或非应答信号*/
	nop;nop;nop;nop;nop;
//	Delay(1);
	SCL=1;			/*置时钟线为高使应答位有效*/
	//Delay(3);	
	nop;nop;nop;nop;nop;   /*时钟高周期大于4us*/
	nop;nop;nop;nop;nop;   /*时钟高周期大于4us*/
	SCL=0;			/*清时钟线钳住I2C 总线以便继续接收字接数据或发送停止条件*/
	nop;nop;nop;nop;nop;
}

/*------------------------------------------
内部函数---------发送一个字节到I2C总线上
	入口:待写入的数据ucdata ;无返回值 
-------------------------------------------*/
bit I2CSendByte(unsigned char ucdata)
{
	bit bACK;
	unsigned char data i;
	i=8;
	while(i--)			   	/*8 位没发送完继续发送*/
	{
		if((ucdata & 0x80)==0x80)
			SDA=1;		/*发送是1*/
		else 
			SDA=0;		/*发送的是0*/
		nop;nop;nop;nop;nop;	
		SCL=1;			/*置时钟线为高通知被控器开始接收数据位*/
		//Delay(3);	
		nop;nop;nop;nop;nop;  /*保证时钟高周期大于4us*/
		nop;nop;nop;nop;nop;  /*保证时钟高周期大于4us*/
		SCL=0;			/*钳住总线准备接收下一个数据位*/
		ucdata=ucdata<<1;  /*发送下一位数据*/
	}
	nop;nop;nop;nop;nop;
	SDA=1;			/*8位数据发送完,释放I2C总线,准备接收应答位*/
	nop;nop;nop;nop;nop;
	SCL=1;			/*开始接收应答信号*/
//	Delay(1);
	nop;nop;nop;nop;nop;
	if(SDA)		/*等待应答,SDA=0为应答*/
		bACK=0;
	else
		bACK=1;
	SCL=0;		/*发送结束钳住总线准备下一步发送或接收数据或进行其它处理*/
	nop;nop;nop;nop;nop;
	return(bACK);		/*正确应答返回0*/
}
	
/*------------------------------------------
内部函数------从I2C接收一个字节
		无入口参数;返回接收到的字节.
--------------------------------------------*/
unsigned char I2CReadByte(void)
{
	unsigned char data i=0,ByteData=0;
	SDA=1;			/*置数据线为输入方式*/
	i=8;
	while(i--)
	{
	   	nop;nop;nop;nop;nop;
		SCL=0;		//置钟线为零准备接收数据
	//	Delay(3);
		nop;nop;nop;nop;nop; /*时钟低周期大于4.7us*/
		nop;nop;nop;nop;nop; /*时钟低周期大于4.7us*/
		SCL=1;		/*置时钟线为高使数据线上数据有效*/
		nop;nop;nop;nop;nop;
		ByteData=ByteData<<1;
		if(SDA)
			ByteData++;
		nop;nop;nop;nop;nop;
	}
	SCL=0;			/*8 位接收完置时钟线和数据线为低准备发送应答或非应答信号*/
	nop;nop;nop;nop;nop;
	return(ByteData);
}
bit I2CRdStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucBuf,unsigned char ucCount)
{	 //从有子地址的器件读取数据
// PCF8563的地址为0xa2,
	unsigned char idata i=0;
	I2CStart();	
	if(!I2CSendByte(ucSla))
	{
		I2CStop();
		return 0;			/*选从器件的地此*/
	}
	if(!I2CSendByte(ucAddress))
	{
		I2CStop();
		return 0;		/*选第一个寄存器地此*/
	}
	I2CStart();
	if(!I2CSendByte(ucSla+1))
	{
		I2CStop();
		return 0;			/*发送读器件命令*/
	}
	i=ucCount;
	while(i--)
	{
		*ucBuf=I2CReadByte();/*读从器件寄存器*/
		if(i)
			SendAck(0);		/*未接收完所有字节,发送应答信号*/
		ucBuf++;
	}
	SendAck(1);			/*接收完所有字节,发送非应答信号*/
	I2CStop();
	return 1;
}
bit I2CWrStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucData,unsigned char ucNo)
{	//8563的地址为0xa2
	unsigned char data i;
	I2CStart();
	if(!I2CSendByte(ucSla))
	{
		I2CStop();
		return 0;		/*write command*/
	}
	if(!I2CSendByte(ucAddress))
	{
		I2CStop();
		return 0;	/*write register Address*/
	}
	i=ucNo;
	while(i--)
	{
		if(!I2CSendByte(*ucData))
		{
			I2CStop();
			return 0;	/*write Data*/
		}
		ucData++;
	}
	I2CStop();
	return 1;
}
/////////////////////////////////////////////////////////////////////
//功    能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返    回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
	unsigned char data tmp;
//I2CRdStr(unsigned char ucSla,unsigned char ucAddress,unsigned char *ucBuf,unsigned char ucCount)
    I2CRdStr(0x50,Address,&tmp,0x01);
	return tmp;
}
/////////////////////////////////////////////////////////////////////
//功    能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
//          value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
    I2CWrStr(0x50,Address,&value,0x01);
}
                              
/////////////////////////////////////////////////////////////////////
//功    能:寻卡
//参数说明: 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]; 
//  unsigned char xTest ;
   ClearBitMask(Status2Reg,0x08);
   WriteRawRC(BitFramingReg,0x07);

//  xTest = ReadRawRC(BitFramingReg);
//  if(xTest == 0x07 )
 //   { LED_GREEN  =0 ;}
 // else {LED_GREEN =1 ;while(1){}}
   SetBitMask(TxControlReg,0x03);
 
   ucComMF522Buf[0] = req_code;

   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
//     if(status  == MI_OK )
//   { LED_GREEN  =0 ;}
//   else {LED_GREEN =1 ;}
   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);   }
 //   memcpy(&ucComMF522Buf[2], pKey, 6); 
 //   memcpy(&ucComMF522Buf[8], pSnr, 4); 
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    {   status = MI_ERR;   }
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
//          pData[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))
 //   {   memcpy(pData, ucComMF522Buf, 16);   }
    {
        for (i=0; i<16; i++)
        {    *(pData+i) = ucComMF522Buf[i];   }
    }
    else
    {   status = MI_ERR;   }
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
//          pData[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;   }
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -