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

📄 rc500.c

📁 RFID RC531 driver source code for PIC microcontroller
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
* 名    称:ClearBitMask()
* 功    能:清一个bit
* 入口参数:reg		内存
			mask俺码
* 出口参数:无
****************************************************************************/
char ClearBitMask(unsigned char reg,unsigned char mask)  
{
    char tmp = 0x00;

    tmp = ReadIO(reg);
    WriteIO(reg,tmp & ~mask);  // clear bit mask
    return 0x00;
}




/****************************************************************************
* 名    称:FlushFIFO()
* 功    能:清除内部FIFO
* 入口参数:无
* 出口参数:无
****************************************************************************/
void FlushFIFO(void)
{  
    SetBitMask(RegControl,0x01);
}





/****************************************************************************
* 名    称:M500PcdCmd()
* 功    能:清一个bit
* 入口参数:unsigned char cmd,
            unsigned char *rcv,
            MfCmdInfo idata *info
* 出口参数:0正常,其它错误码
****************************************************************************/
char  M500PcdCmd(unsigned char cmd,
                 unsigned char *rcv,
                 MfCmdInfo  *info)
{
	char status    = MI_OK;
	unsigned char irqEn = 0x00;
	unsigned char waitFor = 0x00;
	unsigned int timecnt = 0;
	char tmpStatus ;
	unsigned char lastBits;
	WriteIO(RegInterruptEn,0x7F);				//开中断
    WriteIO(RegInterruptRq,0x7F);				//清中断
    WriteIO(RegCommand,PCD_IDLE); 				//清除指令
	
	FlushFIFO();     
    MpIsrInfo = info;  
    MpIsrOut = rcv;
	
	info->irqSource = 0x00;						
	
	switch(cmd)
    {
        case PCD_IDLE:    						//0x00 		无指令,清指令         
            irqEn = 0x00;
            waitFor = 0x00;
            break;
        case PCD_WRITEE2:            			//0x01    	写FIFO,并定入EEPROM 
            irqEn = 0x11;
            waitFor = 0x10;
            break;
        case PCD_READE2:						//0x03		从EEPROM取数据并写入FIFO     
            irqEn = 0x07;
            waitFor = 0x04;
            break;
        case PCD_LOADCONFIG:					//0x07		从EEPROM读数据并用于初始化  
        case PCD_LOADKEYE2:   					//0x0b		将密钥从EEPROM复制到KEY缓存
        case PCD_AUTHENT1:    					//0x0c		执行Cryptol算法的认证过程
            irqEn = 0x05;
            waitFor = 0x04;
            break;
        case PCD_CALCCRC:						//0x12		激活CRC
            irqEn = 0x11;
            waitFor = 0x10;
            break;
        case PCD_AUTHENT2: 						//0x14		执行Cryptol算法的认证过程二
            irqEn = 0x04;
            waitFor = 0x04;
            break;
        case PCD_RECEIVE:   					//0x16		接收  
            info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4);
            irqEn = 0x06;
            waitFor = 0x04;
            break;
        case PCD_LOADKEY: 						//0x19		将密钥从FIFO复制到KEY缓存
            irqEn = 0x05;
            waitFor = 0x04;
            break;
        case PCD_TRANSMIT: 						//0x1a		发送FIFO缓存数据
            irqEn = 0x05;
            waitFor = 0x04;
            break;
        case PCD_TRANSCEIVE: 					//1e		发送接收
	        info->nBitsReceived = -(ReadIO(RegBitFraming) >> 4);
            irqEn = 0x3D;
            waitFor = 0x04;
            break;
        default:
            status = MI_UNKNOWN_COMMAND;		//23
    }
	
	if (status == MI_OK)
    {
		irqEn |= 0x20;  						//发送中断                   
        waitFor |= 0x20;  						//发送中断
		timecnt=200000;
        WriteIO(RegInterruptEn,irqEn | 0x80); 
        WriteIO(RegCommand,cmd);
		while ((!(MpIsrInfo->irqSource & waitFor))&&(--timecnt));
		
		WriteIO(RegInterruptEn,0x7F);			//开中断			         
        WriteIO(RegInterruptRq,0x7F);           //清中断
        SetBitMask(RegControl,0x04);			//内部电流消耗模块包括晶振在内关闭			          
        WriteIO(RegCommand,PCD_IDLE); 			//清指令
		
		
		if (!(MpIsrInfo->irqSource & waitFor))   
        {                               
            status = MI_ACCESSTIMEOUT;			//
        }
        else
        {
            status = MpIsrInfo->status; 		//   超时       
        }
		
		if (status == MI_OK)                    
        {
			//有错
			tmpStatus = (ReadIO(RegErrorFlag) & 0x17);
			if (tmpStatus)//Error 标志指示上一个执行命令的错误状态
            {
				if (tmpStatus & 0x01)					  //如果检测到一个位冲突该位置位
                {
                    info->collPos = ReadIO(RegCollPos);   //取位碰撞的位置
                    status = MI_COLLERR;
                }
				else
                {
                    info->collPos = 0;					//没有位冲突
                    if (tmpStatus & 0x02)  
                    {
                        status = MI_PARITYERR;			//如果奇偶校验失
                    }
                }
				if (tmpStatus & 0x04)   				//如果SOF 不正确该位置 起始桢头不正确
                {
                    status = MI_FRAMINGERR;
                }
                if (tmpStatus & 0x10)   				//FIFO 缓冲区而FIFO 缓冲区已满时
                {
                    FlushFIFO();
                    status = MI_OVFLERR;
                }
 	            if (tmpStatus & 0x08) 					//如果RxCRCEn 置位且CRC 失败
	            {
                    status = MI_CRCERR;
	            }	
                if (status == MI_OK)					//
                    status = MI_NY_IMPLEMENTED;			//100	
			}
			if (cmd == PCD_TRANSCEIVE)
            {
                lastBits = ReadIO(RegSecondaryStatus) & 0x07;//显示最后接收字节的有效位个数
                if (lastBits)
                    info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
                else
                    info->nBitsReceived += info->nBytesReceived * 8;
            }			
		}
		else
		{
            info->collPos = 0x00;
        }
	
	}
	
	MpIsrInfo = 0;         
    MpIsrOut  = 0;
    return status;
}




/****************************************************************************
* 名    称:M500PcdConfig
* 功    能:复位rc500
* 入口参数:无
* 出口参数:0正常,其它错误码
****************************************************************************/
char M500PcdReset()
{
	char status = MI_OK;
    unsigned int timecnt=0;
	
	RC531RST_CLR();
	delay_1ms(25); 
    RC531RST_SET();  
    delay_50us(200); 
    RC531RST_CLR();  
    delay_50us(50);
	
	timecnt = 5000;
//	a = (ReadIO(RegCommand) & 0x3F);
	while ( (ReadIO(RegCommand) & 0x3F) && timecnt)
	{
		timecnt--;	
	}
	
	if(!timecnt)
    {
        status = MI_RESETERR;
    }
	else
	{
		if (ReadIO(RegCommand) != 0x00)
        {                           
            status = MI_INTERFACEERR;
        }
	}
	
	return status;
}





/****************************************************************************
* 名    称:M500PcdRfReset
* 功    能:复位RF卡
* 入口参数:MS 时间 毫秒
* 出口参数:0正常,其它错误码
****************************************************************************/
char M500PcdRfReset(unsigned char ms)
{
    char status = MI_OK;
	
    if(ms)
    {
        ClearBitMask(RegTxControl,0x03); 					//0x11 
        delay_1ms(2);                
        SetBitMask(RegTxControl,0x03); 						//输出信号将传递由发送数据调制的13.56MHz 能量载波
    }
    else
    {
        ClearBitMask(RegTxControl,0x03);  
    }
	
	WriteIO(RegCwConductance, 0x3f);		 	//0x3f, 设置输出驱动的电导系数
    return status;
}






/****************************************************************************
* 名    称:M500PcdConfig
* 功    能:配置RC500内部寄存器函数
* 入口参数:无
* 出口参数:0正常,其它错误码
****************************************************************************/
unsigned char M500PcdConfig(void)
{
	char status;
	if ((status = M500PcdReset()) == MI_OK)
    {
		WriteIO(RegClockQControl,0x00);					//0x1f  控制时钟产生用于90o相移的Q 信道时钟							
        WriteIO(RegClockQControl,0x40);					
        delay_50us(2);  
        ClearBitMask(RegClockQControl,0x40);			//如果该位为0 Q-时钟在复位后和从卡接收数据后自动校准
       
	   
	    WriteIO(RegBitPhase,0xAD);  					//0x1b 选择发送器和接收器时钟之间的位相位
		
		    
        WriteIO(RegRxThreshold,0xFF);					//0x1c 选择位解码器的阀值
		
		   
        WriteIO(RegRxControl2,0x01);					//0x1e	控制解码器的状态并定义接收器的输入源
		
		
        WriteIO(RegFIFOLevel,0x1A);						//0x29 定义FIFO 上溢和下溢警告界限
		
		
        WriteIO(RegTimerControl,0x02);					//0x2b 选择定时器的起始和停止条件
		
		
        WriteIO(RegIRqPinConfig,0x03); 					//0x2d 配置管脚IRQ 的输出状态
		
		
        M500PcdRfReset(1);
		
		
		
	}
	return status;
}




/****************************************************************************
* 名    称:M500PcdMfOutSelect
* 功    能:Select Command defined in ISO14443(MIFARE)
* 入口参数:无
* 出口参数:0正常,其它错误码
****************************************************************************/
char M500PcdMfOutSelect(unsigned char type)
{
    WriteIO(RegMfOutSelect,type&0x7);							//0x26 选择输出到管脚MFOUT 的内部信号
																//来自内部编码器的调制信号包络Miller 编码
    return MI_OK;
}





/****************************************************************************
* 名    称:MfConfig
* 功    能:芯片初始化
* 入口参数:无
* 出口参数:0正常,其它错误码
****************************************************************************/
unsigned char MfConfig(void)
{
	char status=MI_OK;
	char bak;


	bak=M500PcdConfig();
	if(bak!=MI_OK)status=bak;
	
	
	bak=M500PcdMfOutSelect(2);
	if(bak!=MI_OK)status=bak;
	
	return status;
}




/****************************************************************************
* 名    称:M500PcdSetTmo
* 功    能:设置定时时间
* 入口参数:tmoLength  时间
* 出口参数:无
****************************************************************************/
void M500PcdSetTmo(unsigned char tmoLength)
{
    switch(tmoLength)
    {  
        case 1:                       
            WriteIO(RegTimerClock,0x07); 
            WriteIO(RegTimerReload,0x6a);
            break;
        case 2:                       
            WriteIO(RegTimerClock,0x07); 
            WriteIO(RegTimerReload,0xa0);
            break;
        case 3:  
            WriteIO(RegTimerClock,0x09); 
            WriteIO(RegTimerReload,0xa0);
            break;
        case 4: 
            WriteIO(RegTimerClock,0x09);
            WriteIO(RegTimerReload,0xff);
            break;
        case 5:  
            WriteIO(RegTimerClock,0x0b); 
            WriteIO(RegTimerReload,0xff);
            break;
        case 6:                       
            WriteIO(RegTimerClock,0x0d); 
            WriteIO(RegTimerReload,0xff);
            break;
        case 7:                      
            WriteIO(RegTimerClock,0x0f); 
            WriteIO(RegTimerReload,0xff);
            break;
        default:                       
            WriteIO(RegTimerClock,0x15); 
            WriteIO(RegTimerReload,tmoLength);
            break;
    }     
}





/****************************************************************************
* 名    称:M500PiccCommonRequest
* 功    能:寻卡,防冲突,选择卡    返回卡类型(2 bytes)+ 卡系列号(4 bytes)
* 入口参数:req_code 寻卡指令 request code ALL = 0x52  or IDLE = 0x26
			agq 返回卡类型
* 出口参数:0正常,其它错误码
****************************************************************************/
char M500PiccCommonRequest(unsigned char req_code,unsigned char *atq)
{
	char status = MI_OK;
	
    M500PcdSetTmo(3);
	WriteIO(RegChannelRedundancy,0x03);			//奇校验
    ClearBitMask(RegControl,0x08);				//选择定时器的起始和停止条件-当数据接收结束时定时器自动停
    WriteIO(RegBitFraming,0x07);   				//定义要发送的最后一个字节的位数
    SetBitMask(RegTxControl,0x03); 				//管脚TX2 ,TX1上的输出信号将传递由发送数据调制的13.56MHz 能量载波
	
	ResetInfo(MInfo);							//清0
    SerBuffer[0] = req_code;
    MInfo.nBytesToSend = 1;   
					//     0x1e        
	status = M500PcdCmd((unsigned char)PCD_TRANSCEIVE,(unsigned char *)SerBuffer,(MfCmdInfo *)&MInfo);
    if (status)     
    {
        *atq = 0;
    } 
    else 
    {
        if (MInfo.nBitsReceived != 16) 
        {
            *atq = 0;
            status = MI_BITCOUNTERR;
        } 
        else 
        {
            status = MI_OK;
            memcpy((void *)atq,(void *)SerBuffer,2);
        }
    }	
	return status;
}





/****************************************************************************
* 名    称:M500PiccCommonRequest
* 功    能:防冲突 读卡的系列号 MLastSelectedSnr
* 入口参数:bcnt 0 
			snr  卡序列号

⌨️ 快捷键说明

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