Оглавление:

Превратите ваш Arduino в устройство для чтения магнитных карт!: 9 шагов (с изображениями)
Превратите ваш Arduino в устройство для чтения магнитных карт!: 9 шагов (с изображениями)

Видео: Превратите ваш Arduino в устройство для чтения магнитных карт!: 9 шагов (с изображениями)

Видео: Превратите ваш Arduino в устройство для чтения магнитных карт!: 9 шагов (с изображениями)
Видео: Приказ комиссара. Warhammer 40k 2024, Июль
Anonim
Превратите ваш Arduino в устройство для чтения магнитных карт!
Превратите ваш Arduino в устройство для чтения магнитных карт!
Превратите ваш Arduino в устройство для чтения магнитных карт!
Превратите ваш Arduino в устройство для чтения магнитных карт!
Превратите ваш Arduino в устройство для чтения магнитных карт!
Превратите ваш Arduino в устройство для чтения магнитных карт!

Думаю, все использовали считыватели магнитных карт. Я имею в виду, кто в наши дни носит наличные? Их тоже несложно достать, и во время поездки в мой любимый местный магазин электроники я нашел мусорное ведро, полное этих парней. Итак … конечно, я взял один и принес домой, чтобы посмотреть, что я могу сделать с ним и AVR.

Это руководство покажет вам, как подключить считыватель магнитных карт Magtek к AVR или Arduino / clone и прочитать данные с первой дорожки карты. Пристегните свои сиденья; считыватели магнитных карт имеют высокий битрейт!

Шаг 1: Список оборудования

Список оборудования
Список оборудования
Список оборудования
Список оборудования

Вот несколько вещей, которые вам понадобятся для начала.

  • Считыватель магнитных карт (мой - считыватель с двумя головками Magetk 90 мм. $ 5,00)
  • AVR, Arduino или клон (ATmega328p ~ 4,30 доллара США с сайта Mouser.com
  • беспаечный макет
  • какой-то провод
  • может быть, заголовок, если вам нравится такая вещь.
  • что-нибудь для чтения вашего последовательного порта. Я использую терминал AVR от BattleDroids.net

Это все, что вам нужно для начала. В зависимости от того, какой считыватель магнитных карт вы в конечном итоге получите, вам, возможно, придется изменить эти инструкции и, безусловно, код, чтобы работать с вашим конкретным считывателем. Тем не менее, я надеюсь, что написанный мной код должен увести вас довольно далеко.

Шаг 2: самосинхронизирующиеся считыватели магнитных карт

Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт
Самосинхронизирующиеся считыватели магнитных карт

Считыватели магнитных карт являются «самосинхронизирующимися», что означает, что они обеспечивают синхронизацию, называемую стробом, с которой подключенный микроконтроллер может синхронизироваться. Это благо. Это означает, что вам не нужно беспокоиться о поиске синхронизирующего сигнала и синхронизации сигнала, чтобы он центрировался непосредственно на тактовом импульсе, и не беспокоиться о колебаниях в зоне наилучшего восприятия тактового сигнала. Это имеет смысл, когда вы думаете о смахивании карточек: все смахивают в разном темпе, некоторые медленнее, некоторые быстрее, чем другие. Автосинхронизация позволяет даже моей милой бабушке использовать свою карту, не ломая себе запястье. Напоминает мне о необходимости изменить для нее настройку, определяющую допустимое время между щелчками для регистрации двойного щелчка….

Данные этого кард-ридера действительны за 1,0 мкс до того, как строб будет включен в линию, поэтому не стоит беспокоиться о задержке, чтобы попасть в «битовое время». Для считывателя с двумя головками, такого как тот, который я использую, доступны две дорожки данных для чтения. В этой библиотеке я покажу чтение с первого трека, чтобы вы начали. Вам необходимо выполнить пять подключений (четыре, если вы не против отказаться от более точного управления и использовать меньшее количество портов ввода-вывода). Посмотрите картинку ниже. Красный провод идет на + 5В, а черный провод идет на землю. Зеленый провод - / CARD_PRESENT; желтый провод - / STROBE, а белый провод - / DATA1. Косая черта (/) означает, что данные инвертированы. Низкий сигнал (то есть 0) читается как единица или высокий. Остальные разъемы коричневого цвета для / STROBE2 и оранжевого цвета для / DATA2. Мы не будем их использовать. Если хотите, можете забыть о / CARD_PRESENT. Эта линия данных становится низкой после примерно 17 оборотов потока головки, чтобы указать, что карта присутствует (вместо, скажем, случайного шума, заставляющего ваш считыватель отправлять поддельные данные), и используется для проверки того, что данные, которые вы получаете, являются данными карты и не барахло. Вы можете пропустить это соединение, если вы проверите начальную контрольную точку в потоке данных. Подробнее об этом позже. Как вы можете видеть ниже, я использовал штекер под прямым углом, подключенный к макетной плате, и подключил к нему свой считыватель. Я подключил / STROBE к PIND2 (цифровой контакт 2 на Arduino), / CARD_PRESENT к PIND3 (в целях иллюстрации) и / DATA1 к PIND4. Убедитесь, что вы включили подтягивание этих штифтов, чтобы штифты не плавали. Я также обменял свой Arduino на AVR Bare Bones, потому что мне нравится, как он помещается в макетную плату.

Шаг 3. Основы работы с магнитными картами

Основы работы с магнитными картами
Основы работы с магнитными картами

Основные функции, которые вам необходимо выполнить для чтения магнитной карты: 1. Обнаружить, когда карта была проведена, 2. Считать поток данных 3. Обнаружить, когда карта ушла 4. Обработать данные 5. Отобразить data Сначала я познакомлю вас с некоторыми основами работы с магнитными картами, которые вам нужно знать, когда вы начнете писать свой собственный код.

Стандарты магнитных карт

Магнитные карты стандартизированы ISO в следующих документах: 7810 Физические характеристики документа размером с кредитную карту 7811-1 Тиснение 7811-2 Магнитная полоса - низкая коэрцитивность 7811-3 Расположение тисненых символов 7811-4 Расположение дорожек 1 и 2 7811- 5 Расположение дорожки 3 7811-6 Магнитная полоса - высокая коэрцитивность 7813 Карты финансовых транзакций Как видите, финансовые карты указаны в отдельном документе и часто имеют другой формат, чем, скажем, ваша продуктовая карта или международная телефонная карта. Вам нужно будет запрограммировать эти различия. У меня под рукой была только кредитная карта и страховая карта, поэтому я запрограммировал эти типы (они оба относятся к формату B).

Форматы карт

Есть несколько различных форматов магнитных карт. Формат A и B являются общими, причем B - самый распространенный, который я видел, и который поддерживается в этом коде. Я полагаю, что форматы от C до M зарезервированы ISO, а форматы от N до ?? зарезервированы для институционального использования. Дорожка 1 Для финансовых карт первая дорожка записывается со скоростью 210 бит на дюйм и представляет собой первые 0,110 дюйма карты сверху. Данные кодируются как «данные карты» из расчета 7 бит на символ. Это 6 бит для символ и бит для контроля четности. На дорожке 1 ~ 79 буквенно-цифровых символов. Физический порядок обратный. То есть данные записываются на карту в обратном порядке (и, следовательно, будут считаны вашей прошивкой) как. четность нечетная. Формат данных карты выглядит так:

[SS] [FC] [Номер основного счета] [FS] [Имя] [FS] [Дополнительные данные] [FS] [ES] [LRC] где:

SS Начальный дозорный FC Код формата FS Разделитель полей ES Конечный дозорный LRC Знак продольной проверки избыточности Track one SS = '%', FC = один из форматов (часто будет B), FS часто - '', ES - '?' и символом LRC обычно является '<', хотя это не указано в стандартах. Помимо записи на карту обратной стороной, данные имеют бит нечетной четности и имеют размер 0x20 из ASCII. Мы справимся с этим, когда будем обрабатывать данные. Дорожка 2 Дорожка 2 имеет ширину 0,110 дюйма и начинается на 0,110 от верха карты. Плотность записи составляет 75 бит на дюйм. Данные составляют 5 бит на символ и состоят только из 40 цифровых символов. Вы не должны встретить ни одного буквы на этой дорожке. Формат данных карты должен соответствовать этой структуре

[SS] [основной счет №] [FS] [дополнительные данные | дискреционные данные] [ES] [LRC]

SS для второй дорожки - точка с запятой: ';' а FS - '='. Имея это святое знание за поясом, переходите к следующим шагам, чтобы увидеть код, реализующий описанную выше процедуру.

Шаг 4. Определите, когда карта была проведена

Обнаружение, когда карта проводится
Обнаружение, когда карта проводится

1. Обнаружение, когда карта была перемещена. Формально можно проверить контакт / CARD_PRESENT, чтобы увидеть, не опустился ли он на низком уровне. К счастью, в этом нет необходимости. Мы проверим действующую карту позже. В качестве альтернативы вы можете прочитать свой стробоскоп, чтобы увидеть, когда стробоскопы были наложены на контакт, однако это принесет вам много нулей тактирования. Читатель отправит около 60-70 ведущих нулей, чтобы вы знали, что данные будут представлены. Однако мы собираемся использовать природу двоичных данных, чтобы определить, когда начинать запись битов. Начальным сигналом (SS) для первого трека является знак процента (%). Его двоичное значение - 0010 0101, что означает, что оно будет сохранено (и прочитано) как 1010 001 (это 7 бит, поэтому 8-й бит не передается). Теперь внимательный читатель заметит, что, хотя данные идут в обратном направлении, они не соответствуют двоичному значению ASCII. Это потому, что это 0x20 от шестнадцатеричного. Символ% - это 0x25, а 0100 0101 - это 0x05. Из значения карты вычтено 0x20. Тот, который находится там в старшем полубайте, - это бит нечетной четности. Он помещается туда, чтобы в значении было нечетное число единиц. Итак, поскольку мы знаем, что действительная карта всегда будет начинаться с этого стартового сигнального устройства, и поскольку бит четности равен 1, то, когда мы обнаруживаем первый переход с высокого на низкий уровень на выводе данных, мы знаем, что только начали получать начать дозор с карты. Но это не всегда будет правдой, и надежный план - проверить карту / CARD_PRESENT, чтобы узнать, не стал ли он НИЗКОМ. Самый простой способ определить начало SS - создать внешнее прерывание, запускаемое по заднему фронту / STROBE. Данные действительны за 1,0 мкс до спадающего фронта, поэтому, когда вы выбрали спадающий фронт, вы знаете, что можете прочитать вывод / DATA1 и получить действительное значение. Вот код для создания вашего внешнего прерывания, запускаемого по спадающему фронту.

voidInitInterrupt (void) {// Настраиваем прерывание BSET (EIMSK, INT0); // маска внешнего прерывания BSET (EICRA, ISC01); // задний фронт BCLR (EICRA, ISC00); // задний фронт BSET (SREG, 7); // I-бит в SREG}

В моем common.h, который я включаю во все свои программы, можно найти определения BSET и BCLR. Обратитесь к этому файлу, если у вас возникнут вопросы о том, как устанавливать биты. Теперь, когда запускается прерывание, мы хотим выбрать / DATA1 (в моем коде, определенном как CARD_DATA) и установить бит в регистре ввода-вывода общего назначения. Если мы находимся на 7-м бите, сохраните регистр как символ в нашем глобальном буфере. Я использую регистр GPIOR0, потому что это очень быстрый доступ. Псевдокод выглядит примерно так:

Остановить 16-битный таймер Очистить таймер, если ДАННЫЕ НИЗКОЕ. Установите BIT = 1 в REGISTER. Уменьшение BIT. Установите флаг, чтобы мы больше не пропускали 0, иначе DATA HIGH. Установите BIT = 0 в REGISTER Decrement BIT. Если BIT равен 0. Добавить байт в буфер. Индекс приращения Сбросить BIT

Если вы спрашиваете себя, зачем уменьшать, а не увеличивать, помните, что данные идут в обратном направлении, поэтому вместо того, чтобы записывать биты по мере их получения из LSB в MSB, мы сохраняем их из MSB в LSB, поэтому нам не нужно переворачивать биты позже при обработке данных. Если вы действительно хотите, вы также можете добавить сюда шестнадцатеричный код 0x20, но, поскольку на этих стробах он составляет около 5 мкс, я минимизирую обработку в этой подпрограмме обслуживания прерывания.

ISR (INT0_vect) {StopTimer (); ClearTimer (); if (! BCHK (PIND, CARD_DATA1)) // инверсия низкого уровня = 1 {BSET (GPIOR0, bit); --немного; bDataPresent = 1; } иначе, если (bDataPresent) {BCLR (GPIOR0, бит); --немного; } если (бит <0) {бафф [idx] = (char) GPIOR0; ++ idx; бит = 6; } StartTimer ();} Если вам интересно, в чем заключается дело хронометража, это рассматривается на этапе определения того, когда карта покинула считыватель.

Шаг 5: прочтите поток данных

Прочитать поток данных

Что ж, я уже показал вам, как читать данные, поскольку это часть процедуры обслуживания прерывания для нашего внешнего прерывания по спадающему фронту. Альтернативный метод - установить флаг в ISR, а в основном цикле опросить флаг и прочитать данные таким образом, но я считаю, что способ, которым я его представил, чище. Будьте сами себе судьей и напишите свое, но ваш MCU позволит это. При этом давайте перейдем к выяснению того, как определить, когда карта вытаскивает Элвиса и покидает здание.

Шаг 6: обнаружение выхода карты из устройства чтения

Обнаружение выхода карты из устройства чтения
Обнаружение выхода карты из устройства чтения

Определить, когда карта ушла

Формально можно выбрать вывод / CARD_PRESENT, чтобы увидеть, снова ли он стал ВЫСОКИМ, но нам не нужно, чтобы / CARD_PRESENT занимали другой порт ввода-вывода. Вот здесь и появляются эти таймеры. Каждый раз, когда вызывается прерывание, потому что мы обнаружили спад на / STROBE, мы останавливаем таймер, очищаем значение таймера и начинаем чтение. Когда мы закончили читать, мы снова запускаем таймер. Повторяйте до тошноты или пока таймер не достигнет определенного значения. Это означает, что было вызвано последнее прерывание и больше данных не поступало, поэтому мы предполагаем, что это так, и начинаем обрабатывать собранные данные. Для таймеров мы используем TIMER1, то есть 16-битный таймер. Я использую резонатор на 16 МГц снаружи своего AVR. Если вы используете Arduino, то, вероятно, вы тоже. Итак, я выбрал значение предварительного делителя 1024, что означает, что каждые (16, 000, 000/1024) раз таймер будет увеличиваться. То есть он будет «тикать» 15 625 раз в секунду. / CARD_PRESENT перейдет в высокий уровень, указывая на то, что карта покинула считыватель примерно через 150 мсек после последнего бита данных. Зная это, я просто решил проверять каждые 1/4 секунды. Это выглядело бы примерно так:

(((F_CPU) / PRESCALER) / 4) что оказывается около 3900. Итак, когда счетчик таймера TCNT1 достигает 3900, тогда я знаю, что прошло около 300 мс, и я могу с уверенностью заключить, что карта покинула считыватель. Легкий

#define PRESCALER 1024 # define CHECK_TIME ((F_CPU / PRESCALER) / 4) // 250 мс # define StartTimer () BSET (TCCR1B, CS10), BSET (TCCR1B, CS12) // 1024 prescaler # define StopTimer () BCLR (TCCR1B, CS10), BCLR (TCCR1B, CS12) #define ClearTimer () (TCNT1 = 0) Вы видели в ISR, где таймер запускается, останавливается и очищается при каждом прерывании. Теперь в основном цикле мы просто проверяем, достиг ли счетчик таймера нашего целевого значения, и если да, запускаем обработку данных.

for (;;) {if (TCNT1> = CHECK_TIME) {

StopTimer (); ClearTimer (); Данные обработки(); ReadData (); idx = 0; бит = 6; bDataPresent = 0; memset (& buff, 0, MAX_BUFF_SZ1); }} Теперь безопасно обрабатывать данные

код отформатирован

Шаг 7. Обработка данных

Обработка данных
Обработка данных

Обработать данные

Этап обработки состоит из:

  • проверка действующего SS
  • проверка четности
  • преобразование в ASCII
  • проверка на действительный ES
  • проверка LRC

Здесь я не беспокоюсь о проверке четности, так как я просто установил этот бит в ноль. Я также не рассчитываю LRC для этого небольшого урока. Это было бы то, что могло бы понадобиться более полно реализованной прошивке. Вот код для обработки данных, выполняющий вышеуказанные шаги (без ранее упомянутого). Найдите его на изображении ниже. Он прокомментирован и довольно понятен. Специальное замечание о четности и ASCII: я просто сбрасываю бит четности (7-й бит… т.е. 1 с 6 нулями за ним) и для преобразования из «карточных данных» вы должны добавить к значению 0x20. Вот об этом.

Шаг 8: отображение данных

Отобразить данные
Отобразить данные
Отобразить данные
Отобразить данные

Показать данные

Дисплей переходит в программу терминала, которую я написал специально для подключения к AVR через RS232 или USB. Программа называется AVR Terminal. Метод ReadData () довольно уродлив, и вам предлагается найти более чистое решение, чем то, которое придумал я. Также есть вывод функции в Терминале AVR. На выходе получается первая карта медицинского страхования, а вторая карта VISA. Нажмите в верхнем левом углу изображения и выберите исходное или большое изображение, чтобы лучше его рассмотреть.

Шаг 9: загрузка кода и завершение работы

В этом руководстве я обсудил некоторые основы считывателей магнитных карт и показал вам код, который поможет вам начать правильное чтение данных с магнитных карт. Можно сделать еще много работы, например, прочитать и декодировать 2-ю дорожку, вычислить LRC и вычислить нечетную четность для каждого байта. Полный исходный код доступен для загрузки ниже. Он был написан в AVR Studio 4.17. Надеюсь, вам понравилось это руководство, и, как всегда, я с нетерпением жду любых комментариев или предложений, которые могут у вас возникнуть. Удачного кодирования и AVR!

Рекомендуемые: