基于STM32的韋根協(xié)議接收實(shí)現(xiàn)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
01 前言
今年疫情期間,為了便于管理,智能門(mén)禁系統(tǒng)被廣泛應(yīng)用,市面上大量的門(mén)禁終端都是使用韋根協(xié)議進(jìn)行通訊。什么是韋根協(xié)議?如何實(shí)現(xiàn)?本文詳細(xì)解讀。
02 韋根協(xié)議介紹
Wiegand(韋根)協(xié)議是由摩托羅拉公司制定的一種通訊協(xié)議,它適用于涉及門(mén)禁控制系統(tǒng)的讀卡器和卡片的許多特性;其協(xié)議并沒(méi)有定義通訊的波特率、也沒(méi)有定義數(shù)據(jù)長(zhǎng)度。它有很多格式,標(biāo)準(zhǔn)的韋根26-bit是最常用的格式。
此外,還有34-bit、36-bit、44-bit等格式。而標(biāo)準(zhǔn)的26-bit格式是一個(gè)開(kāi)放式的格式,這就意味著任何支持韋根26-bit輸入\輸出的設(shè)備都可以互相連接進(jìn)行通信。
韋根數(shù)據(jù)輸出由兩條數(shù)據(jù)線DATA0和DATA1,和公共的信號(hào)地GND組成。在沒(méi)有數(shù)據(jù)輸出時(shí),DATA0和DATA1都保持高電平(典型為+5V電平),若輸出'0'時(shí),DATA0輸出低脈沖而DATA1保持為高電平,輸出'1'時(shí),DATA1輸出低脈沖而DATA0保持為高。典型的低脈沖寬度為50us,輸出每一bit之前的間隔為1ms(實(shí)際的信號(hào)電平和時(shí)序由實(shí)際的韋根讀卡器決定)。下圖為韋根時(shí)序圖
韋根26:一個(gè)“韋根包”有26位數(shù)據(jù),第1位為第1到第13位的偶校驗(yàn),最后1位為第14到第26位的奇校驗(yàn),中間24位為數(shù)據(jù)位。
韋根34:即一個(gè)“韋根包”有34位數(shù)據(jù),格式為第1位為第1到第17位的偶校驗(yàn),最后1位為第18到第34位的奇校驗(yàn),中間32位為數(shù)據(jù)位。
03 軟件實(shí)現(xiàn)
本文實(shí)現(xiàn)韋根協(xié)議26bit/34bit的接收和數(shù)據(jù)解析,在數(shù)據(jù)接收時(shí)采用一個(gè)循環(huán)緩沖數(shù)組進(jìn)行接收,通過(guò)中斷接收,以信號(hào)的下降沿觸發(fā),不用判斷脈沖寬度,只要做個(gè)計(jì)時(shí)器,做個(gè)超時(shí)判斷數(shù)據(jù)接收完成進(jìn)行處理。
管腳初始化和外部中斷初始化:
//頭文件中對(duì)管腳進(jìn)行定義PC9 DATA0 PC8 DATA1 //C文件中進(jìn)行初始化/**----------------------------------------------------------------- * @函數(shù)名 wiegand_init * @功能 初始化wiegand接口,和外部中斷配置 * * @參數(shù) 無(wú) * @返回值 u8 0表示初始化完成***----------------------------------------------------------------*/u8 wiegand_init(void){ NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = DATA0_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = DATA0_GPIO_MODE; GPIO_Init(DATA0_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = DATA1_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = DATA1_GPIO_MODE; GPIO_Init(DATA1_GPIO_PORT, &GPIO_InitStructure); GPIO_EXTILineConfig(DATA0_GPIO_EXTI_PORT_SOURCE, DATA0_GPIO_EXTI_PIN_SOURCE); EXTI_InitStructure.EXTI_Line = DATA0_EXTI_LINE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = DATA0_EXTI_TRIGGER; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DATA0_EXTI_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); GPIO_EXTILineConfig(DATA1_GPIO_EXTI_PORT_SOURCE, DATA1_GPIO_EXTI_PIN_SOURCE); EXTI_InitStructure.EXTI_Line = DATA1_EXTI_LINE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = DATA1_EXTI_TRIGGER; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DATA1_EXTI_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); return 0;}
外部中斷接收處理:
void EXTI9_5_IRQHandler(void){ if(EXTI_GetFlagStatus(DATA0_EXTI_LINE)) //DATA0數(shù)據(jù)觸發(fā) { EXTI_ClearFlag(DATA0_EXTI_LINE); if(g_wiegandType.Flag.StartFlag == 0) //數(shù)據(jù)接收開(kāi)始標(biāo)志 { g_wiegandType.Flag.StartFlag = 1; g_wiegandType.DataIn.DataLen = 0; g_wiegandType.DataIn.Data[g_wiegandType.DataIn.DataLen++] = 0; //數(shù)據(jù)0存入數(shù)組 g_wiegandType.bitIntervalTime = MAX_BIT_INTERVAL_TIME; //數(shù)據(jù)位超時(shí)處理 } else { g_wiegandType.DataIn.Data[g_wiegandType.DataIn.DataLen++] = 0; g_wiegandType.bitIntervalTime = MAX_BIT_INTERVAL_TIME; } } if(EXTI_GetFlagStatus(DATA1_EXTI_LINE)) //DATA1數(shù)據(jù)觸發(fā) { EXTI_ClearFlag(DATA1_EXTI_LINE); if(g_wiegandType.Flag.StartFlag == 0) { g_wiegandType.Flag.StartFlag = 1; g_wiegandType.DataIn.DataLen = 0; g_wiegandType.DataIn.Data[g_wiegandType.DataIn.DataLen++] = 1; //數(shù)據(jù)1存入數(shù)組 g_wiegandType.bitIntervalTime = MAX_BIT_INTERVAL_TIME; } else { g_wiegandType.DataIn.Data[g_wiegandType.DataIn.DataLen++] = 1; g_wiegandType.bitIntervalTime = MAX_BIT_INTERVAL_TIME; } if(g_colStatus == 1) { COL1_LOW(); } else { COL1_HIGH(); } } }
收到一組數(shù)據(jù)后進(jìn)行解析:
/**----------------------------------------------------------------- * @函數(shù)名 wiegand26 * @功能 wiegand26數(shù)據(jù)解析 * * @參數(shù) 無(wú) * @返回值 u8 >0表示數(shù)據(jù)異常***----------------------------------------------------------------*/u8 wiegand26(void){ u8 i; u32 result; u8 odd = 0; u8 even = 0; if (g_wiegandType.DataIn.DataLen != 26) { return 1; } result = 0; for (i = 0; i < 24; ++i) { if(g_wiegandType.DataIn.Data[i+1] == 1) { result |= 1<<(23-i); if(i<12) { even++; } else { odd++; } } } g_wiegandType.result = result; if(even%2) //偶校驗(yàn)判斷 { if(g_wiegandType.DataIn.Data[0]!=1) return 3; } else { if(g_wiegandType.DataIn.Data[0]==1) return 3; } if(odd%2)//奇校驗(yàn)判斷 { if(g_wiegandType.DataIn.Data[25]==1) return 3; } else { if(g_wiegandType.DataIn.Data[25]!=1) return 3; } return 0;}/**----------------------------------------------------------------- * @函數(shù)名 wiegand34 * @功能 wiegand34數(shù)據(jù)解析 * * @參數(shù) 無(wú) * @返回值 u8 》0表示數(shù)據(jù)異常***----------------------------------------------------------------*/u8 wiegand34(void){ u8 i; u32 result; u8 odd = 0; u8 even = 0; if (g_wiegandType.DataIn.DataLen != 34) { return 1; } result = 0; for (i = 0; i < 32; ++i) { if(g_wiegandType.DataIn.Data[i+1] == 1) { result |= 1<<(31-i); if(i<16) { even++; } else { odd++; } } } g_wiegandType.result = result; if(even%2) { if(g_wiegandType.DataIn.Data[0]!=1) return 3; } else { if(g_wiegandType.DataIn.Data[0]==1) return 3; } if(odd%2) { if(g_wiegandType.DataIn.Data[33]==1) return 3; } else { if(g_wiegandType.DataIn.Data[33]!=1) return 3; } return 0;}
處理好的數(shù)據(jù)通過(guò)調(diào)試串口輸出,查看和自己的發(fā)送的卡號(hào)是否一致,如果異常請(qǐng)檢查DATA0和DATA1是否接反。
04 結(jié)語(yǔ)
韋根協(xié)議是一個(gè)比較簡(jiǎn)單的單工通信,很容易理解,如果有問(wèn)題歡迎討論。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!