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

📄 rf.c

📁 pic16f73单片机控制FM1702读写IC卡的程序例程
💻 C
字号:
#include   <pic.h>
__CONFIG(HS&PROTECT&PWRTEN&BOREN&WDTEN);

//pic16f73//单片机端口定义
#define  cs          RC0
#define  so          RC1
#define  sck         RC2
#define  si          RC3
#define  msi      TRISC3
#define  data1       RC4
#define  data0       RC5
#define  hold        RC6
#define  cardin      RC7
#define  led         RA2
#define  rst1702     RA3

#define nop()   asm("nop")
#define clrwdt()  asm("clrwdt")
#define testbit(myvar,bit) ((myvar)&(1<<(bit)))
#define clrbit(myvar,bit) ((myvar)&=~(1<<(bit)))
#define setbit(myvar,bit) ((myvar)|=(1<<(bit)))

//;==============================================
//;FM1702SL控制寄存器定义
//;==============================================
#define		Page_Reg		          0x00
#define		Command_Reg		        0x01
#define		FIFO_Reg		          0x02
#define		FIFOLength_Reg		    0x04
#define		SecondaryStatus_Reg  	0x05
#define		InterruptEn_Reg		    0x06
#define		InterruptRq_Reg		    0x07
#define		Control_Reg		        0x09
#define		ErrorFlag_Reg		      0x0A
#define		BitFraming_Reg	     	0x0F
#define		TxControl_Reg		      0x11
#define		CwConductance_Reg	    0x12
#define		RxControl2_Reg		    0x1E
#define		ChannelRedundancy_Reg	0x22
#define         RxWait_Reg            0x21


//;==============================================
//;FM1702SL发送命令代码
//;==============================================
#define		WriteEE			  0x01
#define		LoadKeyE2		  0x0B
#define         Transmit                  0x1A
#define		Transceive		  0x1E
#define		Authent1		  0x0C
#define		Authent2		  0x14
////////////////////////////////////////////////////////////
bit rf_over;
char ack,retc,m,buff[48],Card_UID[5];
char mm[6]={0xff,0xff,0xff,0xff,0xff,0xff};

////===============================================
//以下为FM1702读写的子程序
//===============================================
char SPIRead(char SpiAddress,char *ramadr,char width);
char SPIWrite(char SpiAddress,char *ramadr,char width);
char SPI_Init();
char FM1702SL_Init();
char Clear_FIFO();
char Write_FIFO(char *ramadr,char width);
char Read_FIFO(char *ramadr);
char Request();
char Command_Send(char comm,char *ramadr,char width);
char Get_UID();
char Select_Tag();
char Load_Key(char n,char *ramadr);
char Load_Key_EE(char n);
char Authentication(char n);
char rdbuff(char sq,char n);
char Read_Block(char n);                    //
char Write_Block(char *ramadr,char n);
///+++++++++++++++++card++++++++++++++++++++++++///
void wiegend(char *ramadr,char n);

void inisub();
void  rddel();
void  delay50us();
void  delay1ms(char k);

main()
{
di();
 inisub();//初始化端口
 while(1)
  {clrwdt();
   delay1ms(40);
 rst1702=0;

 delay1ms(20);
 retc=SPI_Init();
 if(retc) goto cardsub_end1;//错误
 retc=FM1702SL_Init();
 if(retc) goto cardsub_end1;
 retc=Request();
 if(retc)
 {rf_over=0;
 	led=1;
 cardin=1;
 	goto cardsub_end1;}
 if(rf_over) goto cardsub_end1;
 retc=Get_UID();
 if(retc)
 {delay1ms(10);
 retc=Get_UID();}
 if(retc) goto cardsub_end1;
  retc=Select_Tag();
 if(retc)goto cardsub_end1;

 di();

// gettime();
 //**********寻卡结束********************//
  retc=Load_Key(0x80,mm);//加载购电区的密钥
  if(retc)goto cardsub_end1;//待定
  retc=Load_Key_EE(0x80);//加载购电区的密钥
  if(retc)goto cardsub_end1;//待定
 //***********开始卡操作******************//Load_Key Load_Key_EE

retc=rdbuff(0x7,0x4);//读块0
//if(retc){beep=1;beep_bad=1;goto cardsub_end1;}
if(retc){goto cardsub_end1;}
 // retc=Read_Block(0x5);
//  retc=Read_Block(0x6);
//for(m=0;m<16;m++)
//   buff[m]=m+1;    //
retc=Write_Block(buff,0x4);
if(retc){goto cardsub_end1;}
//
//for(m=0;m<16;m++)
//   buff[m]=0;
//retc=Read_Block(0x4);
 rf_over=1;
 led=0;
 cardin=0;

 m=0;
 ack=1;
 while(hold)
      { rddel();
      	m++;
      	if(m>250)
      	  { ack=0;
      	   break;}
      	}
 if(ack)
    wiegend(buff,16);

cardsub_end1:

     rst1702=1;


  	}
}

////////////////////延时////////////////////
void  rddel()
{        nop();
	       nop();
	       nop();
         nop();
	       nop();
	}

void  delay1ms(char k) //延时kMs
{char i,j;
	for (i=k;i>0;i--)
	   for(j=76;j>0;j--) rddel();
	}

void  delay50us()
{char i,j;
	for (i=3;i>0;i--)
	    rddel();
	}

////////////////初始化//////////////////////////////////
void inisub()
{//ADCON0=0x0;
 ADCON1=0x7;
 TRISA=0;
 PORTA=0xc;
 TRISC=0x48;
 PORTC=0xff;
 OPTION=0x2;

}

//维庚读写//////////////////////
void wiegend(char *ramadr,char n)
 {char i,j;
 	CLRWDT();
 	for(j=0;j<n;j++)
 	    for(i=8;i>0;i--)
 	        {if(testbit(ramadr[j],i-1))
 	        	  {data1=0;
 	        	  	delay50us();delay50us();
 	        	  data1=1;//	delay50us();
                                 rddel();
                                 rddel();
 	        	  	}
 	         else
 	            {data0=0;
 	        	  	delay50us();delay50us();
 	        	  data0=1;
                               rddel();//	delay50us();
                               rddel();
 	            	}
 	        	}
	}
////////////////SPI读//////////////////////////////////////
char SPIRead(char SpiAddress,char *ramadr,char width)
{  char i,j,adrtemp;

	adrtemp=SpiAddress;
	if((adrtemp&0xc0)==0)
	  {adrtemp=((adrtemp<<1)|0x80);
	  	cs=0;
	  	for(i=0;i<8;i++)
	  	{if((adrtemp<<i)&0x80)so=1;
	  		else so=0;
	  		sck=1;nop();nop();nop();nop();
	  		sck=0;
//	  		adrtemp=adrtemp<<1;
	  		}

	  	for(j=0;j<width;j++)
	  	    {if(j!=width-1)  adrtemp=(SpiAddress|0x40)<<1;
                      else   adrtemp=0;
                         ramadr[j]=0;
	  	    	for(i=0;i<8;i++)
	  	    	   {if((adrtemp<<i)&0x80)so=1;
	  	         	else so=0;
	  		        sck=1;
	  		        ramadr[j]=ramadr[j]<<1;
	  		        if(si)ramadr[j]+=0x1;

	  		        sck=0;
//	  		        adrtemp=adrtemp<<1;
	  	    	   	}

	  	    	}
	  	cs=1;
	  	return(0);
	  	}
 else return(1);
}
//=======================================================
//SPI写入程序
//入口:
//SpiAddress:	要写到FM1702SL内的寄存器地址[0x01~0x3f]
//*ramadr   要写入的数据在Ram中的首地址
//width:    要写入的字节数
//出口: 0:成功,1:失败
//作者: 张
//====================================================
char SPIWrite(char SpiAddress,char *ramadr,char width)
{char i,j,adrtemp;
	adrtemp=SpiAddress;
	if((adrtemp&0xc0)==0)
	  {adrtemp=((adrtemp<<1)&0x7e);
	  	cs=0;
	  	for(i=0;i<8;i++)
	  	{if((adrtemp<<i)&0x80)so=1;
	  		else so=0;
	  		sck=1;nop();nop();nop();
	  		sck=0;
//	  		adrtemp=adrtemp<<1;
	  		}

	  	for(j=0;j<width;j++)
	  	    {adrtemp= ramadr[j];
	  	    		for(i=0;i<8;i++)
	  	    	   {if((adrtemp<<i)&0x80)so=1;
	  	         	else so=0;
	  		        sck=1;  nop();nop();nop();
	  		        sck=0;
//	  		        adrtemp=adrtemp<<1;
	  	    	   	}
	  	    	}
	  	cs=1;
	  	return(0);
	  	}
 else return(1);
	}
char SPI_Init()
{
		char acktemp,temp[1];
		acktemp=SPIRead(Command_Reg,temp,1);
		if(acktemp) return(1);
		if(temp[0]) return(1);
		 else
		  { temp[0]=0x80;
		  	acktemp=SPIWrite(Page_Reg,temp,1);
		   	if(acktemp) return(1);
		   	acktemp=SPIRead(Command_Reg,temp,1);
		    if(acktemp) return(1);
		    if(temp[0]) return(1);
		    acktemp=SPIWrite(Page_Reg,temp,1);
		   	if(acktemp) return(1);
		   	return(0);
		   	}

}
char FM1702SL_Init()
{char acktemp,temp[1];
	temp[0]=0x7f;
	acktemp=SPIWrite(InterruptEn_Reg,temp,1);
	if(acktemp) return(1);
  temp[0]=0x7f;
	acktemp=SPIWrite(InterruptRq_Reg,temp,1);

	if(acktemp) return(1);
	temp[0]=0x5b;
	acktemp=SPIWrite(TxControl_Reg,temp,1);
	if(acktemp) return(1);
	temp[0]=0x1;
	acktemp=SPIWrite(RxControl2_Reg,temp,1);
	if(acktemp) return(1);
	temp[0]=0x7;
	acktemp=SPIWrite(RxWait_Reg,temp,1);
	if(acktemp) return(1);
//   acktemp=SPIRead(RxWait_Reg,temp,1);
//	    if(acktemp) return(1);
	return(0);
	}
////使FM1702SL进入软件powerdown模式
////;FM1702_Standby		发送FM1702_Standby信号
//char FM1702_Standby()
//{char acktemp,temp[1];
//	acktemp=SPIRead(Control_Reg,temp,1);
//	if(acktemp) return(1);
//	temp[0]=0x20;
//	acktemp=SPIWrite(Control_Reg,temp,1);
//	if(acktemp) return(1);
//	temp[0]=0x58;
//	acktemp=SPIWrite(TxControl_Reg,temp,1);
//	if(acktemp) return(1);
//	return(0);
//	}
////;使FM1702SL进入工作模式
////FM1702_Wakeup		发送FM1702_Wakeup信号
//char FM1702_Wakeup()
//{char acktemp,temp[1];
//	acktemp=SPIRead(Control_Reg,temp,1);
//	if(acktemp) return(1);
//	temp[0]=0xdf;
//	acktemp=SPIWrite(TxControl_Reg,temp,1);
//	if(acktemp) return(1);
//	acktemp=SPIRead(Control_Reg,temp,1);
//	if(acktemp) return(1);
//	if(temp[0]&0x20)return(1);
//	temp[0]=0x5b;
//	acktemp=SPIWrite(TxControl_Reg,temp,1);
//	if(acktemp) return(1);
//	return(0);
//
//	}
char Request()
{
char acktemp,temp[1];
	temp[0]=0x7;
	acktemp=SPIWrite(BitFraming_Reg,temp,1);
	if(acktemp) return(1);
//	temp[0]=0x7;
	acktemp=SPIRead(Control_Reg,temp,1);
	if(acktemp) return(1);

	temp[0]&=0xf7;
	acktemp=SPIWrite(Control_Reg,temp,1);
	if(acktemp) return(1);

	temp[0]=0x3;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,1);
	if(acktemp) return(1);
	temp[0]=0x52;
  acktemp=Command_Send(Transceive,temp,1);
	if(acktemp) return(1);
	acktemp=Read_FIFO(temp);
	if(acktemp) return(1);
	if((temp[0]!=0x2)|(buff[0]!=0x4)|(buff[1]!=0x0))
	return(1);

	return(0);
}
char Clear_FIFO()
{char acktemp,temp[1],i;
 acktemp=SPIRead(Control_Reg,temp,1);
	if(acktemp) return(1);
	temp[0]|=0x1;
	acktemp=SPIWrite(Control_Reg,temp,1);
	if(acktemp) return(1);
	for(i=0;i<5;i++)
	  {acktemp=SPIRead(FIFOLength_Reg,temp,1);
	  if(acktemp==0)
	      {if(temp[0]==0)return(0);}
	   }
	return(1);
	}

//++++++++++++++++++++++++++++++++++++++++++
char Write_FIFO(char *ramadr,char width)
{char acktemp;
	if(width==0)return(0);
//	 for(i=0;i<width;i++)
	   acktemp=SPIWrite(FIFO_Reg,ramadr,width);
	   	if(acktemp) return(1);
	return(0);
	}
char Read_FIFO(char *ramadr)
{char acktemp,i;
	acktemp=SPIRead(FIFOLength_Reg,ramadr,1);
	if(acktemp) return(1);
	if(ramadr[0]==0)return(1);
	if(ramadr[0]>16)return(1);
	i=ramadr[0];
	acktemp=SPIRead(FIFO_Reg,&buff[0],i);
	 return(0);
	}
char Command_Send(char comm,char *ramadr,char width)
{char acktemp,temp[1],i;
	acktemp=Clear_FIFO();
	if(acktemp) return(1);

  ///测试读写//////////////////////////////
//  acktemp=Read_FIFO(temp);
//	if(acktemp) return(1);
//  buff[0]=0x12;buff[1]=0x34;buff[2]=0x56;
//  acktemp=Write_FIFO(buff,3);
//	if(acktemp) return(1);
//	buff[0]=0;buff[1]=0;buff[2]=0;
//   acktemp=Read_FIFO(temp);
//	if(acktemp) return(1);
 /////////////////////////////////////////////
         acktemp=Write_FIFO(ramadr,width);
	if(acktemp) return(1);

	acktemp=SPIWrite(Command_Reg,&comm,1);
	   	if(acktemp) return(1);
	 for(i=0;i<16;i++)
          {
          acktemp=SPIRead(Command_Reg,temp,1);
	  if(acktemp==0)
	      {if(temp[0]==0)return(0);}
	   }
	   return(1);
	}
char Get_UID()
{char acktemp,temp[2],i;
	temp[0]=0x3;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,1);
	   	if(acktemp) return(1);
	temp[0]=0x93;temp[1]=0x20;
	acktemp=Command_Send(Transceive,temp,2);
	   	if(acktemp) return(1);
	acktemp=Read_FIFO(temp);
	if(temp[0]!=0x5)return(1);
	acktemp=0;
  for(i=0;i<5;i++)
     acktemp^=buff[i];
   if(acktemp) return(1);
   for(i=0;i<5;i++)
     Card_UID[i]=buff[i];
	return(0);
}

char Select_Tag()
{char acktemp,temp[1],i;
	temp[0]=0xf;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,1);
	   	if(acktemp) return(1);
	buff[0]=0x93;buff[1]=0x70;
	for(i=0;i<5;i++)
     buff[i+2]=Card_UID[i];
	acktemp=Command_Send(Transceive,buff,7);
	   	if(acktemp) return(1);
	acktemp=Read_FIFO(temp);
	if(temp[0]!=0x1)return(1);
	if(buff[0]!=0x8)return(1);
	return(0);
	}
//存储密钥
//*ramadr:密钥
//buff[0]密钥密钥地址
//buff[1]:0
//buff[2]~buff[9]不能放密码//////////////
char Load_Key(char n,char *ramadr)
{char acktemp,temp[1],i;
	 buff[0]=n;buff[1]=0x0;
for(i=0;i<6;i++)
	{ temp[0]=ramadr[i];
        buff[2+i+i]=(((ramadr[i]&0xf0)>>4)|((~ramadr[i])&0xf0));
        buff[3+i+i]=((temp[0]&0xf)|(~(temp[0]&0xf)<<4));
   }
acktemp=Command_Send(WriteEE,buff,0x0e);
  delay1ms(4);
acktemp=SPIRead(SecondaryStatus_Reg,temp,1);
if(acktemp) return(1);
if(temp[0]&0x40)
  {temp[0]=0x0;
  acktemp=SPIWrite(Command_Reg,temp,0x1);
  if(acktemp) return(1);
  return(0);}
temp[0]=0x0;
acktemp=SPIWrite(Command_Reg,temp,0x1);
return(1);
}
//加载密钥
//入口:buff[0]密钥密钥地址
//buff[1]:0
char Load_Key_EE(char n)
{char acktemp,temp[2];
	temp[0]=n;temp[1]=0x0;
	acktemp=Command_Send(LoadKeyE2,temp,0x2);
  if(acktemp) return(1);
	acktemp=SPIRead(ErrorFlag_Reg,temp,1);
if(acktemp) return(1);
if(temp[0]&0x40)return(1);
	return(0);
	}

//读卡:
//sq,扇区,n:读N块
char rdbuff(char sq,char n)
{char acktemp;
	acktemp=Authentication(sq);
	if(acktemp) return(1);
	acktemp=Read_Block(n);
	if(acktemp) return(1);
	return(0);
	}
//三重认证
//N认证的块:
//temp[0]:0x60为A密钥,0x61为B密钥
char Authentication(char sq)
{char acktemp,temp[6],i;
	temp[0]=0xf;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,0x1);
  if(acktemp) return(1);
  temp[0]=0x61;
  temp[1]=sq;
  for(i=0;i<4;i++)
  temp[2+i]=Card_UID[i];
  acktemp=Command_Send(Authent1,temp,0x6);
  if(acktemp) return(1);
	acktemp=SPIRead(ErrorFlag_Reg,temp,1);
if(acktemp) return(1);
 if(temp[0]&0xe)return(1);
 acktemp=Command_Send(Authent2,temp,0);
 if(acktemp) return(1);
 acktemp=SPIRead(ErrorFlag_Reg,temp,1);
if(acktemp) return(1);
if(temp[0]&0xe)return(1);
acktemp=SPIRead(Control_Reg,temp,1);
if(acktemp) return(1);
if(temp[0]&0x8)return(0);
	return(1);
	}
char Read_Block(char n)
{char acktemp,temp[2];
	temp[0]=0xf;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,0x1);
	if(acktemp) return(1);
	temp[0]=0x30;temp[1]=n;
	acktemp=Command_Send(Transceive,temp,2);
 if(acktemp) return(1);
	acktemp=SPIRead(ErrorFlag_Reg,temp,1);
  if(acktemp) return(1);
  if(temp[0]&0xe)return(1);
  acktemp=Read_FIFO(temp);
  if(acktemp) return(1);
  if(temp[0]!=16)return(1);
  return(0);
	}
char Write_Block(char *ramadr,char n)
{char acktemp,temp[2];
	temp[0]=0x7;
	acktemp=SPIWrite(ChannelRedundancy_Reg,temp,0x1);
	if(acktemp) return(1);
	temp[0]=0xa0;temp[1]=n;
	acktemp=Command_Send(Transceive,temp,2);
	if(acktemp) return(1);
	temp[1]= buff[0];
	acktemp=Read_FIFO(temp);
  if(acktemp) return(1);
  if(temp[0]!=1)return(1);
  if(buff[0]!=0xa)return(1);
  buff[0]=temp[1];
  acktemp=Command_Send(Transceive,buff,0x10);
	if(acktemp) return(1);
	acktemp=Read_FIFO(temp);
  if(acktemp) return(1);
  if(temp[0]!=1)return(1);
  if(buff[0]!=0xa)return(1);
  buff[0]=temp[1];
  return(0);
	}

⌨️ 快捷键说明

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