📄 wiegand.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// 韦根通信基本原理:
// 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 + -