Работа с Arduino и RFID MFRC522
Технология RFID (Радиочастотная идентификация) позволяет при помощи радиосигнала быстро и безопасно передавать данные между специальными “считывателями” и “метками” – карточками, брелоками, браслетами и т.д. на небольшом расстоянии.
Одно из широко известных развитий технологии – NFC, при помощи которого можно оплачивать покупки или подключать устройства бесконтактно. Нам же доступны менее сложные, но не менее полезные и интересные применения, о которых будет сказано ниже.
Применение
Комплект RFID модуль + метки может быть использован:
- Как часть самодельных охранных систем
- При создании простых электронных замков (метка является ключом)
- В системах контроля доступа (однократный, многократный пропуск)
- В качестве электронного “кошелька” внутри собственного предприятия
- В роли интерактивного предмета в квестах и т.д.
Железо
RFID работает в нескольких частотных диапазонах, в свою очередь RFID модули и метки можно поделить на низкочастотные “LF” (125 кгц) и высокочастотные “HF” (13,56 MHz), существуют так же и ультравысокочастотные “UHF”, но они нас не интересуют.
Наиболее распространенные RFID Arduino-модули основаны на микросхеме MFRC522, работающей с HF метками 13,56 МГц. Поиск модулей и библиотек производится по этому же имени.
Существует два типа модулей MFRC522, с которыми вы скорее всего столкнетесь:
Отвечая на главный вопрос – не смотря на значительную разницу в размере, ощутимой разницы в работе модулей нет, можно брать любой. В комплекте к модулю как правило уже идет несколько меток.
Библиотеки
Для работы с модулем MFRC522 понадобится библиотека https://github.com/miguelbalboa/rfid. Библиотека тяжелая, индусская и имеет немало проблем, но достойных альтернатив просто нет – несколько других “облегченных” библиотек значительно уступают в функциональности и удобстве использования.
Подключение
Модуль MFRC522 подключается по аппаратному интерфейсу SPI, выбранная библиотека предоставляет следующую таблицу подключения к Arduino:
- Контакты модуля RST и SDA (SS) указываются в скетче – можно использовать любые.
- У Leonardo подключение производится к 6-ти контактному ICSP разъему программатора.
Пример подключения модуля к Arduino Nano:

О RFID метках
Прежде всего самая сложная для понимания, но и самая важная часть – работа с RFID метками. В комплекте с модулем идут пара меток MIFARE Classic 1K, как понятно из названия – на 1 килобайт (на самом деле меньше, но об этом позже).
Чтобы изучить организацию памяти такой метки, можно воспользоваться примером из библиотеки, открыв Примеры > MFRC522 > DumpInfo. Однако для вашего удобства я подготовил вот такую карту:

Обратите внимание – память организована в виде 16-ти секторов, по 4 блока каждый. Итого – 64 блока по 16 Байт, как раз набегает 1 Килобайт. Деление по секторам носит скорее условный характер, так как адресация в памяти будет производиться по блокам.
Все сектора кроме нулевого имеют одинаковое строение – 3 блока данных + 1 блок безопасности, так называемый sector trailer. Каждый из этих блоков может быть прочитан и перезаписан (при соблюдении условий), исключение составляет нулевой блок (сектор 0).
Нулевой блок хранит в себе уникальный ID “UID”, тип метки и прочую информацию, записанную заводом-изготовителем. Нулевой сектор не может быть перезаписан, если речь идет о “классических” метках, к которым относятся комплектные с модулем. Таким образом UID позволяет отличить две с виду идентичные метки. UID как правило состоит из 4х байт, свободно считываемых из метки. Важно: китайский рынок может предложить вам “перезаписываемые” метки, UID в которых можно менять, путем перезаписи нулевого блока. Если в вашей системе используется только UID – учтите возможность очень простого копирования UID в метки-болванки (в том числе злоумышленниками).
Блоком безопасности является каждый 4й блок, каждый блок безопасности отвечает за свой сектор (предыдущие 3 блока данных) – он хранит 2 ключа доступа по 6 байт (ключи A и B), а также специальные “Access bits” (Биты доступа), грубо говоря настройки доступа. Ключи A и B могут быть использованы для аутентификации и последующего доступа к блокам данных в пределах сектора. То есть да, для того чтобы получить доступ к любому из блоков внутри сектора необходимо “разблокировать” этот сектор, при помощи одного из ключей.
Поэтому будьте уверены, если производитель позаботился о смене секретных ключей в своих RFID метках – скопировать или как-нибудь изменить содержимое штатными средствами вы уже не сможете, а ведь так хотелось? Идем дальше.
Биты доступа позволяют настроить условия доступа и возможности работы каждого блока в отдельности (каждого блока данных + блока безопасности). Наилучшим инструментом в работе с метками MIFARE Classic 1K является вот этот онлайн-калькулятор http://calc.gmss.ru/Mifare1k/. Если хотите разобраться чуть глубже – обязательно полистайте и опробуйте.
Я же хочу сэкономить ваше время, поэтому сразу уточню, что наиболее удачным решением в большинстве ситуаций будет оставить блоки данных в состоянии transport configuration, то есть по умолчанию.

Однако есть возможность настроить блоки на некоторые интересные сценарии, например защитить от записи (конфигурация 1-0-1 или 0-1-0). Или же сделать так, что прочитать блок можно при помощи как ключа A, так и ключа B, а вот для записи обязательно понадобится ключ B (конфигурация 1-0-0), в таком случае можно ограничить права некоторого оборудования и сделать систему безопаснее. И да, конфигурация 1-1-1 превращает блок в кирпич (обратимо).
В примерах ниже мы будем использовать конфигурацию блоков данных по умолчанию (0-0-0) и следующие принципы:
- Создаем ключ B, значение которого знаем только мы, длина ключа – 6 Байт.
- Ключ A будет полностью аналогичен ключу B, однако он не будет использоваться.
- Биты доступа для блоков безопасности будем использовать в конфигурации 0-1-1

Таким образом для всех операций с меткой применяется только ключ B, который невозможно считать из метки (впрочем, как и ключ A), даже если сектор предварительно разблокирован. Если хотите намертво зашить ключи A и B в блок безопасности – подойдет конфигурация 1-0-1, поменять будет уже невозможно. Ну а последняя 1-1-1 конфигурация блока безопасности заблокирует еще и настройки доступа к блокам данных!
В итоге 3 байта настроек доступа приняли следующие значения: 0x7F 0x07 0x88, байт USER может быть любой.

Начало работы
Работу с RFID модулем удобнее всего производить в конце главного цикла программы, сейчас поймете почему. Для отслеживания поднесенной метки библиотека предлагает использовать пару методов с замысловатыми названиями:
Если поднесенная метка успешно считана – программа идет дальше, в противном случае происходит возврат в начало главного цикла, а весь блок кода связанный с RFID пропускается.
В итоге наш скетч имеет следующую структуру:
Теперь давайте идти по порядку, осваивая основные методы для работы с RFID.
Чтение UID
Самое простое, что можно сделать с RFID меткой – прочитать UID, в некоторых системах уже этого функционала вполне достаточно, например – в простых электронных замках. Как уже сказано ранее, некоторые метки позволяют сменить UID, в свою очередь запретить считать UID из ваших меток не получится – учтите это при разработке.
Так или иначе пример чтения UID и вывод в порт приведен ниже:
Чтение блока
Если чтением UID ваш интерес не ограничился – давайте узнаем, как читать блок данных из метки. Прежде чем что-либо читать или писать, необходимо аутентифицировать (разблокировать) сектор, в котором находится интересующий нас блок.

В примерах ниже будем работать с блоком под номером 6 (сектор 1), за первый сектор и соответственно блоки 4, 5 и 6 отвечает блок безопасности под номером 7. То есть запомнили – блок данных 6, блок безопасности 7.
Аутентификацию сектора производит метод PCD_Authenticate() , по умолчанию все манипуляции с меткой возможны при помощи ключа A, а сам процесс аутентификации выглядит следующим образом:
Обратите внимание на …KEY_A в первом аргументе и цифру 7 вторым аргументом – это и есть номер блока безопасности. Отслеживать статус не обязательно, но крайне желательно.
После успешной аутентификации можно свободно манипулировать разблокированным сектором, в нашем случае будем читать содержимое методом MIFARE_Read() . Читать нужно в байтовый массив, размером 18 (!) байт, чтение происходит из блока 6 (первый аргумент) и выглядит так:
Важно: Не смотря на то, что блоки имеют размер 16 байт, буферный массив создается на 18 байт, а количество байт на чтение передается именно в виде указателя на переменную. В противном случае чтение закончится ошибкой, примите это как факт.
В случае успешного чтения, выведем содержимое блока 6 в монитор порта, все как обычно:
А завершать работу с меткой нужно при помощи еще двух замысловатых методов:
В итоге полный скетч для чтения блока 6 из новой метки со стандартными ключами выглядит так:
После поднесения метки в мониторе порта должны отобразиться 16 байт – содержимое прочитанного блока.
Запись блока
При записи все 16 байт записываются в блок единовременно, для чего должен быть заранее подготовлен байтовый массив на 16 Байт, например такой:
Как в случае и с чтением, сектор в котором находится нужный блок 6 нужно предварительно аутентифицировать, об этом уже сказано выше, так что переходим непосредственно к записи. Запись производится методом MIFARE_Write() , в отличии от MIFARE_Read() тут все несколько проще – указываем записываемый блок, массив и число 16 (количество байт на запись):
Итоговый скетч записи массива в блок 6 выглядит так:
После поднесения метки в мониторе порта должно отобразиться сообщение “Write OK“.
К слову ничто не мешает нам объеденить запись и чтение в одном скетче:
Смена ключей безопасности и настройка блоков
Если вы хотите не только уметь читать и писать данные в метки, но и защить хранящуюся там информацию от стороннего вмешательства – необходимо сменить ключи доступа как минимум от тех секторов, в которых вы собираетесь хранить данные, однако в идеале установить новые ключи для всех секторов, чтобы усложнить задачу потенциальным взломащикам.
Для того, чтобы изменить ключи доступа к сектору, необходимо перезаписать блок безопасности, ответственный за данный сектор. В наших примерах фигурировал блок данных под номером 6 и соответственно блок безопасности под номером 7. Задача по смене ключей безопасности сводится к следующим шагам:
- Создать байтовый массив на 16 ячеек, включающий:
- Ключ A
- Байты настроек доступа
- Ключ B
- Провести аутентификацию выбранного сектора, пока что используя стандартный ключ 0xFFFFFFFFFFFF
- Произвести запись подготовленного массива в блок безопасности, в точности так же, как в случае с обычным блоком.
После этого ключи безопасности будут изменены, а мы сможем безопасно хранить данные в одном или нескольких блоках выбранного сектора! Сейчас покажу по шагам.
- Для создания образа блока безопасности (содержимого массива) придется вернуться вверх по тексту и вспомнить, что при выбранных нами настройках сектора, байты доступа получили значения 0x7F 0x07 0x88. Осталось придумать ключи доступа, имеющие длину 6 байт. Я буду использовать ключ 0xABABABABABAB, данный ключ не является безопасным и подходит исключительно для демонстрации! Так же напоминаю, что ключи A и B будут идентичны, однако использоваться будет только ключ B.

-
1 После того, как мы определились с настройками сектора (“Access Bits“) и ключами безопасности – создаем нужный байтовый массив:
Итоговый скетч записи новых ключей и настроек доступа:
Не забываем сменить “наполнение” ключа в void setup()<> :
Так же напоминаю, что отныне для сектора 1 (блоков 4…7) мы используем только ключ B, соответственно и команда аутентификации отныне выглядит чуть иначе:
Работа с защищенным сектором
Теперь, после того как мы сменили ключи безопасности от сектора 1, в качестве примера будем выводить количество поднесений метки к считывателю в последовательный порт. Количество поднесений хранится в нулевом байте защищенного блока 6 и увеличивается при каждом поднесении:
Количество поднесений ограничено 255, потому что используется лишь 1 Байт, но для примера это и не важно.
Инкремент и декремент
Наболее продвинутые могут обратить внимание на то, что пример выше не имеет смысла, поскольку метки уже имеют функционал инкремента и декремента, позволяющего использовать защищенный блок в качестве электронного кошелька.
Для реализации данного функционала библиотека имеет методы MIFARE_Increment() и MIFARE_Decrement() , однако независимо от установленных байтов доступа данный функционал не показал работоспособность на десятке меток и нескольких модулях. Возможно всему виной поддельные чипы MFRC522, установленные в модули. В любом случае перечисленные методы возвращают ошибку при поднесении метки, а потому и пример для работы не привожу.
Особенности и костыли
- Периодическая перезагрузка и повторная инициализация. В главный цикл программы добавляется таймер на millis() с периодом 500…3000 мс, внутри которого производится принудительный сброс и инициализация модуля. Данный код располагается в начале главного цикла программы. Данный костыль является наиболее эффективным в борьбе с зависанием модуля.
- Принудительная установка усиления и перезагрузка антенны. Полезность сомнительная, однако по некоторым заявлениям библиотека не всегда корректно настраивает антенну после инициализации модуля. Решается добавлением соответствующих строк помимо инициализации модуля в функции void setup()<> :
- Повторное чтение или второй шанс. В примерах выше мы использовали следующую конструкцию для отслеживания поднесенной метки:
Фокус заключается в добавлении еще одной попытке чтения метки, в случае неудачи. Таким образом наша конструкция принимает следующий вид:
Наиболее эффективным и важным является первый костыль, располагайте его перед работой с модулем, желательно в начале цикла void loop()<> , но ни в коем случае не в прерывании таймера. Однако несмотря на то, что приведенные выше хитрости действительно работают и многократно повышают стабильность работы RFID модуля – в случае с электронными замками и прочими системами контроля доступа рекомендуется иметь резервные способы входа, помимо RFID.
Arduino.ru
У некоторых продавцов на Aliexpresse есть в продаже с перезаписываемым 0 блок и 0 сектором. Ищите там.
брелки или rс522? почему то в интернете есть огромное количество как считать данные, но ни одного(я искал) где идёт запись на «болванку» вот это кстати можно считать болванкой? https://ru.aliexpress.com/item/5PCS-Yellow-RFID-Sensor-Proximity-Card-IC-Key-Tags-Keyfobs-Keychain-13-56MHz/32745066583.html?spm=2114.13010608.0.0.Ha8FpB
Я заказывал у этого продавца на пробу, все работает 0 блок и 0 сектор скопировал с нужной карты и зашил в эти. Теперь у меня есть клон, вдруг дома забыл на работе запасная лежит. https://ru.aliexpress.com/item/Free-Shipping-1pc-13-56MHz-Rfid-PVC-Thin-Uid-Changeable-block-0-writable-Card-1K/1711603036.html?detailNewVersion=&categoryId=303006 Сейас стоит 270 руб 3 штучки по 90 руб за штучку.
С помощью Arduino и модуля RC522 изменил 0 блок 0 сектор.
- Войдите на сайт для отправки комментариев
а есть такие круглые брелки? и какой код должен быть чтобы rc522 генерировала сигнал записи а не только читала инфу с карты.
- Войдите на сайт для отправки комментариев

эти наклейки из-за малой антенны через пластик уже могут не срабатывать, им нужен прямой контакт. Лучше большую (увеличит дальность) наклейку на обратную сторону крышки аккумулятора. А если телефон в чехле, то сойдет и метрошный одноразовый билетик.
Если в телефоне есть NFC, то никакх брелков и наклеек уже не надо. Я так на работе и в автобусах прохожу %)
- Войдите на сайт для отправки комментариев
ладно есть наклейки наверно побольше
метрошный билетик можно переписать под свой ключ?
допустим такая история, дали ключ от подъезда. этот ключ можно вписать в билет метро? если нет то в какую наклейку можно? nfc в телефоне нет. и ещё есть код чтобы писать в наклейки. всё что я видел это для чтения данных с карты
- Войдите на сайт для отправки комментариев

Некоторые сектора можно, некоторые вшиты намертво.
Какие сектора использует домофон — ведомо только его разработчикам.
- Войдите на сайт для отправки комментариев
ну ключ с брелка, которым двери открываю, я вижу. этот ключ можно клонировать. какая разница что использует домофон, если он видит ключ из базы он должен открыть, я в ларке могу ключ склонировать и там не спрашивают про секторы. просто берут один брелок отдают два
- Войдите на сайт для отправки комментариев

они используют брелки с перезаписываемыми секторами. Ради эксперимента дайти им метрошный билетик, пусть попробуют на него склонировать — вдруг получится? За это денег не берут 🙂
- Войдите на сайт для отправки комментариев
мы отвлеклись. при чём тут ларёк. есть ардуино, есть брелок с ключем, есть ещё карточка, абсалютно не обязательно метро, чтото подходящее. как один ключ перенести на на другой?
- Войдите на сайт для отправки комментариев

- Войдите на сайт для отправки комментариев
супер то что искал. спасибо
- Войдите на сайт для отправки комментариев

Киньте пожалуйста библиотеку которая подойдёт к скетчу
void loop()
<
if (rfid.isCard())
<
if (rfid.readCardSerial())
<
/* Reading card */
Serial.println(» «);
Serial.println(«Card found»);
Serial.println(«Cardnumber:»);
for (i = 0; i < 5; i++)
<
Serial.print(rfid.serNum[i]);
Serial.print(» «);
reading_card[i] = rfid.serNum[i];
>
Serial.println();
//verification
for (i = 0; i < 5; i++)
<
if (reading_card[i]!=master[i])
<
break;
>
>
if (i == 5)
<
allow();
- Войдите на сайт для отправки комментариев

Всем привет, подскажите, кому-нибудь в проектах пригождалась нога Reset ? хочу ее к VCC подтянуть из соображений экономии ног.
- Войдите на сайт для отправки комментариев

а скетч заливать как будешь?
Какую экономию даст подтяжка Reset к Vcc?
- Войдите на сайт для отправки комментариев

а скетч заливать как будешь?
- Войдите на сайт для отправки комментариев

ыыы, точно! Не туда мысля пошла.
Reset нужен, ибо иногда ридер залипает, а команда halt() дергает именно Reset.
- Войдите на сайт для отправки комментариев

В итоге выяснилось, что всё даже хуже: на команде (из наиболее распространенной библиотеки Мигеля Бальбо) mfrc522.PICC_IsNewCardPresent() ардуино
1. без резета — зависает раз в полчаса.
2. с хардварным и софтварным резетом раз в 2 секунды — зависает раз в 7 часов
3. с вот таким полным отключаением питания раз в 4 секунды — не зависает сутки (а мне больше и не надо)
- Войдите на сайт для отправки комментариев
Подскажите в чем проблема — с библиотекой Мигеля Бальбо все работает, с этой https://github.com/miguelbalboa/rfid не компилируется ни один пример. Ошибка : Arduino: 1.6.4 (Windows 8.1), Плата»Arduino Uno»
- Войдите на сайт для отправки комментариев

странно что эта ошибка вообще вылезла, поиск по UINT8_MAX в папке c:\Program Files\Arduino выдает что оно определяется в stdint.h вот так что, можно не заморачиваясь просто подключить его
- Войдите на сайт для отправки комментариев
странно что эта ошибка вообще вылезла, поиск по UINT8_MAX в папке c:\Program Files\Arduino выдает что оно определяется в stdint.h вот так что, можно не заморачиваясь просто подключить его
Подключал stdint.h — то же самое 🙁
- Войдите на сайт для отправки комментариев
Доброго времени суток, прошу подсказать кто знает как хранить в памяти номера меток т.к. хочу сделать замок.
Собрал схемку, можно записать все метки но после того как отключить питание и снова подать стираються все из памяти
Может есть готовые решения как прикрутить запись на флешку или хранение в eeprom RFID ключей?
Заранее благодарен за помощь
- Войдите на сайт для отправки комментариев

- Войдите на сайт для отправки комментариев
Спасибо за наводку
Я понимаю что должно в EEPROM записывать но почему-то при выключении Дуня забывает все ключи, в написании кода не силен но в коде, который я заливаю функцию записи в память я вижу . Подскажите пож. в чем тогда может быть проблема. Может в коде ошибка? Спасибо
- Войдите на сайт для отправки комментариев
Сорри разобрался, был не внимателен с кнопкой сброса
Подскажите пожалуйста какиеми ключами более надежно пользоваться 125 кГц или 13,56 мГц
Идея сделать замок на калитку во двор на метках , нужно установить антивандальную антену и что-то от наводок
Может у кого есть наработки на эту тему что посоветуете ? На что обратить внимание ?
- Войдите на сайт для отправки комментариев
Ещё вопрос как понять сколько можно ключей записать в ПЗУ ?
- Войдите на сайт для отправки комментариев
Прошу помощи сообщества.
Пробую подключить RFID RC522 совместно с NANO V3.0. Подключаю библиотеку, соединяю все как в скетче. Пробовал RFID-модуль запитывать от NANO и от отдельного источника. Ни в какую не считывается. В чем проблема?
- Войдите на сайт для отправки комментариев
Уже второй модуль RFID купил. Так и не хочет работать. Где подводный камень?
- Войдите на сайт для отправки комментариев

мошт, ключи на 125 кГц?
- Войдите на сайт для отправки комментариев
Ключи использовал из комплекта к модулям.
- Войдите на сайт для отправки комментариев
а распаяли как? схему откуда брали? Штуки четыре к мне приходила RFIDfа, вместе на Nano прекрасно все работают. Пробовали стандартные примеры из библиотеки?
- Войдите на сайт для отправки комментариев

нужно локализовать проблему: в стандартном примере функция ShowReaderDetails() — выводит номер версии ридера. если он выдает некорректную информацию, значит ридер подключен к ардуине неправильно и нужно решать проблему с подключением, а потом уже за ключи браться.
- Войдите на сайт для отправки комментариев
Подскажите новичку. Правильно ли я понял. У меня у домофонного ключа читается все, кроме нулевого сектора. Картина такая:
- Войдите на сайт для отправки комментариев

- Войдите на сайт для отправки комментариев
Хм. Я спрашивл правильно ли я понял, а вы — какой ключ.
Информацию о существовании неких ключей я нашел в нет-е.
Мол хранятся в нулевом секторе и позволяют при таких ограничениях читать/записывать нулевой сектор.
- Войдите на сайт для отправки комментариев

«У меня у домофонного ключа читается все, кроме нулевого сектора» — вот я и интересуюсь какой именно у вас домофонный ключ.
- Войдите на сайт для отправки комментариев
Я вас неправильно понял. Какой именно ключ — не знаю.
Но раз почти все читается, логично предположить, что такой же как те, что шли в комплекте с RC522, только закрыт/зашифрован нулевой сектор.
- Войдите на сайт для отправки комментариев
но не копмилируется скетч RFID-Cloner
Подправите не в ущерб функционалу?
- Войдите на сайт для отправки комментариев

Вечер в хату, уважаемые!
Есть проблема: сделал замок на rc522, раздал домашним наклейки ntag213, на которых одинаковый номер uid (шел с завода), по которому, собственно, и велась идентификация. Дочь потеряла (сперли?) брелок с наклейкой пару дней назад, а сегодня буквально за руку поймал малолетнего «медвежатника» с этим брелоком, который решил, что дома никого и открыл дверь на моих глазах.
Посему вопрос: можно ли и каким образом сменить uid на других наклейках на различные, которые потом пропишу в код замка? Наклейки вроде перезаписываемые. Курил гугл, но четкой инфы именно про смену uid в 10-значном формате не нашел.
Подскажите, плз, кто что знаеет.
- Войдите на сайт для отправки комментариев
Гопнег — вообще в любом пособии по РФИД обычно крупными буквами написано, что категорически нельзя строить систему безопасности на значениях UID, так как метки можно копировать и подменять. Так что делать замок на UID — это почти тоже самое что просто не запирать двери или, к примеру. запирать их на сортирный шпингалет. В этот раз дочь потеряла метку, а в следующий более продвинутый медвежатник просто скопирует ее метку потихоньку, пока она отвернулась — вы даже и не узнаете.
Для использования РФИД в качестве электронного замка необходимо привязываться к защищенным полям метки, которые читаются только по паролю. Тогда вашу метку нельзя будет так легко скопировать.
Ну и возвращаясь к первому вопросу — в случае использования защищенных полей РФИД вы сможете записать на каждую метку свой код и в случае утери метки просто заблокировать этот код в программе замка.
Как очистить блоки nfc rfid rc522
_________________
Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство — я до 14 лет смотрел черно-белый телевизор.
Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет
Неделю сражаюсь с mfrc522 второй ревизии.
rc522 переведен в режим UART. Пока что командами обмениваюсь вручную через Terminal 1.9. Могу писать в FIFO, читать, присваивать значения регистрам.
Застрял на WUPA для Mifare 1k (52h) — то-ли я не так понял даташит (надо сказать даташит тот еще. ). Приведу свой инит и команды коммуникации, может будут мысли по этому поводу — буду признателен.
Инит: 11 3D 2D 30 2C 00 2A 8D 2B 3E 14 03 15 40
Попытка отправить 52 карте Mifare 1k: 09 52 0D 07 01 0C 0D 80
После команды буфер просто пустеет, то-есть ответа (предполагаемого мной) не происходит.
Видимо я что то не так понял из даташита?
Добавлю заранее. REQA тоже пробовал.
09 26 0D 07 01 0C 0D 80
Данные из буфера уходят, и Status2Reg:ModemState = 101 wait for data.
Однако буфер все равно пуст. Или я упускаю какой то регистр, который должен активировать правильный прием данных, или я абсолютно не понимаю что делаю
Импульсные источники питания LM450/600-20Bxx производства компании MORNSUN представляют собой надежные ИП, подходящие для применения в суровых условиях эксплуатации. Особенностью источников питания этой серии является мощность, увеличенная до 450/600 Вт, что существенно расширяет спектр возможных применений. В ИП реализованы необходимые защитные функции, такие как защита от короткого замыкания выхода, перегрузки и превышения выходного напряжения. Изоляция «вход-выход» выдерживает напряжение до 4000 В и резкие перепады температур.
Последний раз редактировалось maddogmaycry Вс сен 10, 2017 17:59:21, всего редактировалось 1 раз.
Обзор представленных в Компэл новых серий семейств DDRH и RSDH на DIN-рейку и на шасси для высоковольтных сетей постоянного тока с диапазоном входных напряжений от 150 до 1500 В. Могут применяться для станций зарядки электромобилей и электробусов, ж/д транспорта, систем хранения энергии, альтернативной энергетики, телекоммуникационных центров и центров обработки данных.
В общем какие косяки я словил на данный момент.
Arduino Mega отказывается нормальные 3.3 вольта выдавать, и дело тут даже не в ASM1117 так как на моей плате с этим регулятором все работает хорошо — будьте внимательны — сам камень может работать, но антенна при этом ничего не принимать (проверено в режиме i2c rc522).
Таки команды были неправильными. Недостаточно установить бит "StartSend" по адресу BitFramingReg, требуется еще и сохранить 7битную длинну, и именно в этой части кода 0D 80 я и пролетел. Нужно отправлять сохраняя 7 битное значение, а значит команда отправки будет 0D 87.
Так же я допустил ошибку по адресу TxControlReg. 14 80 — Должно быть 14 83, ведь бит nvTx2RF должен быть On, почему пока не понятно, но я разберусь позже и наверняка выложу отчет. В общем REQA можно получить следующей командой (для терминала 1.9 — $ = HEX)
Инит $01$0F$11$3D$2D$30$2C$00$2A$8D$2B$3E$14$03$26$70$15$40
Отправка / получение $14$83$09$52$01$0C$0D$87
Classic — 04 00
Desfire EV1 4k — 44 03
Ultralight c — 04 00
Ultralight c без переделки rc522 не заработает, так как требуются более мощные индукторы на > 100ma!
1 — Видео без модификации https://www.youtube.com/watch?v=jaqr-JE8MwA
2 — Модифицированный — https://www.youtube.com/watch?v=42DRSZrFyKc
Озвучивать не стал (особо нечего). О том как произвести модификацию см. коммент ко второму видео.
Продолжаю копать, следующий шаг — анти-коллизия. О успехах отчитаюсь.
Всем кто желает помочь, всегда рад. На выходе планирую библиотеку для недооцененного на мой взгляд mfrc522,- i2c и Uart для работы с шифрованными картами Desfire ev и ultralight c.
На данный момент есть вопрос: [вопрос снят. Ответ: есть разные варианты на разные случаи и разной степенью надежности]
После каждого приема/передачи требуется-ли делать софт/хард ресет зверька? То-есть выходит этакая итерация — инициализация, запрос, чтение, ресет. И по новой — инит.
Еще если вы вовлечены в мир NFC и RFID советую посетить канал https://www.youtube.com/watch?v=tuMjCsIyyuw&t=0s
Человек выкладывает ценнейший материал.
Небольшая программка на PHP помогла увеличить скорость обучения. На данный момент разбираюсь с Classic 1k:
-> 010F [Reset]
-> B7 [Version]
<- 92
-> 010F113D2D302C002A8D2B3E148326701540 [Init]
-> 0952010C0D87 [Send REQA]
-> 8989 [Read REQA]
<- 0400
-> 09930920010C0D80 [Anticol]
-> 8989898989 [Read UID]
<- 90F60BC5A8
-> 09930970099009F6090B09C509A801030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- CE6F
-> 09930970099009F6090B09C509A809CE096F010C0D80 [Select]
-> 898989 [Read SAK]
<- 08B6DD
UDP: Угу, действительно SAK — Coding of Select Acknowledge. В моем случае [08 (00001000) указывает на то что UID передан полностью] [B6DD По всей видимости CRC]
UPD: DD — CRC, B6 фиг знает что, надо будет выяснить.
Desfire ev1. Первая анти-коллизия у него возвращает только первые 4 byte UID. Смотрим табличку.
https://www.nxp.com/docs/en/application . df#page=11
XX1XX0XX — UID not Completed. Все сходится. SAK — 24D836 (24 [00100100]) Позже проверю что он вдаст если его антиколизить правильно.
Кстати, параллельно выяснил, что есть два типа карт classic 1k. До 10 года (4 byte UID) и после (7 byte UID).
В общем дальше авторизация classic 1k.
Последний раз редактировалось maddogmaycry Сб сен 23, 2017 22:47:58, всего редактировалось 8 раз(а).
В общем продолжаем. Пробуем авторизоваться.
Честно сперто из примера https://image.slidesharecdn.com/mifare- . 1278953071 что значит 07671EC1 я пока не разбирался, что то это значит и когда я преодолею свою лень, обязательно узнаем )))
-> 010F [Reset]
-> B7 [Version]
<- 92
-> 010F113D2D302C002A8D2B3E148326701540 [Init]
-> 0952010C0D87 [Send REQA]
-> 8989 [Read REQA]
<- 0400
-> 09930920010C0D80 [Anticol]
-> 8989898989 [Read UID]
<- 90F60BC5A8
-> 09930970099009F6090B09C509A801030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- CE6F
-> 09930970099009F6090B09C509A809CE096F010C0D80 [Select]
-> 898989 [Read SAK]
<- 08B6DD
-> 096009300976094A010C0D80 [Auth block 30]
-> 89898989 [Answer]
<- 07671EC1
Вообще странно пока, откуда в примере взялся block 30 не понимаю, тогда как http://cache.nxp.com/docs/en/data-sheet . pdf#page=8
сообщает явно = блока 4: 0-3. Копаем
UPD
In Mifare Classic 1K tags There are 16 Sectors and each Sectors contains 4 Blocks and each block contains 16 bytes.
Теперь все ясно. Идем дальше.
И так, авторизация и что я на данный момент о ней знаю.
Команда 60 говорит карте — авторизуюсь в таком то блоке.
Карта вызывает нас на челлендж высылая NT.
Теперь у нас есть key, nt, и uid.
Теперь из данных обьектов требуется создать NR, KS1, AR, KS2.
Формулы ни в одном из даташитов найти не удалось (лишь только поверхностные данные).
Что есть еще:
В принципе зачем то описывается процесс генерации NT со стороны карты. Продолжение следует.
nT — Tag nonce.
nR — Reader nonce.
KS — key stream или sector key.
Читаем, есть формулы расчета — http://www.ict-forward.eu/media/worksho . mifare.pdf
Собственно формула аутентификации великолепно демонстрирует слайд ниже
Но все что ниже NT — темный лес.
Создал тему https://www.mifare.net/support/forum/to . procedure/ жду помощи зала.
Параллельно почитываю http://bcc.portal.gov.bd/sites/default/ . 9798-2.pdf
https://www.researchgate.net/publicatio . re_Systems
UDP
Вот я тупень то а. Crypto1 закрытый протокол, и в те времена, когда он все еще был актуален а принципах его работы знать никто не должен был. Именно по этой причине у mfrc522 есть специальная команда для авторизации карты MFAUTH(UID+BLOCK+KEY).
Завтра пробуем.
Я если честно со структурой карты Classic 1k в настоящее время на вы так сказать но уже знаю, что в блоке 00 сектора 0 находится так называемая Manufacture data, и первые 4 байта этого блока содержит UID.
http://cache.nxp.com/docs/en/data-sheet . pdf#page=8
Вот именно этот сектор я и прочитал, о чем свидетельствует последняя строка лога.
Как данные читать после авторизации.
В логе есть регистр — Status2Reg. Его адрес 08 на зпись, и соответственно 88 на чтение. Регистр возвращает нам 08 hex — 00001000 bit’s.
Если открыть доку https://www.nxp.com/docs/en/data-sheet/ . df#page=43 то можно понять, что третий бит "MFCrypto1On" установлен в 1, а это значит, что "ndicates that the MIFARE Crypto1 unit is switched on and therefore all data communication with the card is encrypted" — вся дата между картой и mfrc522 зашифрована, то есть авторизация по идеи сработала (вроде сработала)
Сейчас сделаю пометки прямо в логе, что бы было понятно куда и что.
То-есть после того, как мы авторизовались, и хотим почитать какие-то блоки с карты, то нам надо отправить команду 30 и номер блока (к примеру 00).
Опять же, для MFRC522 команда записи чего либо выглядит так — 09 00 — Запишет в FIFO 00.
Соответсвенно если мы хотим отправить на карту команду 30 00, то обвязка будет следующей 09300900 — в буфере окажется команда 3000. Все элементарно (c)
Но перед тем, как команда уйдет на карту, нам нужно добавить в конец этой команды ее CRC сумму.
В логе можно увидеть, что сначала я отправляю в буффер 30 00. Потом вычисляю CRC.
09 30 09 00 01 03 01 00 — лог
09 30 09 00 — Положить в буфер 30 00 (30 READ, 00 — block)
01 03 — запустить CRC сопроцессор.
01 00 — IDLE — остановить все команды (ну это как бы что бы остановить CRC сопроцессор)
Затем читаю CRC.
-> A2 A1 [GET CRC] — В регистрах A1 и A2 (их последовательность требуется перевернуть) хранится результат вычисления CRC для строки из буффера. Надо помнить, что буффер пустеет после окончания подсчета.
<- 02 A8 — А вот и результат для команды 30 00
Теперь опять помещаю в буфер команду 30 00 но уже добавляю к ней CRC
09 30 09 00 09 02 09 A8 01 0C 0D 80
09 30 09 00 — положить в буфер 30 00
09 02 09 A8 — положить в буфер CRC
01 0C 0D 80 — включаю передачу данных и отправляю все это на карту.
89 — операция чтения буфера.
В логе — 89898989898989 — произвести чтение 7 байт.
Буфер возвращает нам — 90F60BC5A88804
000000000000 — KEYB (угу, по всей видимости все зеркалируется)
FF078069 — Access bits
FFFFFFFFFFFF — KEYA
Это из того что наверняка. Вроде как наверняка
Теперь о порядке авторизации в секторе, как я его понял на данный момент (может не совпадать с действительностью).
Смотрите,- сектор, это вообще условная как я понял единица, ну что бы упростить визуальную составляющую (хотя не факт конечно).
То-есть сектор надо высчитать блоками. Допустим 4 блок = 1 сектор, 0 блок. 5 блок = 1 сектор, 1 блок.
Далее.
Если авторизоваться скажем во втором блоке, то для чтения/записи доступен и блок 0, 1, 3.
Если авторизоваться в блоке номер 4, а блок номер 4 приналежит уже к сектору 1, то картина будет аналогичной.
То-есть по большому счету нет необходимости для доступа к блоку номер 5, авторизоваться в блоке 7. Карта сама определяет сектор авторизации.
Но это пока только моё ИМХО. Вот пример, который демонстрирует авторизацию в блоке номер 01 (где не может быть ключа, но чтение блока номер 03 при этом работает)
096009 01 09FF09FF09FF09FF09FF09FF099009F6090B09C5 [Авторизация в блоке 01]
010E [Authenticate]
88 [Status2Reg]
08
0930090301030100 [Calculate CRC]
A2A1 [GET CRC]
999A
093009 03 0999099A010C0D80 [читаем блок 03]
89898989898989898989898989898989 [Read]
000000000000FF078069FFFFFFFFFFFF
Я использую простой вариант, авторизацию провожу в том же блоке, в котором предполагаю операцию чтения/записи. Хотя конечно возможны и иные ситуации.
Иду дальше. Логично предположить, что авторизовавшись в секторе, мы могли бы получить доступ ко всем 4 блокам. Но вроде как это не так.
После того как один из блоков прочитан, мы получаем следующую картину.
Первый блок прочитан, два других — нет.
На данный момент есть подозрение, что требуется increment для таких вот задач. Но не факт!
Работает. Перед каждой итерацией производим полную очистку буффера, видимо там что то есть. Странно конечно, после операции чтения 89 каждый прочитанный байт должен удаляться.
Все верно, видимо читаю не все что есть в буффере, видимо после операции чтения блока там не только 16 байт данных, но еще какая то системная инфа.
Да, все верно.
90F60BC5A88804008500B42EF0BB6AA8671E
В буффере 18 байт, я читаю только 16. Соответсвенно, когда сопроцессор забирает из буфера данные, то все это дело перемешивается с остатками и CRC высчитывается неверно. Или читаем все 18 байт, или чистим буфер каждый раз когда требуется посчитать CRC. Или можно считать CRC отдельно от mfrc522.
UPD
Все же надо выяснить что за два байта после каждого блока в FIFO. Делаю предположение что это CRC
Сейчас проверим.
Блок 1 — 000000000000000000000000000000003749
Кладу 00h x 32 в FIFO, запускаю просчет CRC.
Читаю CRC регистры и получаю 3749.
Все верно, это CRC блока.
В общем прочитал блоки 0 — 3.
90F60BC5A88804008500B42EF0BB6AA8671E
000000000000000000000000000000003749
000000000000000000000000000000003749
000000000000FF078069FFFFFFFFFFFFD455
Поздновато, но попробуем что нить записать.
https://www.nxp.com/docs/en/data-sheet/ . df#page=15
Write = A0h
Но не все так просто. https://www.nxp.com/docs/en/data-sheet/ . df#page=24
Запись делится на две части. Я так понимаю сначала мы карте отправляем намерение записать что-то в определенный блок, и только затем отправляем это что-то второй частью. Каждая из двух частей сопровождается CRC суммой.
Продолжение следует.
Запись.
-> 09A0090109D609A0010C0D80 [Prepare write]
-> 89 [ACK]
<- 0A — успешно!
-> 0A80 [Clear FIFO]
-> 09FF09FF090009000900090009000900090009000900090009000900090009000103 [Calculate CRC для FF FF 00 x 14]
-> 0100 [IDLE] — просто делаю отмену команд отдельной строкой, дабы дать чуть больше времени на калькуляцию CRC
-> A2A1 [GET CRC]
<- 6119
-> 09FF09FF0900090009000900090009000900090009000900090009000900090009610919010C0D80 [Отправляем FF FF 00 x 14 на карту]
-> 89 [ACK]
<- FF (очень странный ACK — должен быть 0A) Надо разобраться.
-> 0A80 [Clear FIFO]
-> 0930090101030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- 8BB9
-> 09300901098B09B9010C0D80 [Команда прочитать 01 блок]
-> 898989898989898989898989898989898989 [Читаем FIFO]
<- FFFF 00000000000000000000000000006119
UPD
C ACK разобрался. Там как бы надо читать все 16 байт, в моем случае я записывал два байта FF FF.
Ответ — FFFF0AFFFF.. в общем все хорошо.
Завтра попробуем сменить ключ.
Так, напоминаю, что там у нас в третьем блоке
000000000000FF078069FFFFFFFFFFFFD455
000000000000 — KEYB
FF078069 — Access bytes
FFFFFFFFFFFF KEYA
D455 — CRC
В общем пока есть несколько предположений.
1 — 000000000 KEYB, но мы его не видим из-за Access bytes (Это мое ИМХО на данный момент)
2 — Если 000000 это KEYA, то мы его не видим по той же причине, зато видим KEYB и он FFFFF
Пробую поменять все 16 байт в блоке номер 7 (1 сектор 3 блок).
Для начала просто подсунем ему 000000000000FF078069FFFFFFFFFFFF (как есть в общем).
Так, в общем по всей видимости 00000 это скрытый KEYA
-> 09600907090009000900090009000900099009F6090B09C5 [Формируем строку для авторизации]
-> 010E [Запускаем Cryopo1]
-> 09A0090701030100 [Calculate CRC]
-> A2A1 [CRC]
<- E0C5
-> 09A0090709E009C5010C0D80 [Готовим запись]
-> 89898989898989898989898989898989 [ACK]
<- 0A000000000000000000000000000000
-> 0100 [IDLE]
<- 01
-> 0A80 [Clear FIFO]
-> 09FF0900090009000900090009FF09070980096909FF09FF09FF09FF09FF09F10103 [Calcula
te CRC]
-> 0100 [IDLE]
-> A2A1 [GET CRC]
<- B306
-> 09 FF 0900090009000900090009 FF 09 07 09 80 09 69 09FF09FF09FF09FF09FF09 F1 09B30906010C0
D80 [Write]
-> 89898989898989898989898989898989 [ACK]
<- 00000A00000000000000000000000000
-> 0A80 [Clear FIFO]
-> 0930090701030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- BDDC
-> 0930090709BD09DC010C0D80 [Read 00]
-> 898989898989898989898989898989898989 [Read]
<- 00 0000000000FF078069FFFFFFFFFF F1 AABC
Теперь наш ключ FF0000000000. Со старым ключем чтение заданного блока не работает (0000000000000000000000000000).
Авторизовавшись новым KEY A при чтении 7 блока я получил 0000000000FF078069FFFFFFFFF1.
Видимо Access byte’s настроены на скрытие KEYA.
000000000000FF078069FFFFFFFFFF F1 AABC — пример демонстрирует, что KEYB не скрыт.
Ох, Access bytes.
Читаем https://www.nxp.com/docs/en/data-sheet/ . df#page=12
6 7 8 9 байты содержат access bits.
Моя строка 000000000000FF 07 80 69FFFFFFFFFFF1AABC
FF — 1111 1111 — 6 байт
07 — 0000 0111 — 7 байт
80 — 1000 0000 — 8 байт
69 — 0110 1001 — 9 байт — вроде как не учавствует в формировании.
Вообще в даташите сказано что 9-ый байт Access Byte’s = user data. Правила доступа из него не складываются.
Если вы разобрались в этой таблице, то вы молодец.
Небольшая подсказка.
У нас три байта. 1 байт = 8 бит.
В наших трех байтах всего 24 бита.
Первые 12 БИТ это биты доступа (три блока по 4 бита) .
Другие 12 БИТ это инверсия битов доступа.
Зачем? Честно скажу — не изучал.
Читать БИТы требуется справа налево. Например FF = 1111 1111 <-. Вот мы видим 3 2 1 0 3 2 1 0 биты. 0 бит управляет 0 блоком. 1 бит — первым, ну и в таком ключе. Система доступа состоит из трех блоков C1 C2 C3 (три блока по 4 бита) .
12 / 3 = 4 бита.
Возможно инверсия сверху, а вот биты доступа снизу! Надо проверить.
FF — 1111[c2] 1111[c1]
07 — 0000[c1] 0111[c3]
80 — 1000[c3] 0000[c2]
Первые 12 бит (три блока по 4 бита)
0111[c3] 1111[c2] 1111[c1]
1000[c3] 0000[c2] 0000[c1]
Как видите, другие 12 бит это инверсия первых 12-ти или наоборот. Надо бы доку еще раз пошерстить.
Так. Сначала в соответствии с этой таблицей https://www.nxp.com/docs/en/data-sheet/ . df#page=13
проверим какие выставлены правила доступа для моей карты.
FF | 0
7 | 80 | (69) = 1 111 1 111 | 0 000
0 111 | 1 000 0 000 | ( 0110 1001 ) — Справа налево! Три блока по 4 бита.
Соответственно, в настоящий момент для блока 3,- сетка доступа выглядит следующим образом.
Если первые 12 бит = access bits:
С1 = 1 , С2 = 1 , С3 = 0
Если нет, то:
C1 = 0 , С2 = 0 , С3 = 1
Sector trailer это каждый третий блок сектора, в котором располагается KEYA ACCESS BITS KEYB.
Пока что больше похоже что зелёненький вариант является TRUE
Кстати, судя по таблице доступа — KEYA вообще никогда прочитан быть не может.
По всей видимости эпопея с Classic заканчивается. И начинается совсем другая история
Пару пояснений.
В настоящий момент я не подписывал NDA с NXP, и если мне не будет хватать информации для обучения, то я его подпишу.
Это будет означать окончание моего публичного образовательного процесса о DESFIRE на этом форуме.
https://www.nxp.com/docs/en/data-sheet/ . 81_SDS.pdf — короткий даташит, ознакомиться с характеристиками, не более! Для обучения не пригоден. Но кое что из него почерпнуть можно. Вот на пример.
Первое что необходимо будет выделить "7 bytes unique identifier (cascade level 2 according to ISO/IEC 14443-3 and option for
random ID)"
Значит потребуется использовать Cascade Level 2 в Anticollision cycles.
https://www.nxp.com/docs/en/application . pdf#page=3
Допустим у нас 7 byte UID. — В случае с Desfire это уже TRUE UID!
Пример:
01 02 03 04 05 06 07
Таблица говорит нам, что первый каскадный уровень отдаст нам:
CT UID0 UID1 UID2 BCC
Второй уровень:
UID3 UID4 UID5 UID6 BCC
Теперь нам известно как получить UID.
Пробуем.
Кстати, не на всех rc522 можно гонять Desfire. Не хватает у них мощи. Требуется индукторы менять. Ссылки на видео я сбрасывал выше. Любые индукторы на 100мА подойдут. Найдете 0805 — класс, найдете 1206 — 1210 — тоже норм.
У меня плата самодельная, с мощными индукторами в корпусе 1812. Desfire EV1 и UltralightC работают хорошо.
ИМХО на SPI если вы работаете через микроконтроллер, то может и без переделки Desfire работать будет хорошо. Но вот на UART у меня вроде как не хочет. ВРОДЕ! Не очень достоверная информация, не изучал особо. ИМХО в общем.
Так, первая Анти-коллизия возврашает нам
-> 0952010C0D87 [Send REQA]
-> 8989 [Read REQA]
<- 4403
-> 09930920010C0D80 [Anticol]
-> 8989898989 [Read UID]
<- 88 04 5E 6F BD
-> 0993097009880904095E096F09BD01030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- 0E60
-> 0993097009880904095E096F09BD090E0960010C0D80 [Select]
-> 898989 [Read SAK]
<- 24D836 — SAK
4403 — REQA. Приходит в зеркале. Переворачиваем 0344.
Читаем тут — https://www.nxp.com/docs/en/application . pdf#page=9
Тип карты определен как desfire ev1/desfire.
Так, и еще. Тоже не менее важно для понимания.
0344h = 00000011 01000100
0000 — RFU
01 — UID Size (00 = 4 byte, 01 — 7 byte, 11 я так понимаю 10 byte. По поводу 10 byte — ИМХО)
CT- 88
UID0 — 04
UID1 — 5E
UID2 — 6F
BC — BD
24D836 — SAK (Select AcKnowledge). Очень важная штука для понимания того с чем мы имеем дело.
Как им пользоваться описано тут — https://www.nxp.com/docs/en/application . pdf#page=7
На сколько я помню 88 означает что UID передан не полностью. ИМХО! Сейчас найду доку.
Угу, так и есть "The CT (0x88) indicates that the UID is not yet complete, and another Cascade Level
has to follow." — https://www.nxp.com/docs/en/application . pdf#page=3 внизу там листните.
Ок, как получить вторую часть UID.
https://www.nxp.com/docs/en/application . pdf#page=4
Вообще надо понимать, что публичные даташиты NXP — это чисто ознакомительная и я бы сказал неточная теоретическая часть, которая для работы подходит не очень хорошо. К пример, описывается команда CL, но не сказано сколько байт мы запрашиваем. Крайне рекомендую изучить ГОСТ 14443 прежде чем вообще приступать к работе с не то что бы Desfire, а вообще к какой либо другой карте Mifare.
http://docs.cntd.ru/document/1200118652
Если вы уже изучили ГОСТ, то в настоящий момент нас интересует "6.5.3 Антиколлизия и Выбор" пользуйтесь поиском вашего браузера.
Таблица 7 — Кодирование SEL
93 — каскадный уровень 1.
95 — выбор каскадного уровня 2.
Ну и так далее.
Так, нашел иллюстрацию в примерах на ГОСТ 14443
Делаем CL2
-> 010F113D2D302C002A8D2B3E148326701540 [Init]
-> 0952010C0D87 [Send REQA]
-> 8989 [Read REQA]
<- 4403
-> 09 93 09 20 01 0C 0D 80 [Anticol]
-> 8989898989 [Read UID]
<- 88 04 5E 6F BD
-> 09 93 09 70 09 88 09 04 09 5E 09 6F 09 BD 01 03 01 00 [Calculate CRC]
-> A2A1 [GET CRC]
<- 0E 60
-> 09 93 09 70 09 88 09 04 09 5E 09 6F 09 BD 09 0E 09 60 01 0C 0D 80 [Select]
-> 898989 [Read SAK]
<- 24 D8 36
******************************CL1 выполнили, теперь нам требуется произвести CL2 (команда 95 и 20 байт)
-> 09 95 09 20 01 0C 0D 80 [Anticol]
-> 8989898989 [Read UID]
<- DA 49 34 80 27
-> 0995097009DA094909340980092701030100 [Calculate CRC]
-> A2A1 [GET CRC]
<- A4E1
-> 0995097009DA094909340980092709A409E1010C0D80 [Select]
-> 898989 [Read SAK]
<- 20FC70
DA 49 34 80 27
Фиолетовым выделены 4 байта UID3 UID4 UID5 UID6, и его BCC 27.
И так, UID: 04 5E 6F DA 49 34 80
Теперь надо отправить RATS — Request for
Answer To Select
На что карта должна ответить нам ATS — Answer To Select
Вроде так — https://www.nxp.com/docs/en/application . df#page=13
-> 0A80 [Clear FIFO]
-> 09E0098009310973 010C 0D80 [Send RATS]
-> 8989898989898989 [Answer]
<- 06 75 77 81 02 80 02 F0
06 75 77 81 02 80 02 F0 — ATS.
Что это значит сейчас будем узнавать.
Так, что то я пока не нашел описание ответа ATS. Так что отодвину данный вопрос на завтра.
Копаю дальше.
Предположительно после RATS и ответе на него, мы должны выделить Application.
У Desfire карт в отличии от Classic работа с памятью проходит посредством взаимодействия с Application ID. Ну, что то вроде блоков, с которыми мы можем взаимодействовать при помощи разных механизмов.
Что можно делать с Application:
Set Key Settings
Get Key Settings
Change Key
Get Key Version
Create App (Master)
Delete Application
Get AID List
Get Card Version
Format PICC (Master)
Get File List
Get File Settings
Change File Settings
Create Data File
Create Value File
Create Record File
Delete File
Read Data (All)
Write Data (Std)
И много чего еще, но меня пока интересует базис.
Что такое RFID? Как это работает? Взаимодействие RFID модуля RC522 с Arduino
Давно прошли те времена, когда люди стояли и ждали в длинных кассовых очередях в продуктовом магазине. Но теперь, благодаря технологии радиочастотной идентификации (RFID, Radio Frequency IDentification), с помощью решений на базе RFID вы можете заполнить корзину и выйти прямо за дверь. Вам больше не придется ждать, пока кассир пробьет каждый товар в вашей корзине по отдельности. Вместо этого RFID метки, прикрепленные к предметам, будут связываться с RFID считывателем, который будет обнаруживать каждый товар в корзине и пробивать его практически мгновенно.
Что такое RFID? Как это работает? Взаимодействие RFID модуля RC522 с Arduino
Для большинства наших проектов на Arduino отличным выбором будет RFID модуль чтения/записи RF522. Он обладает низким энергопотреблением, низкой стоимостью, он довольно прочный, прост для взаимодействия и безумно популярен среди любителей.
Что такое технология RFID и как она работает?
RFID или система радиочастотной идентификации состоит из двух основных компонентов: транспондера или метки, прикрепленной к идентифицируемому объекту, и приемопередатчика, также известного как интеррогатор (interrogator) или считыватель.
Рисунок 1 – Как работает технология RFID
Считыватель состоит из радиочастотного модуля и антенны, которая генерирует высокочастотное электромагнитное поле. Метка, напротив, обычно является пассивным устройством, то есть она не содержит батареи. Вместо этого она содержит микрочип, который хранит и обрабатывает информацию, и антенну для приема и передачи сигнала.
Для считывания информации, закодированной в метке, она размещается в непосредственной близости от считывателя (она не обязательно должна находиться в пределах прямой видимости от считывателя). Считыватель генерирует электромагнитное поле, которое заставляет электроны проходить через антенну метки и обеспечивать чип питанием.
Рисунок 2 – Как работает технология RFID
Обеспеченная питанием микросхема внутри метки затем отвечает отправкой своей сохраненной информации обратно считывателю в виде другого радиосигнала. Это называется обратным рассеянием (backscatter). Обратное рассеяние или изменение электромагнитной/радиочастотной волны обнаруживается и интерпретируется считывателем, который затем отправляет данные на компьютер или микроконтроллер.
Обзор аппаратного обеспечения — Модуль чтения / записи RF522 RFID
RFID модуль RC522 на основе микросхемы MFRC522 от NXP – это один из самых недорогих вариантов RFID, который вы можете найти в интернете менее чем за четыре доллара. Обычно он поставляется с картой RFID метки и брелоком с объемом памяти 1 КБ. И что лучше всего, он может записать метку, чтобы вы могли хранить в ней свое секретное сообщение.
Рисунок 3 – Модуль RFID считывателя RC522 с меткой-картой и меткой-ключом
Модуль считывателя RFID RC522 предназначен для создания электромагнитного поля на частоте 13,56 МГц, которое он использует для связи с метками RFID (стандартные метки ISO 14443A). Считыватель может взаимодействовать с микроконтроллером через 4-контактный последовательный периферийный интерфейс (SPI) с максимальной скоростью передачи данных 10 Мбит/с. Он также поддерживает связь по протоколам I2C и UART.
У модуля имеется вывод прерывания. Это удобно потому, что вместо того, чтобы постоянно опрашивать RFID модуль «есть ли карта в поле зрения?», модуль сам предупредит нас, когда метка окажется рядом.
Рабочее напряжение модуля составляет от 2,5 до 3,3 В, но хорошая новость заключается в том, что логические выводы допускают напряжение 5 вольт, поэтому мы можем легко подключить его к Arduino или любому микроконтроллеру с 5-вольтовой логикой без использования какого-либо преобразователя логических уровней.
| Частотный диапазон | 13,56 МГц, ISM диапазон |
| Интерфейс | SPI / I2C / UART |
| Рабочее напряжение питания | от 2,5 В до 3,3 В |
| Максимальный рабочий ток | 13-26 мА |
| Минимальный ток (отключение питания) | 10 мкА |
| Логические входы | допускают 5 В |
| Расстояние считывания | 5 см |
Распиновка RFID модуля RC522
Модуль RC522 имеет всего 8 контактов, соединяющих его с внешним миром.
Рисунок 4 – Распиновка RFID модуля считывателя RC522
VCC обеспечивает питание для модуля. Напряжение питания может быть в диапазоне от 2,5 до 3,3 вольт. Вы можете подключить его к выходу 3.3V вашей платы Arduino. Помните, что подключение его к выводу 5V, скорее всего, выведет модуль из строя!
RST – вход для сброса и отключения питания. Когда на этот вывод подается низкий логический уровень, запускается жесткое отключение питания. Оно отключает всех внутренних потребителей тока, включая генератор, и входные выводы отключаются от внешних цепей. Во время нарастающего фронта на этом выводе модуль сбрасывается.
GND вывод земли, должен быть подключен к выводу GND на Arduino.
IRQ – вывод прерывания, который может предупредить микроконтроллер, когда поблизости будет RFID метка.
Вывод MISO / SCL / Tx действует либо как Master-In-Slave-Out (вход ведущего – выход ведомого) при включенном интерфейсе SPI, либо как последовательный тактовый сигнал при включенном интерфейсе I2C, либо как выход последовательных данных при включенном интерфейсе UART.
MOSI (Master Out Slave In) – вход SPI для модуля RC522.
SCK (Serial Clock) принимает тактовые импульсы, предоставляемые мастером на шине SPI, то есть Arduino.
Вывод SS / SDA / Rx действует либо как вход, когда включен интерфейс SPI, либо как линия последовательных данных, когда включен интерфейс I2C, либо как вход последовательных данных, когда включен интерфейс UART. Этот вывод обычно помечается заключением в квадрат, чтобы его можно было использовать в качестве опорной точки для идентификации других выводов.
Подключение RFID модуля RC522 к Arduino UNO
Теперь, когда мы знаем всё о модуле, мы можем подключить его к нашей плате Arduino!
Для начала подключите вывод VCC на модуле к выводу 3,3V на Arduino, а вывод GND — к земле Arduino. Вывод RST может быть подключен к любому цифровому выводу на Arduino. В нашем случае он подключен к цифровому выводу 5. Вывод IRQ не подключен, так как библиотека Arduino, которую мы собираемся использовать, не поддерживает его.
Теперь у нас остаются выводы, которые используются для связи по SPI. Поскольку модуль RC522 требует передачи больших данных, то наилучшая производительность будет обеспечена при использовании аппаратного модуля SPI в микроконтроллере. Использование выводов аппаратного SPI модуля намного быстрее, чем «дергание битов» в коде при взаимодействии через другой набор выводов.
Обратите внимание, что у плат Arduino выводы SPI различаются. Для плат Arduino, таких как UNO/Nano V3.0, это цифровые выводы 13 (SCK), 12 (MISO), 11 (MOSI) и 10 (SS).
Если у вас Arduino Mega, выводы отличаются! Вы должны использовать цифровые выводы 50 (MISO), 51 (MOSI), 52 (SCK) и 53 (SS). В таблице ниже приведен список выводов для связи по SPI для разных плат Arduino.
| MOSI | MISO | SCK | CS | |
|---|---|---|---|---|
| Arduino Uno | 11 | 12 | 13 | 10 |
| Arduino Nano | 11 | 12 | 13 | 10 |
| Arduino Mega | 51 | 50 | 52 | 53 |
В случае если вы используете плату Arduino, отличную от приведенных выше, рекомендуется проверить официальную документацию Arduino, прежде чем продолжить.
Рисунок 5 – Подключение модуля RFIDсчитывателя RC522 к Arduino UNO
Как только вы всё подключите, вы готовы к работе!
Код Arduino. Считывание RFID метки
Связь с RFID модулем RC522 – это сложная работа, но, к счастью для нас, есть библиотека MFRC522, которая упрощает чтение и запись в RFID меток. Спасибо Мигелю Бальбоа. Сначала скачайте библиотеку, посетив репозиторий GitHub, или просто нажмите на кнопку ниже, чтобы скачать архив:
Чтобы установить библиотеку, откройте Arduino IDE, перейдите в Скетч → Подключить библиотеку → Добавить .ZIP библиотеку и выберите только что загруженный файл rfid-master.zip .
После установки библиотеки откройте меню Файл → Примеры → MFRC522 → DumpInfo .
Рисунок 6 – Скетч DumpInfo библиотеки MFRC522
Этот скетч не будет записывать какие-либо данные в метку. Он просто сообщает вам, удалось ли ему прочитать метку, и отображает некоторую информацию о ней. Это может быть очень полезно, прежде чем опробовать любую новую метку!
Перейдите к началу скетча и убедитесь, что RST_PIN инициализирован правильно, в нашем случае мы используем цифровой вывод 5, поэтому измените его на 5!
Рисунок 7 – Изменение вывода RST в примере скетча
Хорошо, теперь загрузите скетч в Arduino и откройте монитор последовательного порта. Как только вы приблизите метку к модулю, вы, вероятно, получите что-то вроде следующего. Не двигайте метку, пока не отобразится вся информация.
Рисунок 8 – Вывод скетча DumpInfo
Он отображает всю полезную информацию о метке, включая уникальный идентификатор (UID) метки, объем памяти и содержание всей памяти в 1 КБ.
Распределение памяти MIFARE Classic 1K
Память метки 1 КБ организована в 16 секторов (от 0 до 15). Каждый сектор дополнительно делится на 4 блока (блоки 0–3). Каждый блок может хранить 16 байтов данных (от 0 до 15).
Это говорит нам, что у нас точно
16 секторов x 4 блока x 16 байтов данных = 1024 байта = 1 КБ памяти
Весь 1 килобайт памяти с секторами, блоками и данными показан ниже.
Рисунок 9 – Вывод скетча DumpInfo. Структура памяти
Рисунок 10 – Трехмерное представление структуры памяти MIFARE Classic 1K
Блок 3 каждого сектора называется Sector Trailer и содержит информацию, называемую Access Bits (биты доступа), для предоставления доступа на чтение и запись к остальным блокам в секторе. Это означает, что в каждом секторе на самом деле для хранения данных доступны только 3 нижних блока (блоки 0, 1 и 2), а это означает, что в 64 байтовом секторе у нас есть только 48 байтов, доступных для нашего собственного использования.
Блок 0 сектора 0 также известен как Manufacturer Block / Manufacturer Data содержит данные производителя микросхемы и уникальный идентификатор (UID). Блок производителя выделен ниже красным цветом.
Рисунок 11 – Вывод скетча DumpInfo. Блок производителя
Предупреждение: перезаписывать блок производителя очень рискованно, и это может навсегда заблокировать карту.
Код Arduino. Запись в RFID метку
Учитывая, что вы успешно прочитали RFID метку, пора перейти к следующему эксперименту. В следующем скетче будет показана простая демонстрация записи пользовательских данных в RFID метку. Протестируйте скетч, прежде чем мы начнем его подробный разбор.
Вывод в мониторе последовательного порта будет выглядеть следующим образом.
Рисунок 12 – Вывод скетча записи RFID метки с помощью RC522
Объяснение кода:
Скетч начинается с включения библиотек MFRC522 и SPI, определения выводов Arduino, к которым подключен RC522, и создания объекта считывателя MFRC522.
Далее нам нужно определить блок, в котором мы собираемся хранить наши данные. Здесь выбран сектор 0, блок 2. Помните, никогда не выбирайте блок 3 в любом секторе. Запись в блок Sector Trailer может сделать блок непригодным для использования.
Далее мы определяем массив из 16 байтов с именем blockcontent[16] , который содержит сообщение, которое мы хотим записать в блок. Вы можете удалить любой блок, написав в него нули.
Далее нам нужно определить массив из 18 байтов с именем readbackblock[18] . Он может быть использован для чтения контента обратно. Подождите . 18 байт? Разве не должно быть 16 байтов? Ответ — нет. Метод MIFARE_Read в библиотеке MFRC522 для хранения 16 байтов блока требует буфер размером не менее 18 байтов.
В функции setup() мы инициализируем последовательную связь с ПК, библиотеку SPI и объект MFRC522. Нам также необходимо подготовить ключ безопасности для функций чтения и записи. Здесь все шесть байтов ключа установлены в 0xFF . Поскольку карты в наборе новые, и их ключи никогда не менялись, они равны 0xFF . Если бы у нас была карта, которая была запрограммирована кем-то другим, нам нужно было бы знать ключ, чтобы получить к ней доступ. Затем этот ключ необходимо будет хранить в переменной key .
В функции loop() мы сначала сканируем, есть ли поблизости карта, если да, эта карта выбирается для записи и чтения.
Записать блок теперь очень просто, нам просто нужно вызвать пользовательскую функцию writeBlock() , которая принимает два параметра: номер блока, в который мы хотим записать данные, и сами данные.
Чтобы проверить, была ли операция записи успешной, нам нужно прочитать содержимое блока обратно. Это можно сделать с помощью пользовательской функции readBlock() , которая снова принимает два параметра: один — номер блока, а другой — массив для хранения содержимого блока. Вы можете использовать функцию PICC_DumpToSerial() , если хотите увидеть весь 1 килобайт памяти с записанным в нее блоком.
Наконец, мы печатаем содержимое массива readbackblock с помощью цикла for и отображаем его в мониторе последовательного порта.
Проект на Arduino
RFID система контроля доступа для дверного замка
Давайте создадим небольшой проект на Arduino, чтобы продемонстрировать, как простой модуль RFID считывателя RC522 можно использовать для создания RFID системы контроля доступа для дверного замка. Наша программа будет сканировать уникальный идентификатор каждой RFID метки, когда она достаточно близко, чтобы запитываться от считывателя RC522. Если UID метки соответствует предопределенному значению ( MasterTag ), которое хранится в памяти Arduino, доступ будет предоставлен. И если сканируем любую неизвестную метку, доступ будет запрещен. Круто! Так ведь?
Так выглядит результат.
Рисунок 13 – Демонстрация работы RFID системы контроля доступа для дверного замка
Конечно, этот проект можно привязать к открытию дверей, включению реле, включению светодиода или к чему-то еще.
Если вы не знакомы с символьными LCD дисплеями размером 16×2, то взгляните на эту статью.
Прежде чем мы перейдем к загрузке кода и сканированию меток, давайте посмотрим на принципиальную схему проекта.
Рисунок 14 – RFID система контроля доступа для дверного замка. Подключение RFID считывателя RC522 и LCD дисплея к Arduino
Всё! Теперь попробуйте приведенный ниже скетч в работе.
Программа довольно проста. Сначала мы включаем необходимые библиотеки, определяем выводы Arduino, создаем объекты LCD и MFRC522 и определяем главную метку.
В функции setup() мы инициализируем интерфейс SPI, объект MFRC522 и LCD дисплей. После этого мы печатаем на LCD дисплее приветственное сообщение.
В функции loop() мы ждем, пока не будет отсканирована новая метка. Как только это будет сделано, мы сравним неизвестную метку с мастер-меткой, определенной в функции setup() . Всё! Если ID метки совпадает с ID мастера, доступ предоставляется, в противном случае в доступе будет отказано.
Ключевым моментом в проекте является пользовательская функция getID() . Как только она просканирует новую карту, внутри цикла for она преобразует 4 байта UID в строки и объединяет их для создания одной строки.
