韦根协议接收

那笑已成往昔 2017-04-17 03:54:34
有大神编写过STM32的韦根协议的接收程序吗?
怎么将脉冲信号转换为数字信号,一位一位的读取,数据错的,接收速度太快了
...全文
1257 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenjiannan521 2019-10-16
  • 打赏
  • 举报
回复
1、在硬件上加RC滤波电路的话,还会出错吗
2、没有加RC滤波电路的时候,读出卡号,几次之后会出现错误卡号,只能重启之后才能读出正确的数据,这是和RC滤波电路有关吗?
weixin_38982873 2017-09-18
  • 打赏
  • 举报
回复
楼主能参考一下你的代码吗?谢谢 q 1778325684
那笑已成往昔 2017-04-20
  • 打赏
  • 举报
回复
感谢 Prry大神的指导,以下附上楼主在大神源码上进行修改的STMF4系列的简单案例
//weigand.c韦根部分 源文件
#include "wiegand.h"
#define USEING_INTERR /
u8 WG_Data[WG_DATA_BITS] = {0};
static u8 u_DataBits = 0;//
#ifdef USEING_INTERR //
//韦根初始化
void WiegandInit(void)
{
u8 i;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

for(i=0; i<WG_DATA_BITS; i++)
{
WG_Data[i]=2;
}

RCC_AHB1PeriphClockCmd(WIEGAND_RCC_PORT,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//对应F1系列的RCC_APB2Periph_AFIO时钟使能
GPIO_InitStructure.GPIO_Pin = WIEGAND_DATA0_GPIO | WIEGAND_DATA1_GPIO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //与下一句合并对应 F1中GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(WIEGAND_PORT, &GPIO_InitStructure);

//Data0 接PB12
SYSCFG_EXTILineConfig(WIEGAND_PortSource,EXTI_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
SYSCFG_EXTILineConfig(WIEGAND_PortSource,EXTI_PinSource13);
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); 与上句相对应为F1的GPIO口作为外部中断源
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);

}
//中断服务函数
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line12) != RESET)
{
WG_Data[u_DataBits] = 0;
u_DataBits++;
EXTI_ClearITPendingBit(EXTI_Line12);
}
else if(EXTI_GetITStatus(EXTI_Line13) != RESET)
{
WG_Data[u_DataBits] = 1;
u_DataBits++;
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
//校验数据
u8 DataCheck(void)
{
u8 i;
u8 oddcheck,evencheck;
u8 u_OddNums,u_EvenNums;
u8 u_OddCheck,u_EvenCheck;
u_OddNums = u_EvenNums = 0;
u_EvenCheck = WG_Data[0];
u_OddCheck = WG_Data[WG_DATA_BITS-1];
if(u_DataBits >= WG_DATA_BITS)
{
for( i=1 ; i<(WG_DATA_BITS/2) ; i++ )
{
if(WG_Data[i]==1)
u_EvenNums++;
}
for( ; i<WG_DATA_BITS-1 ; i++ )
{
if(WG_Data[i]==1)
u_OddNums++;
}
if(u_EvenNums % 2 == 0)
evencheck = 0;
else
evencheck = 1;
if(u_OddNums % 2 == 0)
oddcheck = 1;
else
oddcheck = 0;
return 0;
if((u_EvenCheck == evencheck) && (u_OddCheck == oddcheck))
{
return 0;
}
else
{
return 1;
}
}
else
return 2;
}

//输出功能函数
void IDDataPrintf(void)
{
u8 i;
u32 IDCARD=0x00;
if(DataCheck()==0)
{
printf("ID : ");
for( i=1 ; i<WG_DATA_BITS-1 ; i++ )
{
if(WG_Data[i]==1)
IDCARD|=0x01;
IDCARD<<=1;
printf("%d",WG_Data[i]);
}
printf("\n");
IDCARD>>=1;
printf("Card:%u\n",IDCARD);
u_DataBits=0;
}
else if(DataCheck()==1)
{
printf("DataCheck Error\n");
u_DataBits=0;
}
else
{
printf("Waiting Receive\n");
}
}
#endif

图片为测试结果

Acuity. 2017-04-19
  • 打赏
  • 举报
回复
引用 7 楼 w371584831 的回复:
[quote=引用 6 楼 qq_20553613 的回复:] [quote=引用 4 楼 w371584831 的回复:] @Prry 大神,能给个完整的源码吗?或者再指点下小弟哪里出错了?个人感觉死在中断里了 //输出函数 void IDDataPrintf(void) { u8 t; if(DataCheck()==0) { for(t=0;t<3;t++) { USART_SendData(USART1, IDData[t]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } USART_RX_STA=0; } } //主函数 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { delay_ms(200); LED0!=LED0; IDDataPrintf(); } }
上面的就是完整的源码,如果是F1的单片机,直接编译执行!那个打印函数是我自己的测试代码,根据自己的需要自行编写。 //´®¿Ú´òÓ¡ void IDDataPrintf(void) { u8 CheckFlag = 0; u8 Buff[6],i; if(u_DataBits >= WG_DATA_BITS) { CheckFlag = DataCheck(); if(CheckFlag == 0) { #if 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 for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } else if(CheckFlag == 1) { #if 0 USART_send_string("Read Data Failed\n"); #else for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } u_DataBits = 0; } } [/quote]输出函数,我个人简化了,只进行判断奇偶校验的判断,正确就把数据输出。但串口没有获取到数据,是主函数出错了吗? int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { LED0=!LED0; delay_ms(200); IDDataPrintf(); } }[/quote] 在线仿真查看ID数组变量即可验证是否成功获取数据;串口不打印检查你的串口程序!
那笑已成往昔 2017-04-19
  • 打赏
  • 举报
回复
引用 6 楼 qq_20553613 的回复:
[quote=引用 4 楼 w371584831 的回复:] @Prry 大神,能给个完整的源码吗?或者再指点下小弟哪里出错了?个人感觉死在中断里了 //输出函数 void IDDataPrintf(void) { u8 t; if(DataCheck()==0) { for(t=0;t<3;t++) { USART_SendData(USART1, IDData[t]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } USART_RX_STA=0; } } //主函数 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { delay_ms(200); LED0!=LED0; IDDataPrintf(); } }
上面的就是完整的源码,如果是F1的单片机,直接编译执行!那个打印函数是我自己的测试代码,根据自己的需要自行编写。 //´®¿Ú´òÓ¡ void IDDataPrintf(void) { u8 CheckFlag = 0; u8 Buff[6],i; if(u_DataBits >= WG_DATA_BITS) { CheckFlag = DataCheck(); if(CheckFlag == 0) { #if 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 for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } else if(CheckFlag == 1) { #if 0 USART_send_string("Read Data Failed\n"); #else for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } u_DataBits = 0; } } [/quote]输出函数,我个人简化了,只进行判断奇偶校验的判断,正确就把数据输出。但串口没有获取到数据,是主函数出错了吗? int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { LED0=!LED0; delay_ms(200); IDDataPrintf(); } }
Acuity. 2017-04-18
  • 打赏
  • 举报
回复
引用 4 楼 w371584831 的回复:
@Prry 大神,能给个完整的源码吗?或者再指点下小弟哪里出错了?个人感觉死在中断里了 //输出函数 void IDDataPrintf(void) { u8 t; if(DataCheck()==0) { for(t=0;t<3;t++) { USART_SendData(USART1, IDData[t]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } USART_RX_STA=0; } } //主函数 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { delay_ms(200); LED0!=LED0; IDDataPrintf(); } }
上面的就是完整的源码,如果是F1的单片机,直接编译执行!那个打印函数是我自己的测试代码,根据自己的需要自行编写。 //´®¿Ú´òÓ¡ void IDDataPrintf(void) { u8 CheckFlag = 0; u8 Buff[6],i; if(u_DataBits >= WG_DATA_BITS) { CheckFlag = DataCheck(); if(CheckFlag == 0) { #if 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 for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } else if(CheckFlag == 1) { #if 0 USART_send_string("Read Data Failed\n"); #else for (i = 0;i < 4;i++) Buff[i] = IDData[i]; Buff[i++] = u_DataBits; Buff[i] = CheckFlag; g_Driver.OnSendCanData(Buff,6,0); #endif } u_DataBits = 0; } }
那笑已成往昔 2017-04-18
  • 打赏
  • 举报
回复
引用 3 楼 qq_20553613 的回复:
[quote=引用 2 楼 w371584831 的回复:] F1中引脚与外部中断配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);在F4中用什么替换
请查F4手册,F4应该是HAL库了,查一下也就一句话的事情![/quote]这个已经找到了,不过还是要谢谢大神。F4系列yongSYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource12);替换
那笑已成往昔 2017-04-18
  • 打赏
  • 举报
回复
@Prry 大神,能给个完整的源码吗?或者再指点下小弟哪里出错了?个人感觉死在中断里了 //输出函数 void IDDataPrintf(void) { u8 t; if(DataCheck()==0) { for(t=0;t<3;t++) { USART_SendData(USART1, IDData[t]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); } USART_RX_STA=0; } } //主函数 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); WiegandInit(); while(1) { delay_ms(200); LED0!=LED0; IDDataPrintf(); } }
Acuity. 2017-04-18
  • 打赏
  • 举报
回复
引用 2 楼 w371584831 的回复:
F1中引脚与外部中断配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);在F4中用什么替换
请查F4手册,F4应该是HAL库了,查一下也就一句话的事情!
那笑已成往昔 2017-04-18
  • 打赏
  • 举报
回复
F1中引脚与外部中断配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);在F4中用什么替换
Acuity. 2017-04-17
  • 打赏
  • 举报
回复
中断方式接收,2根中断引脚要加RC滤波,否则易出错。附上2年前上一家公司写的韦根解析程序。 头文件 #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 "main.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; //当前接收数据位数 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

27,508

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧