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

📄 rc500.c

📁 M64+MF RC500 程序从初始配置 -- 寻卡 -- 防冲突 -- 选卡 -- 密码验证 -- 读卡 --- 写卡
💻 C
字号:
//ICC-AVR application builder : 2008-04-18 08:36:23
//Target : M64
//Crystal: 8.0000Mhz
#include <iom64v.h>
#include <macros.h>
#include "RC500.h"
#include "uart.h"

/*****************************变量定义*****************************************/
MfCmdInfo Info;

/*****************************延时程序*****************************************/
void Delay_1us(void)
{
    asm("nop");
}

void Delay_us(uint16 n)
{
    uint16 i;
	for(i=0; i<n; i++)Delay_1us();
}

void Delay_1ms(void)
{
    uint16 i;
	for(i=0; i<1142; i++);
}

void Delay_ms(uint16 n)
{
    uint16 i;
	for(i=0; i<n; i++)Delay_1ms();
}

/*********************************硬件驱动程序*********************************/

void WriteIO(BYTE Address,BYTE value)
{
    WORD addr;
   
    addr = 0x2000 | Address;
    (*(volatile unsigned char *)0x2000) = (Address>>3) | 0x80; //选择寄存器页
    (*(volatile unsigned char *)addr) = value;		   	 	   //写入一个字节
}

BYTE ReadIO(BYTE Address)
{
    WORD addr;
   
    addr = 0x2000 | Address;
    (*(volatile unsigned char *)0x2000) = (Address>>3) | 0x80; //选择寄存器页
    return (*(volatile unsigned char *)addr);    	   	 	   //读取一个字节
}

/*****************************RC500功能程序************************************/
BYTE M500PcdReset(void)
{
    uint16 timecnt;
	
	CLR_RC500RST();
	Delay_ms(25);
	SET_RC500RST();
	Delay_ms(20);
	CLR_RC500RST();
	Delay_ms(10);
	
	timecnt=1000;
	while((ReadIO(RegCommand)&0x3F) & timecnt--);
	if(!timecnt)return 1;
	if(ReadIO(RegCommand)!=0x00)return 1;
	return 0;
}

//配置RC500内部寄存器函数
BYTE M500PcdConfig(void)
{
    if (!M500PcdReset())
    {
        WriteIO(RegClockQControl,0x00); //Q时钟复位
        WriteIO(RegClockQControl,0x40); //Q时钟写入0x40
        Delay_us(150);                  //延时100us以上
		WriteIO(RegClockQControl,0x00); //Q时钟清零 
		WriteIO(RegBitPhase,0xAD);      //写BitPhase寄存器 
        WriteIO(RegRxThreshold,0xFF);   //RxThreshold寄存器写入0FFH 
        WriteIO(RegRxControl2,0x01); 	//RxControl2寄存器写入01H 
        WriteIO(RegFIFOLevel,0x1A);  	//设置FIFO上溢和下溢的界限
        WriteIO(RegTimerControl,0x02);	//设置数据发送完成后停止定时器
        WriteIO(RegIRqPinConfig,0x03);  //配置IRQ管脚的输出状态
        M500PcdRfReset(1);				//打开天线
		WriteIO(RegMfOutSelect,0x02);   //选择输出到管脚MFOUT的信号为来自内部编码的调制信号
		return 0;              
    }
    else 
	    return 1;
}

BYTE M500PcdRfReset(BYTE val)
{
    if(val)
    {
        ClearBitMask(RegTxControl,0x03); 
        Delay_ms(2);                
        SetBitMask(RegTxControl,0x03); 
    }
    else
    {
        ClearBitMask(RegTxControl,0x03);  
    }
    return 0;
}

//置一位
BYTE SetBitMask(BYTE reg,BYTE mask)  
{
    BYTE tmp = 0x00;

    tmp = ReadIO(reg);
    WriteIO(reg,tmp | mask);  // set bit mask
    return 0x00;
}

//清一位
BYTE ClearBitMask(BYTE reg,BYTE mask)  
{
    BYTE tmp = 0x00;

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

//发送命令
BYTE  M500PcdCmd(void)
{
    BYTE i,n;
    BYTE lastBits;
    BYTE irqEn = 0x00;
    BYTE waitFor = 0x00;
	WORD timecnt = 0;

	switch(Info.cmd)
    {
        case PCD_IDLE:                  
             irqEn = 0x00;
             waitFor = 0x00;
             break;
        case PCD_WRITEE2:            
             irqEn = 0x11;
             waitFor = 0x10;
             break;
        case PCD_READE2:     
             irqEn = 0x07;
             waitFor = 0x04;
             break;
        case PCD_LOADCONFIG:  
        case PCD_LOADKEYE2:   
        case PCD_AUTHENT1:    
             irqEn = 0x05;
             waitFor = 0x04;
             break;
        case PCD_CALCCRC:
             irqEn = 0x11;
             waitFor = 0x10;
             break;
        case PCD_AUTHENT2: 
             irqEn = 0x04;
             waitFor = 0x04;
             break;
        case PCD_RECEIVE:     
             irqEn = 0x06;
             waitFor = 0x04;
             break;
        case PCD_LOADKEY: 
             irqEn = 0x05;
             waitFor = 0x04;
             break;
        case PCD_TRANSMIT: 
             irqEn = 0x05;
             waitFor = 0x04;
             break;
        case PCD_TRANSCEIVE: 
             irqEn = 0x3D;
             waitFor = 0x04;
             break;
        default: return 1;
    } 

	WriteIO(RegInterruptEn,0x7F); //清除中断使能
    WriteIO(RegInterruptRq,0x7F); //清除中断标志
    WriteIO(RegCommand,PCD_IDLE); //清除Command寄存器
	SetBitMask(RegControl,0x01);  //清除FIFO指针

	for(i=0; i<Info.nBytesToSend; i++)
	   WriteIO(RegFIFOData,Info.SerBuffer[i]); //将数据写入FIFO

    irqEn |= 0x20;                     
    waitFor |= 0x20;   
    WriteIO(RegInterruptEn,irqEn | 0x80);      //打开中断
	WriteIO(RegCommand,Info.cmd);              //将命令写入命令寄存器 	
	timecnt=1000;
	while(!(ReadIO(RegInterruptRq) & waitFor || !(timecnt--)));
	WriteIO(RegInterruptEn,0x7F);      //清除中断使能   
    WriteIO(RegInterruptRq,0x7F);      //清除中断标志寄存器   
    SetBitMask(RegControl,0x04);       //停止定时器     
    WriteIO(RegCommand,PCD_IDLE);      //清除命令寄存器
	
	if(!timecnt) 
	{ USART_String("timeout!\n");return 1; }                 //超时退出,返回1  
    if(ReadIO(RegErrorFlag)&0x17)
	{ USART_Hex(ReadIO(RegErrorFlag)&0x3F);USART_String("ERRor!\n");return 1; } //如果产生错误则返回1  
	
	if(Info.cmd == PCD_TRANSCEIVE)  
	{
	     n = ReadIO(RegFIFOLength);                    //读取FIFO中数据的总字节数
		 lastBits = ReadIO(RegSecondaryStatus) & 0x07; 
         Info.nBytesReceived = n;
		 
		 if(lastBits)
            Info.nBitsReceived = (n-1) * 8 + lastBits;
         else
            Info.nBitsReceived = n * 8;
		 if(n==0)n=1;
		 for(i=0; i<n; i++)
		    Info.SerBuffer[i]=ReadIO(RegFIFOData);
		
		 /*USART_Hex(n);
		 USART_Hex(lastBits);
		 for(i=0; i<n; i++)
		   USART_Hex(Info.SerBuffer[i]);*/
	} 
	return 0;             
}

//寻卡
BYTE M500PiccCommonRequest(void)
{
    WriteIO(RegTimerClock,0x09);        //设置定时器分频
    WriteIO(RegTimerReload,0xA0);       //设置定时器初值
	ClearBitMask(RegControl,0x08);      //寄存器Control清0 
	WriteIO(RegBitFraming,0x07);     	//寄存器BitFramming写入07H 		
	WriteIO(RegChannelRedundancy,0x03); //选择RF信道上数据完整性检测的类型和模式
    SetBitMask(RegTxControl,0x03);      //打开天线
	//ResetInfo(Info);					
	
	Info.cmd = PCD_TRANSCEIVE;          //命令为发送命令
	Info.nBytesToSend = 1;              //发送字节长度为1
	Info.nBytesReceived = 2;            //接收字节长度为2
	Info.SerBuffer[0] = PICC_REQIDL;    //数据为寻卡命令
	
	if(M500PcdCmd())return 1;             //调用发送命令子函数
	if(Info.nBitsReceived != 16) return 1;//判断接收到是不是16位,否则是错误的
	if(Info.SerBuffer[0]==0x04) return 0; //如果第一个字节是0x04,则是One卡,寻卡成功
	else return 1;                        //否则返回错误状态
}

//防冲突
BYTE M500PiccCascAnticoll(void)
{
    BYTE i;
    BYTE snr_check=0;
    BYTE status=0;
	
    WriteIO(RegTimerClock,0x07);        //设置定时器分频
    WriteIO(RegTimerReload,0X6A);       //设置定时器初值
    WriteIO(RegDecoderControl,0x28);    //防冲突处理
    ClearBitMask(RegControl,0x08);      //
    WriteIO(RegChannelRedundancy,0x03); //
    
	Info.cmd = PCD_TRANSCEIVE;          //命令为发送命令
	Info.nBytesToSend = 2;              //发送字节长度为1
	Info.nBytesReceived = 5;            //接收字节长度为2
	Info.SerBuffer[0] = PICC_ANTICOLL1; //数据0为防冲突命令
	Info.SerBuffer[1] = 0x20;        

	if(M500PcdCmd())status = 1;
    else 
	{
        for(i=0;i<4;i++)
            snr_check^=Info.SerBuffer[i]; //生成校验数据
        if(snr_check!=Info.SerBuffer[i])  //对比校验数据是否正确
            status = 1;
        else
        {
            for(i=0;i<5;i++)
                Info.CardNumber[i] = Info.SerBuffer[i]; //将卡号和CRC装到卡号缓存
        }
    }
    ClearBitMask(RegDecoderControl,0x20); //结束防冲突处理
    return status;
}

//选卡
BYTE M500PiccCascSelect(void)
{
    BYTE i;
	
	WriteIO(RegTimerClock,0x07);        //设置定时器分频
    WriteIO(RegTimerReload,0X6A);       //设置定时器初值 
    WriteIO(RegChannelRedundancy,0x0F); //
    ClearBitMask(RegControl,0x08); 		//
	
	Info.cmd = PCD_TRANSCEIVE;          //命令为发送命令
	Info.nBytesToSend = 7;              //发送字节长度为1
	Info.nBytesReceived = 1;            //接收字节长度为2
	Info.SerBuffer[0] = PICC_ANTICOLL1; //数据0为选卡命令
	Info.SerBuffer[1] = 0x70; 
	for(i=0; i<5; i++)
	     Info.SerBuffer[i+2] = Info.CardNumber[i];
	
	if(M500PcdCmd())return 1;
	if(Info.SerBuffer[0] != 0x08)return 1;
    return 0;
}

//直接验证密码
BYTE M500PiccAuthKey(BYTE *KEY,BYTE Sector,BYTE Block)
{
    Info.cmd = PCD_LOADKEY;             //命令为发送命令
	Info.nBytesToSend = 0x0C;           //发送字节长度为1
	Info.nBytesReceived = 0;            //接收字节长度为2
    M500HostCodeKey(KEY,Info.SerBuffer);//将密码转换成固定格式
	if(M500PcdCmd())return 1;           //调用发送命令子函数
	if(M500PiccAuthState(Sector*4+Block))
	   return 1;//Crytol卡验证子程序  
	return 0;          
}

//密码格式转换
void M500HostCodeKey(BYTE *uncoded,BYTE *coded)   
{
    BYTE cnt = 0;
    BYTE ln  = 0;     
    BYTE hn  = 0;   
	   
    for (cnt=0; cnt<6; cnt++)
    {
        ln = uncoded[cnt] & 0x0F;
        hn = uncoded[cnt] >> 4;
        coded[cnt * 2 + 1] = (~ln << 4) | ln;
        coded[cnt * 2 ] = (~hn << 4) | hn;
    }
}

//Crystol卡验证
BYTE  M500PiccAuthState(BYTE Block)
{
	BYTE i;
	
	Info.cmd = PCD_AUTHENT1;            //命令为发送命令
	Info.nBytesToSend = 0x06;           //发送字节长度为1
	Info.nBytesReceived = 0;            //接收字节长度为2 
	Info.SerBuffer[0] = PICC_AUTHENT1A; //Authen1命令
	Info.SerBuffer[1] = Block; 			//块号
	for(i=0; i<4; i++)					//卡号
	    Info.SerBuffer[i+2] = Info.CardNumber[i];

    if(M500PcdCmd())return 1;           //调用发送命令子函数
	if(ReadIO(RegSecondaryStatus)&0x07)return 1;
	
	Info.cmd = PCD_AUTHENT2;            //Authen2命令
	Info.nBytesToSend = 0; 				//发送数据为0字节
	Info.nBytesReceived = 0; 			//接收数据为0字节
	
	if(M500PcdCmd())return 1;            //调用发送命令子函数
	if(ReadIO(RegControl)==0x08)return 0;//值是否为0x08
	else return 1;
}

//读数据
BYTE M500PiccRead(BYTE Sector,BYTE Block)
{
    BYTE tmp = 0;

	WriteIO(RegTimerClock,0x09);        //设置定时器分频
    WriteIO(RegTimerReload,0xA0);       //设置定时器初值
    WriteIO(RegChannelRedundancy,0x0F);
    ResetInfo(Info);   
	
    Info.cmd = PCD_TRANSCEIVE;
	Info.SerBuffer[0] = PICC_READ;   
    Info.SerBuffer[1] = Sector*4+Block;
    Info.nBytesToSend   = 2;   
	Info.nBytesReceived = 0x10;            //接收字节长度为
	
    if(M500PcdCmd())return 1;           //调用发送命令子函数 
	if(Info.nBytesReceived != 16) return 1; 
	for(tmp=0;tmp<0x10;tmp++)
	  USART_Hex(Info.SerBuffer[tmp]);  
	return 0;
}

//写数据
BYTE M500PiccWrite(BYTE Sector,BYTE Block)
{
	Info.cmd = PCD_TRANSCEIVE;
	Info.SerBuffer[0] = PICC_WRITE;   
    Info.SerBuffer[1] = Sector*4+Block;
    Info.nBytesToSend   = 2;   
	Info.nBytesReceived = 0;            //接收字节长度为
	
	if(M500PcdCmd())return 1;           //调用发送命令子函数 

	WriteIO(RegTimerClock,0x09);        //设置定时器分频
    WriteIO(RegTimerReload,0xA0);       //设置定时器初值
    WriteIO(RegChannelRedundancy,0x0F);
	
	Info.cmd = PCD_TRANSCEIVE;
    Info.nBytesToSend   = 0x10;   
	Info.nBytesReceived = 0;            //接收字节长度为
	
	if(M500PcdCmd())return 1;           //调用发送命令子函数 
	if(Info.SerBuffer[0]==0x0A)return 0;
	return 1;
}

/*
//装载密码到EEPORM
BYTE M500PcdLoadKeyE2(WORD StartAddr)
{
    BYTE key[6];
	
	Info.cmd = PCD_LOADKEYE2;          //命令为发送命令
	Info.nBytesToSend = 2;              //发送字节长度为1
	Info.SerBuffer[0] = StartAddr & 0x0FF; //数据0为防冲突命令
	Info.SerBuffer[1] = StartAddr >> 8; 
	M500HostCodeKey(key,&Info.SerBuffer[2]);
	if(M500PcdCmd())return 1;
	return 0; 
}

//终止卡操作
BYTE M500PiccHalt(void)
{
    ResetInfo(Info);   
    Info.SerBuffer[0] = PICC_HALT ;      // Halt command code
    Info.SerBuffer[1] = 0x00;            // dummy address
    Info.nBytesToSend = 2;
    if(M500PcdCmd()) return 0;
    WriteIO(RegCommand,PCD_IDLE);
    return 1; 
}
*/
/******************************************************************************/

void Device_Init(void)
{
	MCUCR |= (1<<SRE); //使能总线
    XMCRA = 0x00; 
    XMCRB = 0x00;   
	DDR_RC500RST();
	DDR_RC500IRQ(); 
	//LED
	DDRB |= (1<<3);
	PORTB &= ~(1<<3);
	//A0,A1,A2
	DDRE |= (1<<3) | (1<<4) | (1<<5);
	PORTE |= (1<<3) | (1<<4) & ~(1<<5);
	/*EICRA = 0x20; //下降沿触发
 	EICRB = 0x00; 
 	EIMSK = 0x04; //外部中断2
	SEI();*/
}

void main(void)
{
    BYTE KEY[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	
	Device_Init();
	USART_Init();
	USART_String("Start to test RC500!\n");
    
	//初始化并配置寄存器
	if(M500PcdConfig())USART_String("Test error!\n");
	else USART_String("Test OK!\n");
	
	//寻卡
	if(!M500PiccCommonRequest())USART_String("Card has found!\n");
	else USART_String("Card has not found!\n");
	
	//防冲突
	if(!M500PiccCascAnticoll())USART_String("CascAnticoll success!\n");
	else USART_String("CascAnticoll failure!\n");
	
	//选卡
	if(!M500PiccCascSelect())USART_String("Card Select success!\n");
	else USART_String("Card Select failure!\n");
	
	//直接验证密码
	if(!M500PiccAuthKey(KEY,1,1))USART_String("Password validate success!\n");
	else USART_String("Password validate failure!\n");
	
	//读数据
	M500PiccRead(1,1);
	
	//写数据
	if(!M500PiccWrite(1,1))USART_String("Write success!\n");
	else USART_String("Write Failure!\n");
	while(1);
}

/*
#pragma interrupt_handler int2_isr:iv_INT2
void int2_isr(void)
{
    BYTE i,temp;
	BYTE irqMask;
	BYTE irqBits;
	
	irqMask = ReadIO(RegInterruptEn);
    irqBits = ReadIO(RegInterruptRq) & irqMask;
    Info.irqSource |= irqBits; 
	USART_Hex(temp = ReadIO(RegInterruptRq));
	if(temp&0x01)
	{
	    for(i=0; i<Info.nBytesToSend; i++)
	       WriteIO(RegFIFOData,Info.SerBuffer[i]); //将数据写入FIFO
	    WriteIO(RegInterruptRq,0x01);  
	}
}
*/

⌨️ 快捷键说明

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