韦根协议及IO模拟韦根34接口

韦根协议及IO模拟韦根34接口1 写在前面韦根 Wiegand 协议是国际上统一的标准 是由摩托罗拉公司制定的一种通讯协议 它适用于涉及门禁控制系统的读卡器和卡片的许多特性 韦根有许多种类格式 常见有 26 bit 34 bit 37 bit 格式 其中 26 bit 格式是最常用的格式 而标准 26 bit 格式是一个开放式的格式 这就意味着任何人都可以购买某一特定格式的 HID 卡 并且这些特定格式的种类是公开可选的 26 Bi

1.写在前面

韦根(Wiegand)协议是国际上统一的标准,是由摩托罗拉公司制定的一种通讯协议。它适用于涉及门禁控制系统的读卡器和卡片的许多特性。 韦根有许多种类格式,常见有26-bit 、34-bit、37-bit格式,其中26-bit格式是最常用的格式。而标准26-bit 格式是一个开放式的格式,这就意味着任何人都可以购买某一特定格式的HID卡,并且这些特定格式的种类是公开可选的。26-Bit格式就是一个广泛使用的工业标准,并且对所有HID的用户开放。几乎所有的门禁控制系统都接受标准的26-Bit格式。

2.韦根接口

Wiegand接口通常由2根线组成,它们分别是数据线0(Data0)和数据1(Data1)。韦根时序图规定,Data0和Data1数据线在没有数据传输使时均保持+5V的高电平;Data0输出低电平表示1bit 0,Data1输出低电平表示1bit 1。其中,电压值低于1V表示低电平信号,电压值高于4V表示高电平信号。

韦根协议及IO模拟韦根34接口

                                  

3.韦根34协议

韦根协议及IO模拟韦根34接口

Wiegand 34各数据位的含义如下:

第 1 位: 为输出第2—17位的偶校验位

第 2-17 位: ID卡的HID码

第18-33位: ID卡的PID号码

第 34 位: 为输出第18-33位的奇校验位

数据输出顺序:HID码和PID码均为高位在前,低位在后。

例:一张ID卡内容为:

HID:32769   PID:34953  (假设卡面印字为:   001   34953 )

相应的二进制为:

HID:1000 0000 0000 0001

PID:1000 1000 1000 1001

输出如下:

12                     1718                     33  34

0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 10 0 0 1 0 0 0 1 0 0 1   0

|       HID_L            |          PID            |

4.韦根34接收程序(stm32)

一般情况下,很少MCU提供硬件韦根接口,但可以根据上述韦根协议的标准,结合时序图,通过MCU IO口读取电平变化解析韦根数据。 IO口解析时序电平,有IO中断方式和循环查询读取方式,推荐使用IO中断的方式,保证数据接收实时性和准确性。以下代码为中断方式实现。

头文件:

#ifndef _WIEGAND_H_ #define _WIEGAND_H_ // Wiegand 数据格式 #define WG_DATA_BITS 34 //韦根34格式 // Wiegand 数据线接口 #define WIEGAND_PORT GPIOB #define WIEGAND_DATA1_GPIO GPIO_Pin_13 #define WIEGAND_DATA0_GPIO GPIO_Pin_12 #define WIEGAND_RCC_PORT RCC_APB2Periph_GPIOB #define WIEGAND_DATA1 PBin(13) #define WIEGAND_DATA0 PBin(12) // 外部函数 extern void WiegandInit(void); extern void IDDataPrintf(void); #endif 

源文件:

 #include "stm32f10x.h" #include "wiegand.h" #define USEING_INTERR //使能中断方式 static u8 u_EvenCheck = 2; //偶检验 static u8 u_OddCheck = 2; //奇校验 static u8 u_EvenNums = 0; //偶校验软件比较 static u8 u_OddNums = 0; //奇校验软件比较 static u8 u_DataBits = 0; //当前接收数据位数 static u8 IDData[4]; //4字节ID号 #ifdef USEING_INTERR /* * 函数名:WiegandInit * 功能 :外部中断引脚初始化 * 输入 : 无 * 输出 :无 / void WiegandInit(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(WIEGAND_RCC_PORT | RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Pin = WIEGAND_DATA0_GPIO | WIEGAND_DATA1_GPIO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //下拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(WIEGAND_PORT, &GPIO_InitStructure); //Data0 中断线 PB12 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12); EXTI_InitStructure.EXTI_Line = EXTI_Line12; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //Data1 中断线 PB13 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); EXTI_InitStructure.EXTI_Line = EXTI_Line13; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //中断优先级,尽可能设为最高优先级 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0x01; //抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /* * 函数名:EXTI15_10_IRQHandler * 功能 :两数据线中断函数 * 输入 : 无 * 输出 :无 / void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line12) != RESET) {//Data0-> 低电平表示1位0 if (u_DataBits == 0) {//偶校验 u_EvenCheck = 0; } else if (u_DataBits == (WG_DATA_BITS -1)) {//奇校验 u_OddCheck = 0; } else {//数据,4字节、高位在前 IDData[(WG_DATA_BITS - 2 - u_DataBits) / 8] &= ~(0x1 << ((WG_DATA_BITS - 2 - u_DataBits) % 8)); } u_DataBits++; EXTI_ClearITPendingBit(EXTI_Line12); } else if(EXTI_GetITStatus(EXTI_Line13) != RESET) {//Data1 -> 低电平表示1位1 if (u_DataBits == 0) {//偶校验 u_EvenCheck = 1; } else if (u_DataBits == (WG_DATA_BITS -1)) { //奇校验 u_OddCheck = 1; } else {//数据,4字节,高位在前 IDData[(WG_DATA_BITS - 2 - u_DataBits) / 8] |= (0x1 << ((WG_DATA_BITS - 2 - u_DataBits) % 8)); if(u_DataBits < WG_DATA_BITS / 2) u_EvenNums++; //计算1的个数来作偶校验 else if(u_DataBits < WG_DATA_BITS - 1) u_OddNums++; //计算1的个数来作奇校验 } u_DataBits++; EXTI_ClearITPendingBit(EXTI_Line13); } } /* * 函数名:Check * 功能 :奇偶校验,确定读出数据书否正确 * 输入 : 无 * 输出 :0->校验成功,数据有效 1->校验失败,数据无效 / u8 DataCheck(void) { u8 oddcheck,evencheck; if(u_DataBits >= WG_DATA_BITS) {//数据接收完才校验 //u_DataBits = 0; if(u_EvenNums % 2 == 0) evencheck = 0; //偶数个1 else evencheck = 1; //奇数个1 if(u_OddNums % 2 == 0) oddcheck = 1; //偶数个1 else oddcheck = 0; //奇数个1 u_EvenNums = 0; u_OddNums = 0; //清零 if((u_EvenCheck == evencheck) && (u_OddCheck == oddcheck)) {//校验成功 u_EvenCheck = 2; u_OddCheck = 2; return 0; //和实际的校验码一起返回成功 } else {//校验失败 u_EvenCheck = 2; u_OddCheck = 2; return 1; } } else return 2; } #else //查询方式 /* * 函数名:WiegandInit * 功能 :Wiegan数据线引脚初始化, * 输入 : 无 * 输出 :无 / void WiegandInit(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(WIEGAND_RCC_PORT | RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Pin = WIEGAND_DATA0_GPIO | WIEGAND_DATA1_GPIO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(WIEGAND_PORT, &GPIO_InitStructure); } /* * 函数名:GetWiegandData * 功能 :查询方式获取Wiegand数据 * 输入 : 无 * 输出 :无 / u8 GetWiegandData(void) { } #endif /* * 函数名:IDDataPrintf * 功能 :串口打印结果测试 * 输入 : 无 * 输出 :无 / void IDDataPrintf(void) { u8 CheckFlag = 0; u8 Buff[6],i; if(u_DataBits >= WG_DATA_BITS) { CheckFlag = DataCheck(); if(CheckFlag == 0) { USART_printf(USART1,"%s " "%d " "%d " "%d " "%d ","ID:", IDData[0],IDData[1],IDData[2],IDData[3]); USART_send_string("\n"); USART_send_string("DataBits/Check: "); USART_printf(USART1, "%d " "%d\n ",u_DataBits,CheckFlag); } else if(CheckFlag == 1) { USART_send_string("Read Data Failed\n"); } u_DataBits = 0; } }

代码简要分析:

1)只实现“IO中断”方式解析韦根数据;

2)数据解析在“EXTI15_10_IRQHandler”中断函数中,主要将电平解析成实际数据,这部分执行时间不长,在中断处理可以接受;

3)“DataCheck”为数据校验函数,主要验证解析数据的正确性;

4)“IDDataPrintf”为测试用,连接串口,将结果打印至电脑串口助手;自行实现串口打印代码,或者直接接仿真器在线查看查看解析到的数据。

5.注意事项

1)采用IO中断的方式接收解析,查询方式可能响应不过来;

2)采用IO中断方式时,尽可能将中断优先级设为最高,防止被其他中断打断,导致数据出错;

3)IO中断中处理事务尽可能少,减少耗时;

4)连接韦根数据线的IO口必须加RC滤波,从硬件上增加抗干扰能力。

6.参考

[1]  https://baike.baidu.com/item/韦根协议/?fr=aladdin

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200531.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午10:38
下一篇 2026年3月20日 上午10:38


相关推荐

  • 算法笔记 4.3 递归 ——谢尔宾斯基地毯「建议收藏」

    算法笔记 4.3 递归 ——谢尔宾斯基地毯「建议收藏」算法笔记递归谢尔宾斯基地毯

    2022年7月13日
    24
  • js中的匿名函数_js匿名函数怎么定义

    js中的匿名函数_js匿名函数怎么定义定义:匿名函数顾名思义指的是没有名字的函数,在实际开发中使用的频率非常高!也是学好JS的重点。匿名函数:没有实际名字的函数。首先我们声明一个普通函数://声明一个普通函数,函数的名字叫fnfunctionfn(){console.log(“张培跃”);}然后将函数的名字去掉即是匿名函数://匿名函数,咦,运行时,你会发现报错啦!function(){console.log(“张培跃”);}到此,你会发现单独运行一个匿名函数,由于不符合语法…

    2022年10月3日
    5
  • idea的svn怎么用_idea电脑配置

    idea的svn怎么用_idea电脑配置1、下载并安装安装时务必选择cmdlineclienttools,否则会缺少EXE文件2、在IDEA中配置SVN执行路径3、从SVN中导出项目4、设置设置上传文件分组ChangeList,用于忽略部分文件上传5、设置IDEA项目中忽略部分文件类型显示,这样就不会显示需要提交*.classpath;*.gitignore;*.hprof;*….

    2025年11月6日
    4
  • Linux系统打不开gedit文本编辑器

    Linux系统打不开gedit文本编辑器写实验发现打不开gedit,报错如下:Unabletoinitserver:无法连接:拒绝连接(gedit:1289):Gtk-WARNIING**:20:46:00.562:cannotopendisplay于是收录各种gedit不能用原因如下(错误提示不一定和上面一样):原因1:vnc连接被禁用了。这种情况下一般虚拟机也没连上网(打开浏览器显示没网),打开虚拟机设置>选项>vnc连接,启用。具体参数设置可看链接(Vmware官网,将虚拟机配置为V..

    2022年7月26日
    58
  • spring事件监听(eventListener)

    spring事件监听(eventListener)原理:观察者模式#spring的事件监听有三个部分组成,事件(ApplicationEvent)、监听器(ApplicationListener)和事件发布操作。事件#事件类需要继承ApplicationEvent,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12…

    2025年6月11日
    7
  • 数据结构与算法经典书籍——大话数据结构(带配套源码)

    数据结构与算法经典书籍——大话数据结构(带配套源码)书本下载链接:链接:https://pan.baidu.com/s/1jgVnbBZoLgA8pshpxbapOQ密码:577l配套程序链接:https://pan.baidu.com/s/1HYka42KngWT2el7T0HO7LA密码:i6hw虽说数据结构以美国人MarkAllenWeiss写的《数据结构与算法分析——C语言实现》最好,但是我发现他的书让人很不容易理解,可能我们…

    2022年6月3日
    57

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号