韦根26协议读头的使用及proteus仿真

本文详细介绍了韦根26协议的工作原理,包括数据传输方式、奇偶校验规则以及PID和HID编码。作者还展示了如何在Proteus中使用定时器和中断服务程序实现韦根26读头的数据发送与接收,以及在实际硬件中的连接示例。
摘要由CSDN通过智能技术生成

proteus仿真下载:

(仿真电路连接和实际硬件电路图有所不同,见文中说明)

链接:https://pan.baidu.com/s/1lE3fXhxlXvlca3QdciRIIw 
提取码:z9xa 

手上有一个韦根26协议的读头,想把它利用起来。

我购买的是UID IC卡,配合这种读头使用。

什么是韦根26协议:

        Wiegand(韦根)协议是由摩托罗拉公司制定的一种通讯协议,它适用于涉及门禁控制系统的读卡器和卡片的许多特性,其协议并没有定义通讯的波特率、也没有定义数据长度。

        韦根格式主要定义是数据传输方式:Data0和Data1两根数据线分别传输0和1,现在应用最多的是26bit,34bit,36bit,44bit等等,其中标准26-bit 格式是一个开放式的格式,任何人都可以购买某一特定格式的HID卡,并且这些特定格式的种类是公开可选的,26-Bit格式就是一个广泛使用的工业标准,并且对所有HID的用户开放,现在几乎所有的门禁控制系统都接受26-Bit格式的标准。

韦根数据是如何输出的:

      韦根码在数据的传输中只需两条数据线,一条为DATA0,另一条为DATA1。协议规定,两条数据线在无数据时均为高电平。DATA0为低电平代表数据0,DATA1为低电平代表数据1。(低电平信号低于1V,高电平信号大于4V),数据信号波形如图所示。

 

韦根数据的输出格式

标准韦根输出是由26位二进制数组成,例如有数据:01000110111000001001010101

各位的含义如下:

最高位,也就是序号为1的那位,是第2-13位的偶校验位。

最低位,也就是序号为26的那位,是第14-25位的奇校验位。

第2-9位对应与电子卡HID码的低8位

第10-25位对应电子卡的PID号码

以上数据从左至右顺序发送。

关于奇偶校验:

      偶校验就是加上校验位后,使得数据中1的个数为偶数。例如,在上面的韦根26数据中,第1位是第2-13位的偶校验位。第2-13位一共有6个1,算上校验位,要使1的个数为偶数,那么偶校验位必须为0。

     奇校验就是加上校验位后,使得数据中1的个数位奇数。例如,在上面的韦根26数据中,第26位是第14-25位的奇校验位。第14-25位一共有4个1,算上校验位,要使1的个数为奇数,那么奇校验位必须为1。

关于HID和PID号码:

       HIDHidden ID code 隐含码,PIDPublic ID code 公开码。PID很容易在读出器的输出结果中找到,但HID在读出器的输出结果中部分或者全部隐藏。

韦根26接收

       为了保证数据接收的实时性,需要在中断服务程序中接收数据,而不是通过查询的方式接收。

       以上就是韦根26协议的相关知识。


下面来看一下手中的读头

        我购买的韦根26协议读头是读IC卡的,卡扣是UID类型的IC卡。它的各个引脚功能为:

        读头需要提供9-16V的电源电压。韦根协议规定,无信号的时候是高电平,有信号的时候是低电平,那么,D0,D1上的电平是多少呢?使用15V电源供电的情况下,用万用表测量了一下是5V。

       读头读卡后输出了些什么数据呢?按照图示接好电源,将D0和D1连接到逻辑分析仪的两路上,将逻辑分析仪的捕获电平设置为自定义:0.2V,读卡后得到的波形如下:

        经测量,每个低电平的时间是404us,两个数据间的间隔是2ms。但是和韦根26协议规定的低电平持续时间:20us-200us略有不同。

        图中,粉色的是D0,每个负脉冲代表0,蓝色的是D1每个负脉冲代表1。图中上下两行数据加起来正好是26个。

解读一下这些数据:

         注意一下,这个时间轴是从左往右的,也就是左边数据是先发送的,右边数据是后发送的。

             那么读头发送的原始数据应该是:01000110111000001001010101 一共26位。

用proteus模拟韦根26读头的数据发送

使用定时器T1,采用16位定时器方式。

//8051 T1初始化
void Timer1_init()
{
 TMOD=0x10; //T1 16位定时器模式
 ET1=0;     //关闭定时器中断
 TR1=0;		//关闭定时器
 TF1=0;	    //清除TF1标志
}

      例如,就发送上面的这个数据:01000110111000001001010101  十进制的18580053

      发送数据0的时候,就是将数据线D0拉低404us,发送数据1的时候,就是将数据线D1拉低404us。

     首先设置定时器初值,用STC的下载器计算404us的预装入值。

拉低数据线,等待404us到时,之后抬高数据线,再等待2ms的时间,一位数据就发送完成了。

void Send_bit(bit bD)
{

   //拉低数据线D0 404us
   TL1 = 0x8C;		//设置定时初值
   TH1 = 0xFE;		//设置定时初值
   
   if(bD==0)
     Send_D0=0;
   else
     Send_D1=0;

   TR1=1; //开启定时器

   while(TF1 ==0); 	//等待溢出

   //时间到抬高数据线
   if(bD==0)
     Send_D0=1;
   else
     Send_D1=1;

   TF1=0;  	//清溢出标志
   TR1=0;	//关定时器

   //下面是数据位的间隔 2ms
   TL1 = 0xCD;		//设置定时初值
   TH1 = 0xF8;		//设置定时初值

   TR1=1;   //开启定时器

   while(TF1 ==0); 	//等待溢出
   TF1=0;  	//清溢出标志
   TR1=0;	//关定时器
}

将韦根26协议的数据装入一个无符号长整型变量里:

//二进制  0 100011011100000100101010 1 头尾两位为奇偶校验位,十进制是18580053

unsigned long WG26=18580053;  

无符号长整型是四个字节32位,装入26位的数据,则最前面的6位是无效的,循环移位6次,把无效数据移除。

//000000  01000110111000001001010101

 for(i=0; i<6; i++)
 {
   WGdata=WGdata<<1;
 }

//现在WGdata中的数据是  01000110111000001001010101  000000,后面多了6个0。

有效数据已经移动到最前面,可以开始发送了,循环26次发送数据
 for(i=0; i<26; i++)
 {
  if( (WGdata & 0x80000000) == 0x80000000 )
    Send_bit(1);   //如果最高位为1,发送1
  else
    Send_bit(0);   //如果最高位为0,发送0

    WGdata=WGdata<<1;   //左移1位
 }
}

完整发送函数:

//发送韦根26数据,用4个字节保存,一共32位
void SendWG26(unsigned long WGdata)
{
 uchar data i;

 //从最高位开始发送数据,将开头的6个无效数据位隔过去
 //18580053
 //000000  01000110111000001001010101
 //01000110111000001001010101  000000
 for(i=0; i<6; i++)
 {
   WGdata=WGdata<<1;
 }


 //有效数据位已经移到了开头,开始发送数据
 for(i=0; i<26; i++)
 {
  if( (WGdata & 0x80000000) == 0x80000000 )
    Send_bit(1);
  else
    Send_bit(0);

	WGdata=WGdata<<1;
 }
}

数据的接收

将数据线D0,D1连接到与门74HC08上,两条数据线上有数据发送时会产生INT0的下降沿中断。

(这只是仿真图,实际硬件连接有所不同)

在中断服务程序中接收数据:

还是用一个4字节的无符号长整型数据WG26,将收到的数据记入其最低位。每接到一位数据,左移一次。当接收到26个数据时,认为收到了读头发来的完整数据。设置接收完成标志ReceiveFlag=1;供主程序查询。

这里设置了一个超时检测,就是接收到的两位数据之间的时间间隔如果大于5ms就认为数据超时,(因为读头发来的数据每位之间的间隔是2ms)。这样,如果有意外的脉冲干扰,引起计数数据位的count值错误,也只会产生一次数据接收错误,将各种标志和变量全部清零后,不会影响下一次的数据接收。

在中断服务程序退出之前,一定要清除中断标志IE0,以免响应了无效数据的中断标志,产生接收错误。

void INT0_ISR(void)  interrupt 0           //外部中断0服务程序
{  
  //如果接到的两位数据之间间隔超过5ms,定时器溢出标志TF1置位
  //超时检测使用定时器T1,16位定时方式
  EX0=0;    //关中断


  //如果有定时器超时标志置位
  if(TF1==1)
  //数据有误,放弃数据
  {
   LCD_StrDisp(0x00,"Try Again       ");
   LCD_StrDisp(0x40,"TimeOut Error   ");   
   Beep(10);

   //隔过至少一个数据包的时间,以便放弃不完整的数据
   //延时100ms 	
   Delay50ms();
   Delay50ms();

   TR1=0;  //关定时
   TF1=0;  //清标志
   TL1 = 0x00; //设置定时初值	5ms 溢出
   TH1 = 0xEE; //设置定时初值	5ms 溢出

   count=0;
   WG26=0;
   ReceiveFlag=0;
  } 
  //如果数据位间隔未超时
  else
  {

   WG26=WG26<<1;

   if(RD0==0)
     //接收到了0
	 WG26=WG26&0xFFFFFFFE;
   else if(RD1==0)
     //接收到了1
	 WG26=WG26|0x00000001;

     count++;
    if(count==26)
    {
     count=0;
     ReceiveFlag=1;  
	 TR1=0; //关定时
	 TF1=0;	//清标志
    } 
	else
	{
	//为接收下一位做准备
	TR1 = 0; //关定时
    TF1 = 0; //清除TF1标志

    TL1 = 0x00; //设置定时初值
    TH1 = 0xEE; //设置定时初值

    //超过5ms溢出标志被置位
    TR1 = 1;	//定时器1开始计时 
	}
  }

	IE0=0;  //清除INT0中断标志,很重要!
    EX0=1;  //开中断
}

在主程序查询到接收完成标志后,开始对数据进行奇偶校验位的核对。

得到奇校验位,记入odd=1

将无效的6位移除

得到偶校验位,记入even=0

将偶校验位移除,统计前12位有几个1

100011011100 000100101010  1

有6个1,因此偶校验位应为0,核对接收到的偶校验位even是否为0

再统计后12位中有几个1

100011011100 000100101010  1

有4个1,因此奇校验位应为1,核对接收到的奇校验位odd是否位1

如果奇偶校验正确,显示数据,如果错误,给出错误提示。

完整检查数据函数:

bit DataCheck()
{
 uchar data count=0,i;
 unsigned long xdata temp;
 uchar idata odd,even;

 temp=WG26;

  //得到奇校验位
  if( (temp&0x00000001) ==0x00000001)
    odd=1;
  else
    odd=0;

 //统计第2-13位1的个数
 //把没用的6位移除
 for(i=0; i<6; i++)
   temp=temp<<1; 

   //得到偶校验位
 if( (temp&0x80000000) ==0x80000000)
    even=1;
 else
    even=0;
 
 //将偶校验位移除	
 temp=temp<<1;	 
 //开始统计第2-13位有几个1 
 for(i=0; i<12; i++)
 {
   if( (temp&0x80000000) == 0x80000000)
	  count++;
   temp=temp<<1;	
 }
 //判断偶校验位的正确性
 if( (count%2==0 && even==0) || (count%2==1 && even==1) )  
 {
	//接着判断奇校验位	14-25位
	count=0;
	for(i=0; i<12; i++)
	{
	  if( (temp&0x80000000) ==0x80000000)
	    count++;
      temp=temp<<1;
	}
	if( (count%2==0 && odd==1) || (count%2==1 && odd==0 ) )
	{
	  //数据正确
	  return 1;
	}
	else
	{
     return 0;
	}
 }
 else
   return 0;  //数据有错误  
}

实际硬件连接:

实际硬件连接和仿真有所不同,为了稳定接收数据,需要通过一片总线驱动芯片74LS573再连接74LS08到单片机,见图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值