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

📄 wiegand.c

📁 门禁控制器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
// 韦根通信基本原理:
//   1位奇校验位+韦根数据(24位/32位)+1位偶校验位
//   数据位发送/接收维持时间100us
//   数据位发送/接收周期为120ms
//////////////////////////////////////////////////////////////////////////////

#include "Global.h"

// 全局变量定义
extern data  char  User_id[6];		// 用户编号
extern idata char  wieformat;		// 韦根通信格式
extern data  uchar door_state;		// 门控状态
extern idata uchar decaddr;			// 设备地址	
extern idata uchar areaaddr;		// 分组地址

extern data  ulong Wiegand_dat;			// 韦根通信数据
extern data  uchar Wiecnt_max;			// 韦根通信长度
extern data  uchar Wgnd_count;			// 韦根数据位计数

extern bdata bit recv_end;				// 韦根接收结束
extern bdata bit W_rec_end;				// 韦根写记录结束
extern bdata bit Odd;					// 韦根校验
extern bdata bit Even;

extern xdata char  tele_code[12];		// 报警电话号码

extern data uint  trans_ctr;			// 发送数据指针
extern data uint  trans_size;			// 发送数据大小
extern xdata uchar trans_buf[TRANSBUFSIZE];	// 发送数据缓冲区

///////////////////////////////////////////////////////////////////////////////
// 100us延迟
///////////////////////////////////////////////////////////////////////////////
void Delay100us()
{
	idata uchar i;

	for(i=0;i<38;i++);
}

///////////////////////////////////////////////////////////////////////////////
// 韦根数据左移通信
///////////////////////////////////////////////////////////////////////////////
void Wiegand_rol()
{
	Wiegand_dat=Wiegand_dat<<1;
}

///////////////////////////////////////////////////////////////////////////////
// 中断2服务例程
///////////////////////////////////////////////////////////////////////////////
void int0() interrupt 0 using 1
{
	switch(Wgnd_count)
	{
	case 0:
		TR1=0;
		TF1=0;
		TH1=0xf5;
		TL1=0x33;			// 1.5ms
		TR1=1;
		Even=0;
		Wgnd_count++;
		break;
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
	case 16:
	case 17:
	case 18:
	case 19:
	case 20:
	case 21:
	case 22:
	case 23:
	case 24:
	case 25:
	case 26:
	case 27:
	case 28:
	case 29:
	case 30:
	case 31:
	case 32:
		TR1=0;
		TF1=0;
		TH1=0xf5;
		TL1=0x33;			// 1.5ms
		TR1=1;
		Wiegand_rol();
		Wgnd_count++;
		break;
	case 33:
		TR1=0;
		TF1=0;			// 接收完成
		Odd=0;
		recv_end=TRUE;
		Wgnd_count++;
		break;
	default:
		break;
	}
}

///////////////////////////////////////////////////////////////////////////////
// 中断2服务例程
///////////////////////////////////////////////////////////////////////////////
void int1() interrupt 2 using 1
{
	switch(Wgnd_count)
	{
	case 0:
		TR1=0;
		TF1=0;
		TH1=0xf5;
		TL1=0x33;			// 1.5ms
		TR1=1;
		Even=1;
		Wgnd_count++;
		break;
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
	case 16:
	case 17:
	case 18:
	case 19:
	case 20:
	case 21:
	case 22:
	case 23:
	case 24:
	case 25:
	case 26:
	case 27:
	case 28:
	case 29:
	case 30:
	case 31:
	case 32:
		TR1=0;
		TF1=0;
		TH1=0xf5;
		TL1=0x33;			// 1.5ms
		TR1=1;
		Wiegand_rol();		// 数据位0
		Wiegand_dat|=0x01;	// 接收数据位1
		Wgnd_count++;
		break;
	case 33:
		TR1=0;
		TF1=0;			// 接收完成
		Odd=1;
		recv_end=TRUE;
		Wgnd_count++;
		break;
	default:
		break;
	}
}

///////////////////////////////////////////////////////////////////////////////
// 韦根通信初始化
///////////////////////////////////////////////////////////////////////////////
void W_init()
{
	switch(wieformat)
	{
	case 1:
		Wiecnt_max=32;		// 自定义格式,自定义34位=1+32+1
		break;
	case 2:
		Wiecnt_max=24;		// 标准26位=1+24+1
		break;
	case 3:
		Wiecnt_max=32;		// 标准34位=1+32+1
		break;
	default:
		break;	
	}

	Wiegand_dat=0;
	Wgnd_count=0;
	Odd=0;
	Even=0;

	TCON|=0x05;

	EX1=0;					// 设置int1中断
	EX0=0;					// 设置int0中断

	return;
}

///////////////////////////////////////////////////////////////////////////////
// 偶校验
///////////////////////////////////////////////////////////////////////////////
bit W_oddchk()
{
	idata uchar i;
	idata uchar temp_odd=0;
	idata uint  tempw=0;

	switch(wieformat)
	{
	case 1:	
	case 3: 
		tempw=Wiegand_dat&0x0ffff;		// 韦根数据
		for(i=0;i<16;i++)
		{
			if(IBIT(tempw,i))temp_odd++;	// 偶计数
		}
		if(temp_odd&0x01)return FALSE;
		else return TRUE;
		break;
	case 2:
		tempw=Wiegand_dat&0x0fff;
		for(i=0;i<12;i++)
		{
			if(IBIT(tempw,i))temp_odd++;
		}
		if(temp_odd&0x01)return FALSE;
		else return TRUE;
		break;
	default:
		break;	
	}
}

///////////////////////////////////////////////////////////////////////////////
// 奇校验
///////////////////////////////////////////////////////////////////////////////
bit W_evenchk()
{
	idata uchar i;
	idata uchar temp_even=0;
	idata uint  tempw=0;

	switch(wieformat)
	{
	case 1:	
	case 3: 
		tempw=(Wiegand_dat>>16)&0x0ffff;	// 韦根数据
		for(i=0;i<16;i++)
		{
			if(IBIT(tempw,i))temp_even++;	// 奇校验
		}
		if(temp_even&0x01)return TRUE;
		else return FALSE;
		break;
	case 2: 
		tempw=(Wiegand_dat>>12)&0x0fff;
		for(i=0;i<12;i++)
		{
			if(IBIT(tempw,i))temp_even++;
		}
		if(temp_even&0x01)return TRUE;
		else return FALSE;
		break;
	default:
		break;	
	}
}

///////////////////////////////////////////////////////////////////////////////
// 韦根数据接收
///////////////////////////////////////////////////////////////////////////////
void Wiegand_recv()
{
	idata uchar tempaddr;

	if(TF1)
	{
		TR1=0;
		TF1=0;			// 接收位超时
		recv_end=FALSE;
		Wgnd_count=0;
		Wiegand_dat=0;
		Odd=0;
		Even=0;
	}

	if(recv_end)
	{
		tempaddr=(Wiegand_dat>>16)&0xff;
		if(tempaddr==areaaddr)
		{
			tempaddr=(Wiegand_dat>>8)&0xff;
			if(tempaddr==decaddr)
			{
				tempaddr=door_state&0x80;
				door_state=(uchar)(tempaddr+(Wiegand_dat&0xff));
			}
		}

		if(W_evenchk())
		{
			if(W_oddchk())
			{
			}
		}

		Wiegand_dat=0;
		Wgnd_count=0;
		Odd=0;
		Even=0;
		recv_end=FALSE;
	}
}

///////////////////////////////////////////////////////////////////////////////
// 发送韦根数据的1位
///////////////////////////////////////////////////////////////////////////////
void Send_bit(bit outbit)
{
	if(outbit)
	{
		DATA1=0;
		Delay100us();		// 100us维持周期
		DATA1=1;
	}
	else
	{
		DATA0=0;
		Delay100us();
		DATA0=1;
	}
}

///////////////////////////////////////////////////////////////////////////////
// 发送韦根数据
///////////////////////////////////////////////////////////////////////////////
void Send_Wiegand()
{
	idata uchar i;
	idata ulong c;

	Odd=0;				// 校验初始化
	Even=0;
	Odd=W_oddchk();		// 校验
	Even=W_evenchk();


	EX0=0;				// 禁止外部中断接收数据
	EX1=0;

	for(i=0;i<38;i++){;}

	Send_bit(Even);		// 发送奇校验位

	for(i=0;i<Wiecnt_max;i++)
	{
		TR1=0;
		TH1=0xf8;
		TL1=0xcc;			// 1ms
		TR1=1;				// T1参数设置
		while(!TF1);		// TF1溢出
		TF1=0;

		c=Wiegand_dat;		// 要发送的韦根数据

		switch(wieformat)
		{
		case 1:	
		case 3: 
			if(Wiegand_dat&0x80000000)
				Send_bit(1);	// 数据最高位先发送,数据1
			else
				Send_bit(0);	// 数据0
			Wiegand_dat=c<<1;	// 发送下一位
			break;
		case 2:
			if(Wiegand_dat&0x800000)
				Send_bit(1);	// 数据最高位先发送,数据1
			else
				Send_bit(0);	// 数据0
			Wiegand_dat=c<<1;	// 发送下一位
			break;
		default:
			break;
		}
	}

	TR1=0;
	TH1=0xf8;
	TL1=0xcc;
	TR1=1;
	while(!TF1);
	TF1=0;
	TF1=0;

	Send_bit(Odd);			// 发送偶校验位

	EX0=1;			// 允许外部中断接收数据
	EX1=1;

	for(i=0;i<4;i++){;}
}

///////////////////////////////////////////////////////////////////////////////
// 白名单注册
///////////////////////////////////////////////////////////////////////////////
void white_bill_reg()
{
	idata uchar i;

	Wiegand_dat=0x000000f1;			// F1命令注册白名单
	Wiegand_dat=Wiegand_dat<<8;

	Wiegand_dat=Wiegand_dat+decaddr;	// 设备地址
	Wiegand_dat=Wiegand_dat<<16;

	Wiegand_dat=Wiegand_dat+asctoint(User_id);	// 用户编号

	Send_Wiegand();

	for(i=0; i<10; i++)
		Wait10ms();

	// 发两次保险
	Wiegand_dat=0x000000f1;			// F1命令注册白名单
	Wiegand_dat=Wiegand_dat<<8;

	Wiegand_dat=Wiegand_dat+decaddr;	// 设备地址
	Wiegand_dat=Wiegand_dat<<16;

	Wiegand_dat=Wiegand_dat+asctoint(User_id);	// 用户编号
	Send_Wiegand();

	Wiegand_dat=0;
	Wgnd_count=0;
}

///////////////////////////////////////////////////////////////////////////////
// 白名单注销
///////////////////////////////////////////////////////////////////////////////
void white_bill_del()
{
	idata uchar i;

	Wiegand_dat=0x000000f2;			// F2命令注销白名单
	Wiegand_dat=Wiegand_dat<<8;

	Wiegand_dat=Wiegand_dat+decaddr;	// 设备地址
	Wiegand_dat=Wiegand_dat<<16;

	Wiegand_dat=Wiegand_dat+asctoint(User_id);	// 用户编号

	Send_Wiegand();

⌨️ 快捷键说明

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