大二寒假的时候实验室的门禁坏了,那个时候我们也才刚进入实验室不久,然后修好它就成了我们的任务,程序我有些一部分,硬件不是我负责的,恰逢整理资料,就算是复习一下韦根协议吧~
Wiegand26以及Wiegand34协议, 是由美国工业安全委员会SIA的隶属组织制定的一个关于存取控制的标准协议。非接触式IC卡读写器接口和输出,也采用了该协议标准。
1 韦根协议—韦根协议的数据信号
韦根数据输出由二根线组成,分别是DATA0 和 DATA1 ;二根线分别为‘0’或‘1’输出。
输出‘0’时:DATA0线上出现负脉冲;
输出‘1’时:DATA1线上出现负脉冲;
负脉冲宽度TP=100微秒;周期TW=1600微秒;
2 韦根协议— 韦根码的数据格式(韦根26)
第2到第9位为分组码,分组码共有8个二进制位,有256个状态;(电子卡HID码的低8位)
第10到第25位为标识码,标识码共16个二进制位,有65536个状态;(电子卡的PID号码)
第1位是第2到第13位的偶校验位;
第26位是第14到第25位的奇校验位。
E XXXX XXXX XXXX XXXXXXXXXXXXO
其中E表示前12位偶较验,X表示24位数据,O表示后12位奇校验,以上数据高位在前,从左至右顺序发送。
编号含义:
HID号码即Hidden ID code 隐含码,PID号码即Public ID code 公开码。 PID很容易在读出器的输出结果中找到,但HID在读出器的输出结果中部分或者全部隐掉。HID是一个非常重要的号码,它不仅存在于卡中,也存在于读卡器中。如果卡中的HID与读卡器中的HID不同的话,那么这张卡就无法在这个读卡器上正常工作。
然后我们将韦根两条数据线接到STM32的GPIO,通过外部中断的方式读取26位数据
初始化GPIO:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA,PORTC时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PC5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC5
//外部中断初始化函数
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
//GPIOC.5 中断线以及中断初始化配置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
//GPIOA.15 中断线以及中断初始化配置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
EXTI_InitStructure.EXTI_Line=EXTI_Line15;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
中断服务程序:
void EXTI9_5_IRQHandler(void)
{
if(KEY0==0) {
//LED0=!LED0;
weigen[ii]=1;
ii++;
if(ii==26)
{
ii=0;
check();
}
}
EXTI_ClearITPendingBit(EXTI_Line5); //清除LINE5上的中断标志位
}
void EXTI15_10_IRQHandler(void)
{
if(KEY1==0) {
//LED1=!LED1;
weigen[ii]=0;
ii++;
if(ii==26)
{
ii=0;
check();
}
}
EXTI_ClearITPendingBit(EXTI_Line15); //清除LINE15线路挂起位
}
然后将26位数据转为int类型数据,通过比较预存起来的卡号相比较来判断开门与否
void check()
{
for(i=0;i<26;i++)
{
if(weigen[i] == 1)
{
kaHao += pow(2,i);
}
}
for(m=0;m<40;m++)
{
if(kahaoku[m] == kaHao)
{
printf("Success! ");
LED1=1;
delay_ms(500);
LED1=0;
break;
}
else
{
//printf("Failed ");
LED1=0;
}
}
printf("%d",kaHao);
kaHao = 0;
// delay_ms(1000);
printf("\n");
}
写的很渣,用过一段时间后发现还有bug,经不起测试的程序0.0,曾经还被没存卡号的老师刷开门禁,真是丢人了,后来师兄的项目就做着这个就被换了,一开始觉得这个东西其实很简单,但是要做得好真的不是一件容易的事情,加油吧~