[Źródło: http://www.st.com/en/evaluation-tools/32f746gdiscovery.html]
Wiegand
Jest to trój-przewodowym interfejsem komunikacyjny, z czego jedno z wyprowadzeń jest wspólną masą. Pozostałe dwa przewody to data0 (D0) oraz data1 (D1). Linia D0 służy do informowania o wystąpieniu bitu o wartości 0. Linia D1 odwrotnie.
Najczęściej wykorzystywany jest w systemach RFID do przesyłania informacji pomiędzy urządzeniami.
Działanie protokołu jest dosyć proste, wygląda następująco:
Jeśli nie są przesyłane żadne dane to na obu liniach utrzymywany jest stan wysoki. Gdy wysyłana jest jedynka to linia D0 jest w stanie wysoki, natomiast linia D1 w stanie niskim. W przypadku przesłania 0 działanie jest odwrotne, czyli na linii D1 utrzymywany jest stan wysoki, natomiast D0 otrzymuje stan niski.
W celu zabezpieczenia danych wykorzystywana jest kontrola parzystości oraz kontrola nieparzystości.Obie metody sprawdzają ilości jedynek jakie występują w określonej części wiadomości.
Odbieranie danych można rozwiązać na dwa sposoby, albo następuje odliczanie zadanej ilości bitów do odebrania lub należy odczekać określony czas i po jego przeminięciu przerwać transmisję i sprawdzić odebraną ramkę.
Jeśli odlicza się czas pomiędzy impulsami należy przyjąć, że czas impulsu nie będzie przekraczał 100us, natomiast czas pomiędzy impulsami nie będzie dłuższy niż 50 - 100 ms. Wszystko zależy od rodzaju urządzenia jakie się wykorzystuje.
Standard card po przesyłanych danych przez wiegand wyglądają następująco:
Karta RFID 26 bitów:
Ramka danych wygląda następująco:
P FFFF FFFF CCCC CCCC CCCC CCCC O
Pierwszy bit P oznacza bit kontroli parzystości dla bitów na pozycjach od 1 do 12(czyli FFFF FFFF CCCC). Ostatni bit O odnosi się do kontroli nieparzystości bitów na pozycjach od 13 do 24 (czyli CCCC CCCC CCCC).
Bity oznaczone jako FFFF FFFF oznaczją tzw. Facility Code, który może przyjmować wartości od 0 do 255. Bity z numerem karty oznaczone są jako C. Mogą przyjmować dane z zakresu od 0 do 65535.
Poniżej przykładowy przebieg odczytu takiej karty zarejestrowany na analizatorze stanów logicznych:
Czas wygenerowania impulsu:
Jak widać na obrazku powyżej impuls generowany jest na około 40us.
Czas przerwy pomiędzy przesłaniem kolejnych bitów danych:
Karta RFID 37 bitów:
Jest to podobny format co w przypadku 26 bitów, natomiast pozwala on na przechowywanie znacznie większych ilości danych.
Ramka danych wygląda następująco:
P FFFF FFFF FFFF FFFF CCC CCCC CCCC CCCC CCCC O
Jak widać na początku i na końcu występują bity parzystości oraz nieparzystości. Facility code może przyjmować wartości z zakresu od 0 do 65535 natomiast numer karty od 0 do 524287.
Poniżej przykładowy przebieg odczytu takiej karty zarejestrowany na analizatorze stanów logicznych:
Można też spotkać standardy 32, 34, 37 bitów w przypadku odczytu kart bądź w przypadku obsługiwania klawiatur formaty 4 czy 8 bitowe.
W celu zabezpieczenia danych wykorzystywana jest kontrola parzystości oraz kontrola nieparzystości.Obie metody sprawdzają ilości jedynek jakie występują w określonej części wiadomości.
Odbieranie danych można rozwiązać na dwa sposoby, albo następuje odliczanie zadanej ilości bitów do odebrania lub należy odczekać określony czas i po jego przeminięciu przerwać transmisję i sprawdzić odebraną ramkę.
Jeśli odlicza się czas pomiędzy impulsami należy przyjąć, że czas impulsu nie będzie przekraczał 100us, natomiast czas pomiędzy impulsami nie będzie dłuższy niż 50 - 100 ms. Wszystko zależy od rodzaju urządzenia jakie się wykorzystuje.
Standard card po przesyłanych danych przez wiegand wyglądają następująco:
Karta RFID 26 bitów:
Ramka danych wygląda następująco:
P FFFF FFFF CCCC CCCC CCCC CCCC O
Pierwszy bit P oznacza bit kontroli parzystości dla bitów na pozycjach od 1 do 12(czyli FFFF FFFF CCCC). Ostatni bit O odnosi się do kontroli nieparzystości bitów na pozycjach od 13 do 24 (czyli CCCC CCCC CCCC).
Bity oznaczone jako FFFF FFFF oznaczją tzw. Facility Code, który może przyjmować wartości od 0 do 255. Bity z numerem karty oznaczone są jako C. Mogą przyjmować dane z zakresu od 0 do 65535.
Poniżej przykładowy przebieg odczytu takiej karty zarejestrowany na analizatorze stanów logicznych:
Czas wygenerowania impulsu:
Jak widać na obrazku powyżej impuls generowany jest na około 40us.
Czas przerwy pomiędzy przesłaniem kolejnych bitów danych:
W tym przypadku czas przerwy wynosi ponad 2ms.
Karta RFID 37 bitów:
Jest to podobny format co w przypadku 26 bitów, natomiast pozwala on na przechowywanie znacznie większych ilości danych.
Ramka danych wygląda następująco:
P FFFF FFFF FFFF FFFF CCC CCCC CCCC CCCC CCCC O
Jak widać na początku i na końcu występują bity parzystości oraz nieparzystości. Facility code może przyjmować wartości z zakresu od 0 do 65535 natomiast numer karty od 0 do 524287.
Poniżej przykładowy przebieg odczytu takiej karty zarejestrowany na analizatorze stanów logicznych:
Można też spotkać standardy 32, 34, 37 bitów w przypadku odczytu kart bądź w przypadku obsługiwania klawiatur formaty 4 czy 8 bitowe.
Program:
Kod został przygotowany w oparciu o przerwania na dwóch pinach transmitujących dane oraz z obsługa przekroczenia czasu odliczoną na timerze. Program odbiera wszystkie dane od wieganda, i wyświetla je na ekranie (jeśli został również uruchomiony usart).
Dane odnośnie odebranych informacji przechowywane są w strukturze:
- enum wiegandReceiveDataNumber {
- wiegandNoData = 0,
- wiegandWrongFrame = 1,
- wiegand37Bit = 2,
- wiegand26Bit = 3,
- wiegand32Bit = 4
- };
- /* @brief: structure for wiegand data */
- typedef struct wiegandDataStruct {
- volatile uint8_t wiegandDat[kWiegandData]; /* receive data, one field one bit */
- volatile uint8_t wiegandDataPosition; /* number of receive data */
- uint32_t readCardNumber; /* card number read from receive data */
- uint32_t facilityCode; /* facility code read from receive data*/
- uint32_t oldReadCardNumber; /* Old card number, it contain previous card, reset after timeout */
- volatile uint16_t wiegandTimeout; /* calculate timeout for receiving data */
- enum wiegandReceiveDataNumber wiegandDataType; /* type of receive data, if receive 26 or 37 itp */
- volatile uint8_t wiegandStartReceive:2; /* set when first interrupt came, inform timer interrupt to start counting */
- } wiegandData_t;
Inicjalizacja pinów:
- void wiegandInitPins(uint8_t channel)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- if(channel == 1)
- {
- kData0ClockCh1;
- kData1ClockCh1;
- GPIO_InitStruct.Pin = kData0PinCh1;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(kData0PortCh1, &GPIO_InitStruct);
- GPIO_InitStruct.Pin = kData1PinCh1;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(kData1PortCh1, &GPIO_InitStruct);
- // NVIC config
- HAL_NVIC_SetPriority(kData0IrqnCh1, 0, 0);
- HAL_NVIC_EnableIRQ(kData0IrqnCh1);
- HAL_NVIC_SetPriority(kData1IrqnCh1, 0, 0);
- HAL_NVIC_EnableIRQ(kData1IrqnCh1);
- }
- else if(channel == 2)
- {
- kData0ClockCh2;
- kData1ClockCh2;
- GPIO_InitStruct.Pin = kData0PinCh2;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(kData0PortCh2, &GPIO_InitStruct);
- GPIO_InitStruct.Pin = kData1PinCh2;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(kData1PortCh2, &GPIO_InitStruct);
- // NVIC config
- HAL_NVIC_SetPriority(kData0IrqnCh2, 0, 0);
- HAL_NVIC_EnableIRQ(kData0IrqnCh2);
- HAL_NVIC_SetPriority(kData1IrqnCh2, 0, 0);
- HAL_NVIC_EnableIRQ(kData1IrqnCh2);
- }
- }
Biblioteka obsługuje dwa kanały wieganda. W związku z tym znajduje się w funkcji osobne włączenie dla każdego z nich. Domyślne pinu to:
- /* @brief: Definition of pins for wiegand CH1 */
- #define kData0PortCh1 GPIOA
- #define kData0PinCh1 GPIO_PIN_8
- #define kData0ClockCh1 __GPIOA_CLK_ENABLE()
- #define kData0IrqnCh1 EXTI9_5_IRQn
- #define kData1PortCh1 GPIOB
- #define kData1PinCh1 GPIO_PIN_15
- #define kData1ClockCh1 __GPIOB_CLK_ENABLE()
- #define kData1IrqnCh1 EXTI15_10_IRQn
- /* @brief: Definition of pins for wiegand CH2 */
- #define kData0PortCh2 GPIOB
- #define kData0PinCh2 GPIO_PIN_8
- #define kData0ClockCh2 __GPIOA_CLK_ENABLE()
- #define kData0IrqnCh2 EXTI9_5_IRQn
- #define kData1PortCh2 GPIOB
- #define kData1PinCh2 GPIO_PIN_9
- #define kData1ClockCh2 __GPIOB_CLK_ENABLE()
- #define kData1IrqnCh2 EXTI9_5_IRQn
Oprócz tego przygotowałem także funkcje pozwalającą na inicjalizacje pinów innych niż domyślne, natomiast trzeba do tego przygotować obsługę przerwań.
- void wiegandInitPinsCustom(GPIO_TypeDef *GPIOxD0, uint16_t PinD0, GPIO_TypeDef *GPIOxD1, uint16_t PinD1)
- {
- uint16_t dataPin[2] = {PinD0, PinD1};
- GPIO_InitTypeDef GPIO_InitStruct;
- PORT_CLOCK_ENABLE(GPIOxD0);
- PORT_CLOCK_ENABLE(GPIOxD1);
- GPIO_InitStruct.Pin = PinD0;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOxD0, &GPIO_InitStruct);
- GPIO_InitStruct.Pin = PinD1;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOxD1, &GPIO_InitStruct);
- for(uint8_t i = 0; i<2; i++)
- {
- /* Set proper NVIC for pins */
- if(dataPin[i] == GPIO_PIN_0){
- HAL_NVIC_SetPriority(EXTI0_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI0_IRQn);
- }
- else if(dataPin[i] == GPIO_PIN_1){
- HAL_NVIC_SetPriority(EXTI1_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI1_IRQn);
- }
- else if(dataPin[i] == GPIO_PIN_2){
- HAL_NVIC_SetPriority(EXTI2_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI2_IRQn);
- }
- else if(dataPin[i] == GPIO_PIN_3){
- HAL_NVIC_SetPriority(EXTI3_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI3_IRQn);
- }
- else if(dataPin[i] == GPIO_PIN_4){
- HAL_NVIC_SetPriority(EXTI4_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI4_IRQn);
- }
- else if((dataPin[i] >= GPIO_PIN_5) && (dataPin[i] <= GPIO_PIN_9)){
- HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
- }
- else if((dataPin[i] >= GPIO_PIN_10) && (dataPin[i] <= GPIO_PIN_15)){
- HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x01, 0);
- HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
- }
- }
- }
Funkcje odbierające dane w przerwaniach:
- void EXTI9_5_IRQHandler(void)
- {
- if(__HAL_GPIO_EXTI_GET_IT(kData0PinCh1) != RESET)
- {
- __HAL_GPIO_EXTI_CLEAR_IT(kData0PinCh1);
- if((HAL_GPIO_ReadPin(kData0PortCh1, kData0PinCh1)==GPIO_PIN_RESET) &&
- (HAL_GPIO_ReadPin(kData1PortCh1, kData1PinCh1)==GPIO_PIN_SET))
- {
- if(wiegandData.wiegandDataPosition < (kWiegandCard37Bits - 1))
- {
- wiegandData.wiegandStartReceive = 1;
- wiegandData.wiegandTimeout = 0;
- *(wiegandData.wiegandDat + wiegandData.wiegandDataPosition) = 0;
- wiegandData.wiegandDataPosition++;
- }
- }
- }
- if(__HAL_GPIO_EXTI_GET_IT(kData0PortCh2) != RESET)
- {
- __HAL_GPIO_EXTI_CLEAR_IT(kData0PortCh2);
- if((HAL_GPIO_ReadPin(kData0PortCh2, kData0PortCh2)==GPIO_PIN_RESET) &&
- (HAL_GPIO_ReadPin(kData1PortCh2, kData1PortCh2)==GPIO_PIN_SET))
- {
- if(wiegandDataCh2.wiegandDataPosition < (kWiegandCard37Bits - 1))
- {
- wiegandDataCh2.wiegandStartReceive = 1;
- wiegandDataCh2.wiegandTimeout = 0;
- *(wiegandDataCh2.wiegandDat + wiegandDataCh2.wiegandDataPosition) = 0;
- wiegandDataCh2.wiegandDataPosition++;
- }
- }
- }
- if(__HAL_GPIO_EXTI_GET_IT(kData1PortCh2) != RESET)
- {
- __HAL_GPIO_EXTI_CLEAR_IT(kData1PortCh2);
- if((HAL_GPIO_ReadPin(kData1PortCh2, kData1PortCh2)==GPIO_PIN_RESET) &&
- (HAL_GPIO_ReadPin(kData0PortCh2, kData0PortCh2)==GPIO_PIN_SET))
- {
- if(wiegandDataCh2.wiegandDataPosition < (kWiegandCard37Bits - 1))
- {
- wiegandDataCh2.wiegandStartReceive = 1;
- wiegandDataCh2.wiegandTimeout = 0;
- *(wiegandDataCh2.wiegandDat + wiegandDataCh2.wiegandDataPosition) = 0;
- wiegandDataCh2.wiegandDataPosition++;
- }
- }
- }
- }
- void EXTI15_10_IRQHandler(void)
- {
- if(__HAL_GPIO_EXTI_GET_IT(kData1PinCh1) != RESET)
- {
- __HAL_GPIO_EXTI_CLEAR_IT(kData1PinCh1);
- if((HAL_GPIO_ReadPin(kData1PortCh1, kData1PinCh1)==GPIO_PIN_RESET) &&
- (HAL_GPIO_ReadPin(kData0PortCh1, kData0PinCh1)==GPIO_PIN_SET))
- {
- if(wiegandData.wiegandDataPosition < (kWiegandCard37Bits - 1))
- {
- wiegandData.wiegandStartReceive = 1;
- wiegandData.wiegandTimeout = 0;
- *(wiegandData.wiegandDat + wiegandData.wiegandDataPosition) = 1;
- wiegandData.wiegandDataPosition++;
- }
- }
- }
- }
Przerwanie odbiera maksymalnie 37 bitów. Wcześniejsze przerwanie programu następuje po przekroczeniu czasu oczekiwania.
Sprawdzanie poprawności transmisji, jeśli w kodzie występują bity parzystości oraz nieparzystości. Na pozycji zerowej sprawdzany jest bit parzystości, ostatnia pozycja sprawdza bit nieparzystości. Należy pamiętać, że przed rozpoczęciem obsługi ramki danych należy wiedzieć jakie ilości danych mogą przyjść od układu do mikrokontrolera. Pozwoli to na bezpieczniejszą obsługę interfejsu, niż obsługiwanie jakiejkolwiek odebranej ramki, której długość będzie nieznana.
Poniżej znajdują się funkcje sprawdzające odebraną ramkę danych:
- static uint8_t wiegandCheckDataFrame(wiegandData_t * wiegandInfo,
- enum wiegandReceiveDataNumber receiveFormat)
- {
- if(receiveFormat == wiegand37Bit)
- {
- /* Check data frame */
- if(wiegandCheckEvenParity(wiegandInfo, 0, wiegand37Bit) == 0){
- return 0; /* Error wrong frame */
- }
- if(wiegandCheckOddParity(wiegandInfo, 36, wiegand37Bit) == 0){
- return 0; /* Error wrong frame */
- }
- }
- else if(receiveFormat == wiegand26Bit)
- {
- /* Check data frame */
- if(wiegandCheckEvenParity(wiegandInfo, 0, wiegand26Bit) == 0){
- return 0; /* Error wrong frame */
- }
- if(wiegandCheckOddParity(wiegandInfo, 25, wiegand26Bit) == 0){
- return 0; /* Error wrong frame */
- }
- }
- return 1; /* Frame OK */
- }
- static uint8_t wiegandCheckEvenParity(wiegandData_t * wiegandInfo, uint8_t evenParityPosition,enum wiegandReceiveDataNumber receiveFormat)
- {
- uint8_t number_of_one = 0;
- uint8_t even_parity_bit = 0;
- if(receiveFormat == wiegand37Bit)
- {
- for(uint8_t i=1; i<=18; i++)
- {
- if(wiegandInfo->wiegandDat[i] == 1) { number_of_one++; }
- }
- if(number_of_one % 2 == 0) { even_parity_bit = 0; }
- else { even_parity_bit = 1; }
- if(wiegandInfo->wiegandDat[evenParityPosition] == even_parity_bit)
- {
- return 1;
- }
- }
- else if(receiveFormat == wiegand26Bit)
- {
- for(uint8_t i=1; i<=12; i++)
- {
- if(wiegandInfo->wiegandDat[i] == 1) { number_of_one++; }
- }
- if(number_of_one % 2 == 0) { even_parity_bit = 0; }
- else { even_parity_bit = 1; }
- if(wiegandInfo->wiegandDat[evenParityPosition] == even_parity_bit)
- {
- return 1;
- }
- }
- return 0; /* Error */
- }
- static uint8_t wiegandCheckOddParity(wiegandData_t * wiegandInfo, uint8_t oddParityPosition, enum wiegandReceiveDataNumber receiveFormat)
- {
- uint8_t number_of_one = 0;
- uint8_t odd_parity_bit = 0;
- if(receiveFormat == wiegand37Bit)
- {
- for(uint8_t i=18; i<=35; i++)
- {
- if(wiegandInfo->wiegandDat[i] == 1) { number_of_one++; }
- }
- if(number_of_one % 2 == 0) { odd_parity_bit = 1; }
- else { odd_parity_bit = 0; }
- if(wiegandInfo->wiegandDat[oddParityPosition] == odd_parity_bit)
- {
- return 1;
- }
- }
- else if(receiveFormat == wiegand26Bit)
- {
- for(uint8_t i=13; i<=24; i++)
- {
- if(wiegandInfo->wiegandDat[i] == 1) { number_of_one++; }
- }
- if(number_of_one % 2 == 0) { odd_parity_bit = 1; }
- else { odd_parity_bit = 0; }
- if(wiegandInfo->wiegandDat[oddParityPosition] == odd_parity_bit)
- {
- return 1;
- }
- }
- return 0; /* Error */
- }
Wypisanie odebranych danych na ekranie:
- static void wiegandDecode37BitNumber(wiegandData_t *wiegandInfo)
- {
- #if DEBUG_USART == 1
- char data[50] = {0};
- #endif
- /* Get facility code */
- for(uint8_t i=1; i<=16; i++)
- {
- if(*(wiegandInfo->wiegandDat + i) == 1){
- wiegandInfo->facilityCode = wiegandInfo->facilityCode << 1;
- wiegandInfo->facilityCode = wiegandInfo->facilityCode + 0x01;
- }
- else{
- wiegandInfo->facilityCode = wiegandInfo->facilityCode << 1;
- }
- }
- /* Get card number */
- for(uint8_t i=17; i<=35; i++)
- {
- if(*(wiegandInfo->wiegandDat + i) == 1){
- wiegandInfo->readCardNumber = wiegandInfo->readCardNumber << 1;
- wiegandInfo->readCardNumber = wiegandInfo->readCardNumber + 0x01;
- }
- else{
- wiegandInfo->readCardNumber = wiegandInfo->readCardNumber << 1;
- }
- }
- #if DEBUG_USART == 1
- sprintf(data, "FacilityCode %lu", wiegandInfo->facilityCode);
- DebugMsg(data);
- sprintf(data, "CardNumber %lu", wiegandInfo->readCardNumber);
- DebugMsg(data);
- #endif
- }
- static void wiegandDecode26BitNumber(wiegandData_t *wiegandInfo)
- {
- #if DEBUG_USART == 1
- char data[50] = {0};
- #endif
- /* Get facility code */
- for(uint8_t i=1; i<=12; i++)
- {
- if(*(wiegandInfo->wiegandDat + i) == 1){
- wiegandInfo->facilityCode = wiegandInfo->facilityCode << 1;
- wiegandInfo->facilityCode = wiegandInfo->facilityCode + 0x01;
- }
- else{
- wiegandInfo->facilityCode = wiegandInfo->facilityCode << 1;
- }
- }
- /* Get card number */
- for(uint8_t i=13; i<=24; i++)
- {
- if(*(wiegandInfo->wiegandDat + i) == 1){
- wiegandInfo->readCardNumber = wiegandInfo->facilityCode << 1;
- wiegandInfo->readCardNumber = wiegandInfo->facilityCode + 0x01;
- }
- else{
- wiegandInfo->readCardNumber = wiegandInfo->facilityCode << 1;
- }
- }
- #if DEBUG_USART == 1
- sprintf(data, "FacilityCode %lu", wiegandInfo->facilityCode);
- DebugMsg(data);
- sprintf(data, "cardNumber %lu", wiegandInfo->facilityCode);
- DebugMsg(data);
- #endif
- }
Główna funkcja programu którą należy wywoływać w pętli while wygląda następująco:
- void wiegandMainFunction(void)
- {
- uint8_t returnValue = 0xFF;
- returnValue = wiegandCheckReceiveDataFormat(&wiegandData);
- /* Check first channel */
- switch(returnValue) {
- case wiegand37Bit: /* card 37 bits */
- wiegandDecode37BitNumber(&wiegandData);
- break;
- case wiegand26Bit: /* card 26 bits */
- wiegandDecode26BitNumber(&wiegandData);
- break;
- default:
- /* wrong card number */
- break;
- }
- /* Check second channel */
- returnValue = wiegandCheckReceiveDataFormat(&wiegandDataCh2);
- switch(returnValue) {
- case wiegandNoData:
- return; /* No data */
- break;
- case wiegandWrongFrame:
- return;/* wiegandWrongFrame */
- break;
- case wiegand37Bit: /* card 37 bits */
- wiegandDecode37BitNumber(&wiegandDataCh2);
- break;
- case wiegand26Bit: /* card 26 bits */
- wiegandDecode26BitNumber(&wiegandDataCh2);
- break;
- default:
- /* wrong card number */
- break;
- }
- ClearStructureData();
- }
Funkcja odpowiedzialna za sprawdzenie formatu i zwrócenie odpowiedniej informacji:
- static enum wiegandReceiveDataNumber wiegandCheckReceiveDataFormat(wiegandData_t * wiegandInfo)
- {
- char data[50] = {0};
- /* check number of receive bits and calculate parity */
- if(wiegandInfo->wiegandTimeout == kWiegandTimeoutMs && (wiegandInfo->wiegandStartReceive == 1))
- {
- /* Flag for block operation in HAL_TIM_PeriodElapsedCallback go zero */
- wiegandInfo->wiegandStartReceive = 0;
- if(wiegandInfo->wiegandDataPosition == 0) {
- /* No data in buffer */
- }
- else if(wiegandInfo->wiegandDataPosition == (kWiegandCard37Bits))
- {
- #if DEBUG_USART == 1
- for(uint8_t i=0; i<37; i++)
- {
- sprintf(data, "[%u]", i);
- Usart_Uart_SendString(USART1, data, ZERO);
- Usart_Uart_SendNumber(USART1, (uint32_t)wiegandInfo->wiegandDat[i]);
- Usart_Uart_SendString(USART1, " ", CR_LF);
- }
- #endif
- if(wiegandCheckDataFrame(wiegandInfo, wiegand37Bit) == 1)
- {
- wiegandInfo->wiegandDataType = wiegand37Bit;
- return wiegand37Bit;
- }
- wiegandInfo->wiegandDataType = wiegandWrongFrame;
- wiegandInfo->wiegandDataPosition = 0;
- return wiegandWrongFrame;
- }
- else if(wiegandInfo->wiegandDataPosition == kWiegandCard26Bits)
- {
- #if DEBUG_USART == 1
- for(uint8_t i=0; i<26; i++)
- {
- sprintf(data, "[%u]", i);
- Usart_Uart_SendString(USART1, data, ZERO);
- Usart_Uart_SendNumber(USART1, (uint32_t)wiegandInfo->wiegandDat[i]);
- Usart_Uart_SendString(USART1, " ", CR_LF);
- }
- #endif
- if(wiegandCheckDataFrame(wiegandInfo, wiegand26Bit) == 1)
- {
- wiegandInfo->wiegandDataPosition = wiegand26Bit;
- return 3;
- }
- wiegandInfo->wiegandDataType = wiegandWrongFrame;
- wiegandInfo->wiegandDataPosition = 0;
- return wiegandWrongFrame;
- }
- else
- {
- sprintf(data, "odebrane: %u", wiegandInfo->wiegandDataPosition);
- DebugMsg(data);
- for(uint8_t i=0; i<37; i++)
- {
- sprintf(data, "[%u]", i);
- Usart_Uart_SendString(USART1, data, ZERO);
- Usart_Uart_SendNumber(USART1, (uint32_t)wiegandInfo->wiegandDat[i]);
- Usart_Uart_SendString(USART1, " ", CR_LF);
- }
- wiegandInfo->wiegandDataPosition = 0;
- }
- }
- return 1;
- }
Jest ona wywoływana po przekroczeniu czasu oczekiwania na kolejny bit oraz gdy rozpoczęto odbieranie danych.
Pliki z biblioteką do wieganda można pobrać pod tym linkiem.