STM32 - Wiegand card reader





Здравствуйте.

Библиотека для работы с Wiegand на stm32.

Попалась мне в руки панель доступа она же Card Reader (на картинке) с названием DAHUA DHI-ASR1101A-D. Ещё бывают такие же, но без кнопок, только Card Reader (DHI-ASR1100A-D), и ещё всякие бывают, различных производителей.

Эти штуки общаются с микроконтроллером по протоколу Wiegand (там ещё есть RS485, но речь не о нём).

Распиновка у прибора такая…


Взято здесь.

Питается она от 12 вольт, а выходы данных 5-ти вольтовые. Я подключал к stm32 к пинам толлерантным к пяти вольтам.

CASE — служит для сигнализации о несанкционированном вскрытии устройства. То есть если кто-то попытается открутить панель от стены, тогда это проводок выдаст сигнал («плюс»).

LED — после того как код карточки прилетит в МК, и эта карточка окажется валидна, тогда если этот пин кратковременно прижать к «земле», то рисунок на панели подсветится зелёным.

Нам же сейчас интересны контакты D0 и D1, это и есть Wiegand.


Сам по себе этот протокол предельно прост. Обе линии D0 и D1 постоянно находятся в высоком состоянии, а данные передаются импульсами (короткими прижатиями (20-200 мкс) той или другой линии к «земле»). Импульс на линии D0 значит, что передался ноль, а импульс на D1 значит что передалась единица. Паузы между импульсами примерно 2 мс.

Выглядит это так…



После завершения передачи пакета, делается пауза от 250 до 500 мс. В прерываниях мы обрабатываем эти импульсы, а по длинной паузе отсутствия импульсов определяем что пакет получен.

Подробности тут.


В названии протокола обычно присутствуют цифры, типа — Wiegand-26, Wiegand-34, и т.д. Эти цифры означают количество бит в пакете. Например в описываемом устройстве используется Wiegand-4 и Wiegand-34, в первом случае передаётся код кнопки, а во втором 32-х битный ID карты. То есть, Wiegand-34 означает что он несёт в себе 32-х битное значение, а оставшиеся два бита это то ли стартовый и стоповый биты, то ли биты чётности, не знаю. Представленная ниже библиотека умеет работать с различными протоколами.

Вот так выглядит нажатие кнопки 1, и считывание карты…


Значение DEC совпадает с тем что написано на карте.




Перейдём к настройкам:

В Кубе нужно настроить два пина на внешнее прерывание, у меня это будут PB12 и PB13…



Даём пинам названия D0 и D1 соответственно, и настраиваем их оба на режим Falling.

Включаем прерывания…



Ну и настраиваем USART для вывода инфы.


Подключаем проводки D0 и D1 к PB12 и PB13, соединяем «земли», и запитываем устройство.



Теперь о программе:

За основу была взята ардуиновская библиотека Wiegand-Protocol-Library-for-Arduino и адаптирована под stm32. По ссылке в README написано что ещё существуют какие-то многобитовые протоколы, и дана ссылка на нужную либу, которую я не переделывал.


В проект нужно добавить файлы wiegand.c и wiegand.h. В main.c инклюдим заголовок…

/* USER CODE BEGIN Includes */
#include "wiegand.h"
/* USER CODE END Includes */



Прописываем дефайны пинов…

/* USER CODE BEGIN PD */
#define D0        D0_Pin
#define D1        D1_Pin
/* USER CODE END PD */

Если не присваивали пинам имена, то вместо D0_Pin и D1_Pin пропишите дефолтные названия (GPIO_PIN_12 и GPIO_PIN_13).


Объявляем глобальную переменную…

/* USER CODE BEGIN PV */
volatile uint8_t wig_flag_inrt = 1;
/* USER CODE END PV */

Позже скажу зачем.


Добавляем колбек для прерываний…

/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(wig_flag_inrt && GPIO_Pin == D0)
	{
		ReadD0();
	}
	else if(wig_flag_inrt && GPIO_Pin == D1)
	{
		ReadD1();
	}
}
/* USER CODE END 0 */

При срабатывании прерывания будут вызываться функции обработки сигналов.


А в бесконечном цикле проверяем есть ли новые данные, и если есть, то считываем их…

/* USER CODE BEGIN WHILE */
while (1)
{
	if(wig_available())
	{
		wig_flag_inrt = 0;
		uint32_t wcode = getCode();
		int16_t wtype = getWiegandType();
		wig_flag_inrt = 1;

		char str[64] = {0,};
		snprintf(str, 64, "HEX=0x%lX DEC=%lu, Protokol Wiegand-%d\n", wcode, wcode, wtype);
		HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000);
	}
}


Вот собственно и весь код. В оригинальной библиотеке сделано отключение прерываний в момент проверки и получения новых данных, видимо чтоб предотвратить искажение результата (хотя мне это кажется сомнительным действием так как получается что прерывания отключаются при каждой проверке, что в свою очередь может привести к пропуску сигналов). Я не стал делать отключение, а просто добавил флажок (wig_flag_inrt), который не даст войти в функции обработки сигналов в момент чтения результата (правда этот вариант тоже имеет свой изъян).

И ещё, функцию wig_available() наверно лучше вызывать не постоянно, а например раз в 20-30 мс, будет вполне достаточно. Можно сделать это через таймер и флажок, а можно и так.


Результат…



Символ 0x1B (звёздочка) можно использовать как команду сброса набранных ранее цифр (если вы их складываете в какой-то массив), а символ 0xD (решётка) можно использовать как конец приёма цифр (типа Enter). При нажатии на эту кнопку устройство издаёт дополнительный сигнал.


В библиотеке (в main.c) есть закомментированный код для складывания цифр в массив и вывода его на печать при нажатии «решётки».



Размер буфера для цифр равен 12 — если он переполнится то обнулится. Если набрать несколько цифр и нажать «звёздочку», то массив с цифрами обнулится. Если набрать несколько цифр, а потом провести картой, то массив с цифрами опять таки обнулится и на печать будет выведена ID карты.


И в довершение ещё один пример, в котором сделано так, чтоб можно было не нажимать кнопку «решётка» (Enter) после ввода цифрового кода. То есть, вы набрали нужный код, и если в течении нескольких секунд новых цифр не вводится, то это расценивается системой как конец ввода. При этом нажатие на «решётку» работает в обычном режиме, ну и сброс само собой тоже.

Это может пригодится когда пульт находится в одном месте, а ворота в другом. Тогда можно просто набрать код, и идти к воротам. Пока дойдёшь — они откроются.

В примере всё то же самое, только добавлен таймер и несколько условий. Таймер настроен на паузу 4 секунды и работает в одноимпульсном режиме. Менять длину паузы нужно с помощью переполнения и сравнения. Сейчас переполнение равно 40000, а сравнение 39999. Если нужно сделать паузу 3 секунды, тогда делаем переполнение 30000, а сравнение 29999. Это справедливо если тактовая частота 72МГц.



Это всё, всем спасибо


Телеграм-чат istarik

Телеграм-чат STM32


  • 0
  • 513
Поддержать автора




Telegram-чат istarik

Задать вопрос по статье
Telegram-канал istarik

Известит Вас о новых публикациях






Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.