1.写在前面

韦根(Wiegand)协议是国际统一的标准,是摩托罗拉公司制定的通信协议。 这适用于门禁管理系统中涉及的读卡器和卡的许多特性。 韦根有很多类型的格式,一般有26 -比特、34 -比特、37 -比特格式,其中26 -比特格式是最普遍的格式。 标准的26位格式是开放格式,这意味着任何人都可以购买特定格式的HID卡,该特定格式类型是公开选项。 26位格式是广泛使用的行业标准,对所有HID的用户开放。 大多数门禁管理系统都接受标准的26位格式。

2.韦根接口

Wiegand接口通常包括两条线路,每个数据线0(data0)和数据1 )1(Data1)。 根据韦根时序图,Data0和Data1数据线在没有数据传输时都维持5V的高电平; Data0输出的低电平表示1比特0,而Data1输出的低电平表示1比特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:32769PID:34953 (卡面打印为2147584137001 34953 () ) ) ) )。

对应的二进制文件如下。

HID:1000 0000 0000 0001

PID:1000 1000 1000 1001

输出如下。

1217183334

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 10

|HID_L|PID|

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

虽然通常很少MCU提供硬件晶片增益接口,但是基于上面提到的晶片增益协议标准,可组合时序图并从MCU IO端口读取电平变化以分析晶片增益数据。 IO端口解析时序等级,有IO中断方式和循环查询读取方式,推荐IO中断方式以保证数据接收的实时性和准确性。 以下代码以中断方式实现。

头文件:

# ifndef _ wiegand _ h _ # define _ wiegand _ h _/wiegand数据格式# define WG _ data _ bit s34//wiegand格式dieg and efinewiegand _ data1 _ gpio gpio _ pin _ 13 # define wiegand _ data0_ gpio gpio _ pin _ 12 # define wiegand _ RCC Externvoididdataprintf(void; #endif源文件:

# include ‘ STM 32 F10 x.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/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4字节ID号

* 输出 :无**********************************************************/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位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