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

📄 zlg500b.c

📁 RFID 使用C8051F020和周立功RC500开发模块
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "main.h"

#define __SRC
#include "zlg500B.h"
#undef	__SRC



void Serial_int(void) interrupt 4 using 1 		//串口中断来干什么呢
{
	uchar stx,index,BCC_sum=0,rcv_len=5;
	
	ES0=0;			//串行中断允许位,
	RI0=0;			//串口接收中断标志清零
	stx=SBUF0;		//收到的数据转到stx
					/*通信协议中500B向主机发出响应信号*/
	delay_50us(1);	//延时:协议中没有这一延时

	CON_485=1;		//TXD发送时为高	即是主机有数据发出了
	REN0=0;			//暂时的禁止接收
	SBUF0=ACK;		//主机发送应答信号  主机己经准备好了接收从ZLG500B发出来的数据帧
	while(TI0==0);
	TI0=0;
	CON_485=0;		//因为串口己经发送完毕,将RS485控制信号拉低
	REN0=1;			//允许接收

	for(index=0;index<rcv_len;index++)
	{
		START_T2(RCAP2_10ms);			//定时器2的10MS的溢出率是自动重装方式
		while(RI0==0&&TF2==0);			//没有接收到什么AND定时器2没有溢出
		if(RI0==1)						//如果产生了接收中断
		{	RI0=0;						
			ser_buffer[index]=SBUF0;		//发送数据
			if(index==LENGTH)			//发到最后一个数据了	
				rcv_len+=ser_buffer[index];			//最后一个数据与rcv_len
			if(index<rcv_len-2)						//当前序列号小于3
				BCC_sum^=ser_buffer[index];			//异或
				/*	BCC校验码计算数据块中所有的INFO字节然后将结果传送到数据块的最后一个字节
					如下式所示
					INFO[n] = BCC = ~ INFO[0] ⊕ INFO[1] ⊕ ... ⊕ INFO[n-1] (⊕ ... XOR ~…NOT)*/
		}
		else	break;
	}		//完成的数据的下行,命令模式
			
	STOP_T2();		//停用TIMER2
	ES0=1;			//串行口中断允许位
	
	if(stx!=STX)	return;		//如果主机收到的是错的数据
	if(index==rcv_len)
	{
		if(BCC_sum!=~ser_buffer[rcv_len-2])	return;		//BCC码又不对
		if(ser_buffer[rcv_len-1]!=ETX)	return;			//结束标志数据又不对
	}
	else	return;

	newdata=1;			//成功		当中断接收到新数据时该位置位
}	


uchar senddata()
{
  	uchar send_cnt=3;		//主机最多发3次STX信号
	uchar send_len;
	uchar temp;

	ES0=0;			//串行中断允许
	do
	{	CON_485=1;
		REN0=0;
		SBUF0=STX;		//主机向从机发送开始
		while(TI0==0);
		TI0=0;
		CON_485=0;		//发送完成就可以拉低

		REN0=1;
		START_T2(RCAP2_10ms);			//自动重装方式
		while(RI0==0&&TF2==0);			//没有接收到什么 AND 定时器2没有溢出		//这里是查询,一定要有事发生才行
										//很可能是串口收到数据(500B的应答信号)
		STOP_T2();

		if(RI0==1)						//如果收到500B的响应
		{	RI0=0;
			temp=SBUF0;
			delay_50us(1);
			if(temp==ACK)	break;		//收到500B的ACK信号
		}
	}while(--send_cnt);
	if(send_cnt==0)	return COMM_ERR;		//退出整个发送数据
		
	
	send_len=ser_buffer[LENGTH]+5;			//有5个附属字节
	ser_buffer[send_len-2]=0;
	ser_buffer[send_len-1]=ETX;			//最后发送一个终止符ETX结束本次发送
	
	REN0=0;
	CON_485=1;					//表示又要发送数据了
	for(send_cnt=0;send_cnt<send_len;send_cnt++)
	{
		SBUF0=ser_buffer[send_cnt];
		if(send_cnt<(send_len-2))			//非BCC和ETX字节
			ser_buffer[send_len-2]^=ser_buffer[send_cnt];		//求BCC
		if(send_cnt==send_len-3)
			ser_buffer[send_len-2]=~ser_buffer[send_len-2];		//最后求到BCC
		while(TI0==0);
		TI0=0;
	}
	CON_485=0;		//发送完成收工
	REN0=1;
	ES0=1;			//开中断
	
	return	COMM_OK;
}



uchar ser_comm(void)		//主机等待500B发回状态和响应数据.若在300MS内未检测到响应,则退出本次传输
{
	uchar ser_wdg=120;
	if(senddata()!=COMM_OK)	return COMM_ERR;		//数据发送失败

	START_T2(RCAP2_2ms);	                        //定时器溢出2MS	
	while(newdata==0&&ser_wdg!=0)
	{
		if(TF2)
		{
			START_T2(RCAP2_2ms);
			ser_wdg--;
		}
	}
	if(newdata)	
	{	
		newdata=0;
		return COMM_OK;
	}
	else
		return COMM_ERR;			//在300MS未栓测到响应	
}



#if mifs_request_en
uchar mifs_request(uchar _Mode,uchar idata *_TagType)		//发出询问命令,栓查在在效范围内是否有卡存在
{	
	ser_buffer[SEQNR]=0;						//数据交换包的序号
	ser_buffer[COMMAND]=0x41;					//命令对应的数值
	ser_buffer[LENGTH]=0x01;					//数据长度
	ser_buffer[DATA]=_Mode;						//只有一个数据
	
	if(ser_comm()!=COMM_OK)						//主机等待500B发回状态和响应数据.若在300MS内未检测到响应,则退出本次传输
		return COMM_ERR;
		
	if(ser_buffer[STATUS]==MI_OK)		//500B---主机:响应模式的状态字符
	{
		_TagType[0]=ser_buffer[DATA];
		_TagType[1]=ser_buffer[DATA+1];
	}
	return ser_buffer[STATUS];				//返回状态值
}
#endif

#if mifs_anticoll_en
uchar mifs_anticoll(uchar _Bcnt,uchar idata *_SNR)		//开始防冲突操作,返回卡的序列号
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x42;			                 //
	ser_buffer[LENGTH]=0x01;
	ser_buffer[DATA]=_Bcnt;
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;				//己经将数据发出
		
	if(ser_buffer[STATUS]==MI_OK)
	{
		memcpy(_SNR,&ser_buffer[DATA],4);			//复制字符得到卡序列号
	}
	return ser_buffer[STATUS];		
}
#endif

#if mifs_anticoll2_en
uchar mifs_anticoll2(uchar _Encoll,uchar _Bcnt,uchar idata *_SNR)			//可禁止或允许多张卡进入
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x71;
	ser_buffer[LENGTH]=0x02;
	ser_buffer[DATA]=_Encoll;
	ser_buffer[DATA+1]=_Bcnt;
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
		
	if(ser_buffer[STATUS]==MI_OK)
	{
		memcpy(_SNR,&ser_buffer[DATA],4);						//复制字符得到卡序列号
	}
	return ser_buffer[STATUS];
}
#endif

#if mifs_select_en
uchar mifs_select(uchar idata *_SNR,uchar idata *_Size)				//选择卡,返回卡的存贮容量
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x43;
	ser_buffer[LENGTH]=0x04;
	memcpy(&ser_buffer[DATA],_SNR,4);				//数据字节为卡的序列号
		
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
		
	if(ser_buffer[STATUS]==MI_OK)
	{
		*_Size=ser_buffer[DATA];			//返回卡的容量
	}
	return ser_buffer[STATUS];	
}
#endif

#if mifs_authentication_en
uchar mifs_authentication(uchar _Mode,uchar _SecNr)			//开始进行验证操作
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x44;
	ser_buffer[LENGTH]=0x02;
	ser_buffer[DATA]=_Mode;
	ser_buffer[DATA+1]=_SecNr;				//所访问卡的扇区号   必须小于16
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];	
}
#endif

#if mifs_authentication2_en
uchar mifs_authentication2(uchar _Mode,uchar _SecNr,uchar _KeyNr)		//可选择密匙区验证
{																		//_KeyNr 用于证实的密钥区号
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x72;
	ser_buffer[LENGTH]=0x03;
	ser_buffer[DATA]=_Mode;
	if(_SecNr<=32)
		ser_buffer[DATA+1]=_SecNr;
	else
		ser_buffer[DATA+1]=32+((_SecNr-32)<<2);	                   //为了支持S70卡
	ser_buffer[DATA+2]=_KeyNr;
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];	
}
#endif

#if mifs_authKey_en													//ISO 9798-2在RWM和RFID之间使用3轮确认
uchar mifs_authKey(uchar _Mode,uchar _SecNr,uchar *_Key)			//直接密码验证
{																	//_Key用于证实的密码首址
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x73;
	ser_buffer[LENGTH]=0x08;
	ser_buffer[DATA]=_Mode;
	if(_SecNr<=32)
		ser_buffer[DATA+1]=_SecNr;
	else
		ser_buffer[DATA+1]=32+((_SecNr-32)<<2);           	//为了支持S70卡
	memcpy(&ser_buffer[DATA+2],_Key,6);						//将密码向500B上面发
	
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];	
}
#endif

#if mifs_halt_en
uchar mifs_halt(void)					//将卡置于挂起状态
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x45;
	ser_buffer[LENGTH]=0x00;
	
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];	
}
#endif

#if mifs_read_en
uchar mifs_read(uchar _Adr,uchar idata *_Data)			//从卡中相应地址中读出一个16字节的数据块
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x46;
	ser_buffer[LENGTH]=0x01;
	ser_buffer[DATA]=_Adr;
		
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
		
	if(ser_buffer[STATUS]==MI_OK)					//如果读成功
	{
		memcpy(_Data,&ser_buffer[DATA],16);			//将数据复制出来
	}
	return ser_buffer[STATUS];		
}
#endif

#if mifs_write_en
uchar mifs_write(uchar _Adr,uchar idata *_Data)			//向指定地址写入16字节的数据
{
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x47;
	ser_buffer[LENGTH]=17;
	ser_buffer[DATA]=_Adr;
	memcpy(&ser_buffer[DATA+1],_Data,16);		//将要发送的数据复制到数据帧中
		
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];		
}
#endif

#if mifs_increment_en
uchar mifs_increment(uchar _Adr,long idata *_Value)			//增加访问单元块的字节中的数值,并将结果保存在卡的内部寄存器
{	uchar *temp=(uchar *)_Value;							//temp为首地址
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x48;
	ser_buffer[LENGTH]=5;
	ser_buffer[DATA]=_Adr;
	ser_buffer[DATA+1]=*(temp+3);
	ser_buffer[DATA+2]=*(temp+2);
	ser_buffer[DATA+3]=*(temp+1);
	ser_buffer[DATA+4]=*temp;
			
	if(ser_comm()!=COMM_OK)
		return COMM_ERR;
	
	return ser_buffer[STATUS];
}
#endif

#if mifs_decrement_en
uchar mifs_decrement(uchar _Adr,long idata *_Value)
{
	uchar *temp=(uchar *)_Value;
	ser_buffer[SEQNR]=0;
	ser_buffer[COMMAND]=0x49;
	ser_buffer[LENGTH]=5;
	ser_buffer[DATA]=_Adr;
	ser_buffer[DATA+1]=*(temp+3);
	ser_buffer[DATA+2]=*(temp+2);
	ser_buffer[DATA+3]=*(temp+1);
	ser_buffer[DATA+4]=*temp;

⌨️ 快捷键说明

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