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表示高电平信号。

3.韦根34协议

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

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

第 2-17 位: ID卡的HID码

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

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

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

例:一张ID卡内容为:

HID:32769   PID:34953  (假设卡面印字为:2147584137   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 中断线    PB12GPIO_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 中断线  PB13GPIO_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位0if (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位1if (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;                    //偶数个1else                              evencheck = 1;                 //奇数个1if(u_OddNums % 2 == 0)oddcheck = 1;                    //偶数个1else 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;} }elsereturn 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/韦根协议/9914978?fr=aladdin

韦根协议及IO模拟韦根34接口相关推荐

  1. STM32任意IO模拟8080时序驱动TFTLCD屏

    本篇硬件平台STM32F103ZET6.TFTLCD屏采用2.8寸.320*240分辨率.16bitRGB.37pin.ILI9341驱动. 本来准备使用STM32F429平台的,因为它有LTDC,顺 ...

  2. 关于App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...

  3. FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用

    写在前面 SPI协议系列文章: FPGA实现的SPI协议(一)----SPI驱动 FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用 在上篇文章,简要介绍了SPI协 ...

  4. LCD显示器的模拟和数字接口

    LCD显示器的模拟和数字接口 1 模拟接口 模拟和数字视频信源已经存在了很长时间,模拟视频常用于台式机,而数字视频则在笔记本电脑中比较流行.当前大量计算机使用的模拟视频输出,因此保证了模拟接口支持 ...

  5. Objective-C 入门(七)协议 protocol(JAVA中的接口)

    Objective-C 入门(七)协议 protocol(JAVA中的接口) 接口的作用想必大家都比较了解 OV中的 protocol 相比接口作用相似 语法稍有不同 1.先来看声明一个协议 在创建文 ...

  6. 关于IO模拟时序(SPI)的注意事项

    原则:有硬件I2C.SPI时尽量用硬件操作,省去IO模拟繁琐的时序调试.但在内部资源不够时就要用IO模拟总线了. 关于短延时:模拟时序时是否需要延时要看MCU与device的相对速度.比如I2C如果4 ...

  7. Vuejs模拟Ajax请求接口(天气预报API)跨域问题 - 案例篇

    vuejs的Ajax跨域请求问题一直都是前端人员开发vue项目进程中经常遇到的不得不解决的热门问题,也是个心病. 首先看一下,页面 报错内容提示: Access to XMLHttpRequest a ...

  8. 用到oracle是不是就是cs架构,用Oracle 的2Tier协议录制脚本模拟CS系统测试的案例和注意事项pdf...

    Loadrunner使用Oracle 的2Tier协议录制脚本模拟CS系统 测试的案例和注意事项 联系人:qinwenchuang@http://www.doczj.com/doc/f68c11e8f ...

  9. Java HttpURLConnection模拟请求Rest接口解决中文乱码问题

    Java HttpURLConnection模拟请求Rest接口解决中文乱码问题 参考文章: (1)Java HttpURLConnection模拟请求Rest接口解决中文乱码问题 (2)https: ...

  10. 个人微信号二次开发sdk协议,微信个人号开发API接口

    个人微信号二次开发sdk协议,微信个人号开发API接口 微信SDK程序概要说明 个人微信号开发sdk非微信ipad协议.非mac协议,非安卓协议,api可实现微信99%功能: 无需扫码登录.可收发朋友 ...

最新文章

  1. 盘点当下大热的 7 大 Github 机器学习『创新』项目
  2. 好程序员web前端分享js剪切板Clipboard.js 使用
  3. html5 table的表头拖动,可拖动table表头的实现
  4. Springboot+Maven在IDEA中配置好Maven后执行Reimport时提示:com.google.inject.internal.Errors.throwCreationExceptio
  5. Moravec角点检测算子
  6. 格力电器Java面试题_JAVA设计模式学习--工厂模式
  7. Simulink之不可控整流电路
  8. 浏览器中跨域创建cookie的问题
  9. kubernetes(K8s):管理云平台中多个主机上的容器化的应用
  10. javascript之Map 和 Set
  11. from Crypto.Cipher import AES报错
  12. mybatis--面向接口编程
  13. 中国武术和泰拳的对抗史
  14. spark ubuntu 分部署安装配置
  15. ED1 SoC Linux环境搭建
  16. Impala优化基本方案
  17. 公司福利直接影响员工的身心健康
  18. Excel以逗号拆分数据
  19. 计算机网络安全技术复习知识点总结
  20. MADDPG论文中文翻译

热门文章

  1. gma 教程 | 气候气象 | 计算标准化降水指数(SPI)
  2. 二进位注册文件_注册表导入时提示导入文件不是注册脚本,只能导入二进位注册文件...
  3. Python学习,55道django面试题,来试试吧
  4. GMSM —— 国密简介、概念(SM1-9)、ZUC祖冲之算法
  5. 正则方程(机器学习)
  6. 【javascript】字符串逆序输出
  7. 【INDIRECT】函数教你制作多级下拉菜单
  8. Java调用百度图像识别接口
  9. Matplotlib——绘制散点图并连线
  10. 主数据管理(MDM)的成熟度