韦尔根协议 - C 语言编程实现
一. 韦根协议介绍
定义
Wiegand(韦根)协议是由摩托罗拉公司制定的一种通讯协议,它适用于涉及门禁控制系统的读卡器和卡片的许多特性,其协议并没有定义通讯的波特率、也没有定义数据长度韦根格式主要定义是数据传输方式:Data0和Data1两根数据线分别传输0和1,现在应用最多的是26bit,34bit,36bit,44bit等等,其中标准26-bit 格式是一个开放式的格式,任何人都可以购买某一特定格式的HID卡,并且这些特定格式的种类是公开可选的,26-Bit格式就是一个广泛使用的工业标准,并且对所有HID的用户开放,现在几乎所有的门禁控制系统都接受26-Bit格式的标准。
时序
根数据输出由二根线组成,分别是DATA0 和 DATA1 ;二根线分别为‘0’或‘1’输出。
输出‘0’时:DATA0线上出现负脉冲;
输出‘1’时:DATA1线上出现负脉冲;
负脉冲宽度TP=100微秒;周期TW=1600微秒;
韦根26输出格式:
bit0为bit1~bit12的偶校验[1]
bit1~bit24为3字节卡号信息
bit25为bit13~bit24的奇校验
[1]通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数
二. 韦根协议编程
韦根协议接收
韦根的数据线:一个专门发送0, 一个专门发送1。用两个IO端口来接收韦根数据,两个IO都用中断方式来接收数据。代码入下:
volatile long reader = 0;
volatile int readerCount = 0;
long sign = 0xff0000;
void readerOne(void)
{
readerCount++;
reader = reader << 1;
reader |= 1;
}
void readerZero(void)
{
readerCount++;
reader = reader << 1;
}
void setup()
{
Serial.begin(9600);
attachInterrupt(3, readerZero, RISING);
attachInterrupt(2, readerOne, RISING);
delay(10);
reader = 0;
readerCount = 0;
}
void loop()
{
if(readerCount >=26)
{
Serial.print(" Reader:");
Serial.print(reader);
Serial.println("");
reader = reader & 0x1fffffe;
reader = reader >> 1;
long hid = reader & sign;
hid = hid >> 16;
hid = hid * 256 * 256;
sign = sign >> 8;
long pid1 = reader & sign;
pid1 = pid1 >> 8;
pid1 = pid1 * 256;
sign = sign >> 8;
long pid2 = reader & sign;
sign = 0xff0000;
long value = hid + pid1 + pid2;
Serial.println( value);
reader = 0, readerCount = 0;
hid = 0, pid1 = 0, pid2 = 0, value = 0;
}
}
韦根协议26发送
- 发送 偶校验位bit0
- 发送bit1~bit24 总共3字节卡号信息
- 发送bit25为bit13~bit24的奇校验
容易理解代码:http://blog.sina.com.cn/s/blog_4bb1137401010426.html
奇偶校验算法:https://www.cnblogs.com/Yogurshine/p/3949723.html
百度:https://baike.baidu.com/item/%E9%9F%A6%E6%A0%B9%E5%8D%8F%E8%AE%AE/9914978?fr=aladdin
void Send_Weigand26(unsigned char *str)
{
unsigned char one_num = 0;
unsigned char even = 0;
unsigned char odd = 0;
unsigned char check_temp,i;
check_temp = *str;
for(i = 0;i < 8;i++)
{
if(check_temp & 0x01)
one_num++;
check_temp >>= 1;
}
check_temp = *(str + 1);
for(i = 0;i < 4;i++)
{
if(check_temp & 0x80)
one_num++;
check_temp <<= 1;
}
if(one_num % 2 )
even = 1;
else
even = 0;
one_num = 0;
check_temp = *(str + 1);
for(i = 0;i < 4;i++)
{
if(check_temp & 0x01)
one_num++;
check_temp >>= 1;
}
check_temp = *(str + 2);
for(i = 0;i < 8;i++)
{
if(check_temp & 0x01)
one_num++;
check_temp >>= 1;
}
if(one_num % 2 )
odd = 0;
else
odd = 1;
one_num = 0;
WG_DATA0 = 1;
WG_DATA1 = 1;
Delay_1ms(2);
if(even)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
Delay_1ms(2);
for(i = 0;i < 24;i++)
{
WG_DATA0 = 1;
WG_DATA1 = 1;
if(str[0] & 0x80)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
(*(long*)&str[0]) <<= 1;
Delay_1ms(2);
}
WG_DATA0 = 1;
WG_DATA1 = 1;
if(odd)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
Delay_1ms(2);
}
void Send_Weigand34(unsigned char *str)
{
unsigned char one_num = 0;
unsigned char even = 0;
unsigned char odd = 0;
unsigned char check_temp,i;
check_temp = *str;
for(i = 0;i < 8;i++)
{
if(check_temp & 0×01)
one_num++;
check_temp >>= 1;
}
check_temp = *(str + 1);
for(i = 0;i < 8;i++)
{
if(check_temp & 0×01)
one_num++;
check_temp >>= 1;
}
if(one_num % 2 )
even = 1;
else
even = 0;
one_num = 0;
check_temp = *(str + 2);
for(i = 0;i < 8;i++)
{
if(check_temp & 0×01)
one_num++;
check_temp >>= 1;
}
check_temp = *(str + 3);
for(i = 0;i < 8;i++)
{
if(check_temp & 0×01)
one_num++;
check_temp >>= 1;
}
if(one_num % 2 )
odd = 0;
else
odd = 1;
one_num = 0;
WG_DATA0 = 1;
WG_DATA1 = 1;
Delay_1ms(2);
if(even)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
Delay_1ms(2);
for(i = 0;i < 32;i++)
{
WG_DATA0 = 1;
WG_DATA1 = 1;
if(str[0] & 0×80)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
(*(long*)&str[0]) <<= 1;
Delay_1ms(2);
}
WG_DATA0 = 1;
WG_DATA1 = 1;
if(odd)
{
WG_DATA1 = 0;
Delay_50us(8);
WG_DATA1 = 1;
}
else
{
WG_DATA0 = 0;
Delay_50us(8);
WG_DATA0 = 1;
}
Delay_1ms(2);
}
上一篇: 韦根协议简介
下一篇: 魏因加滕协议 - STM32 收发器
推荐阅读
-
go语言Socket编程-Socket编程 什么是Socket Socket,英文含义是插座、插孔,一般称之为套接字,用于描述IP地址和端口。可以实现不同程序间的数据通信。 Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用:Socket,该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 套接字的内核实现较为复杂,不宜在学习初期深入学习,了解到如下结构足矣。 套接字通讯原理示意 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 网络应用程序设计模式 C/S模式 传统的网络应用设计模式,客户机(client)/服务器(server)模式。需要在通讯两端各自部署客户机和服务器来完成数据通信。 B/S模式 浏览器(Browser)/服务器(Server)模式。只需在一端部署服务器,而另外一端使用每台PC都默认配置的浏览器即可完成数据的传输。 优缺点 对于C/S模式来说,其优点明显。客户端位于目标主机上可以保证性能,将数据缓存至客户端本地,从而提高数据传输效率。且,一般来说客户端和服务器程序由一个开发团队创作,所以他们之间所采用的协议相对灵活。可以在标准协议的基础上根据需求裁剪及定制。例如,腾讯所采用的通信协议,即为ftp协议的修改剪裁版。 因此,传统的网络应用程序及较大型的网络应用程序都首选C/S模式进行开发。如,知名的网络游戏魔兽世界。3D画面,数据量庞大,使用C/S模式可以提前在本地进行大量数据的缓存处理,从而提高观感。 C/S模式的缺点也较突出。由于客户端和服务器都需要有一个开发团队来完成开发。工作量将成倍提升,开发周期较长。另外,从用户角度出发,需要将客户端安插至用户主机上,对用户主机的安全性构成威胁。这也是很多用户不愿使用C/S模式应用程序的重要原因。 B/S模式相比C/S模式而言,由于它没有独立的客户端,使用标准浏览器作为客户端,其工作开发量较小。只需开发服务器端即可。另外由于其采用浏览器显示数据,因此移植性非常好,不受平台限制。如早期的偷菜游戏,在各个平台上都可以完美运行。 B/S模式的缺点也较明显。由于使用第三方浏览器,因此网络应用支持受限。另外,没有客户端放到对方主机上,缓存数据不尽如人意,从而传输数据量受到限制。应用的观感大打折扣。第三,必须与浏览器一样,采用标准http协议进行通信,协议选择不灵活。 因此在开发过程中,模式的选择由上述各自的特点决定。根据实际需求选择应用程序设计模式。 简单的C/S模型通信 Server端:Listen函数 func Listen(network, address string) (Listener, error) network:选用的协议:TCP、UDP, 如:“tcp”或 “udp” address:IP地址+端口号, 如:“127.0.0.1:8000”或 “:8000” Listener 接口: type Listener interface { Accept (Conn, error) Close error Addr Addr } Conn 接口: type Conn interface { Read(b byte) (n int, err error) Write(b byte) (n int, err error) Close error LocalAddr Addr RemoteAddr Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error } 参看 [<u>https://studygolang.com/pkgdoc</u>](https://studygolang.com/pkgdoc) 中文帮助文档中的demo: 示例代码:TCP服务器.go package main import ( "net" "fmt" ) func main { // 创建监听 listener, err:= net.Listen("tcp", ":8000") if err != nil { fmt.Println("listen err:", err) return } defer listener.Close // 主协程结束时,关闭listener fmt.Println("服务器等待客户端建立连接...") // 等待客户端连接请求 conn, err := listener.Accept if err != nil { fmt.Println("accept err:", err) return } defer conn.Close // 使用结束,断开与客户端链接 fmt.Println("客户端与服务器连接建立成功...") // 接收客户端数据 buf := make(byte, 1024) // 创建1024大小的缓冲区,用于read n, err := conn.Read(buf) if err != nil { fmt.Println("read err:", err) return } fmt.Println("服务器读到:", string(buf[:n])) // 读多少,打印多少。 }
-
韦尔根协议 - C 语言编程实现