Function ReedCard()
MSComm1.CommPort = 1 'Выставляем порт
MSComm1.Settings = "19200,N,8,1" 'Выставляем настройки
MSComm1.InputLen = 0
On Error Resume Next
MSComm1.PortOpen = True
MSComm1.Output = Chr(&HAA) & Chr(&HBB) & Chr(&H6) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H1) & Chr(&H2) & Chr(&H52) & Chr(&H51) 'Вот это строка для общения с ридером. Первая нужна для "пробуждения" ридера. Отправляем символы в hex виде
sleep (0.1) 'Спим немного, чтоб не бомбить девайс(иногда не работает корректно без сна)
Answer = MSComm1.Input
MSComm1.Output = Chr(&HAA) & Chr(&HBB) & Chr(&H5) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H2) & Chr(&H2) & Chr(&H0) 'Вторая команда пришлет нам ответ. Это то, что нам нужно — код карты. Правда, пока только ASCII-символами
sleep (0.1)
Answer = MSComm1.Input
Dim ReadPort As String
If Len(Answer) > 10 Then 'Если при попытке считать карта была на ридере, то ответом на предыдущую команду будет строка из 14-ти символов. Если на ридер были отправлены команды на считывание, но карты не было на месте, то в ответ будет возвращено 5 символов. Поэтому, если символов >10, то обрабатываем карту
Dim a: a = s2a(Answer) 'StringToArray-функция. Просто переводит нашу строку из 14 символов в массив[14]
Dim i
For i = 0 To UBound(a)
a(i) = Right(0 & Hex(Asc(a(i))), 2) 'В каждом элементе массива "а" у нас хранился какой-то ASCII-символ. Этот цикл пробегается по каждому символу, берет его ascii-код и переводит его в hex
Next
ReadPort = Join(a)
MSComm1.Output = Chr(170) & Chr(187) & Chr(6) & Chr(0) & Chr(0) & Chr(0) & Chr(6) & Chr(1) & Chr(7) & Chr(0) 'А эта команда нужна только для того, чтобы "пикнуть" :) Т.е. ридер просто издаст звук(это для того, чтоб было понятно, что ридер считал карту)
'''' Тут дальше идет мой код, который просто переводит хексовую строку в число. Например: AA BB CC DD -> 2864434397. Тут много кода, но вам он не нужен — вы и сами сможете его написать.
End If
MSComm1.PortOpen = False
End Sub
Function s2a(s)
ReDim a(Len(s) - 1)
Dim i
For i = 0 To UBound(a)
a(i) = Mid(s, i + 1, 1)
Next
s2a = a
End Function
Sub sleep(sk)
PauseTime = sk
Start = Timer
Do While Timer < Start + PauseTime
Loop
End Sub
Не так уж и сложно. Но проблема заключалась в том, что этот код на VB мне нужно было перенести на Pascal в MS-DOS. Несколько дней бился с этим, но скармливая эти команды в Com-порт ридер не подавал признаков жизни. Тогда я решил сначала реализовать это на своём «родном» языке — C#. Так же пришлось попотеть, но в итоге понял в чем кроется разгадка!
serialPort1.Open();
serialPort1.Write(((char)0xAA) + "" + ((char)0xBB) + "" + ((char)0x6) + "" + ((char)0x0) + "" + ((char)0x0) + "" + ((char)0x0) + "" + ((char)0x6) + "" + ((char)0x1) + "" + ((char)0x7) + "" + ((char)0x0));
serialPort1.Close();
Код выше неправильный. Я какое-то время над ним экспериментировал, но он никак не хотел работать. И кавычки убирал. И .ToString() добавлял. И посимвольно писал в порт. Ничего. И потом как вдруг дошло:
serialPort1.Open();
byte[] ar = new byte[10];
ar[0] = 170;
ar[1] = 187;
ar[2] = 6;
ar[3] = 0;
ar[4] = 0;
ar[5] = 0;
ar[6] = 6;
ar[7] = 1;
ar[8] = 7;
ar[9] = 0;
serialPort1.Write(ar, 0, ar.Length);
serialPort1.Close();
И всё заработало! Осталось только перенести это в паскаль:
var
ar: array of Byte[10];
begin
OpenCom (ComNo, B_19200, Bits_8+Stops_1+Parity_No, 2048);
ar[0]:=170;
ar[1]:=187;
ar[2]:=6;
ar[3]:=0;
ar[4]:=0;
ar[5]:=0;
ar[6]:=6;
ar[7]:=1;
ar[8]:=7;
ar[9]:=0;
for i:=0 to 10 do begin
WriteCom(ComNo,ar[i]);
end;
Код выше заставляет ридер «пикнуть». Дальше переделать всё под себя очень просто.
P.S. Информации по этой проблеме в ру-сегменте не нашел совсем, на англоязычных же есть, но крупицы. От себя информацию по работе с RS232 на примере китайского кардридера собрал. Надеюсь кому-нибудь поможет. Удачи!
Комментарии (16)
golf2109
22.02.2017 21:11а автору запретили во время работы использовать любые терминальные программы?
ElijahCapricorn
22.02.2017 21:21Странно, что автор не знает, что в его «родном» C# строки кодируются в utf и каждый символ занимает по два байта.
ColdPhoenix
22.02.2017 22:59хранение в данном случае не имеет значения.
кодировка по умолчанию для строковых операций SerialPort это ASCII, итого все что выше кода 127 обрезано в знак вопроса.
косяк автора в попытке применять строки вместо байт.
Votming
24.02.2017 05:43Вы цепляетесь к словам:) Хотя я и так выделил кавычками слово «родной». Просто он мне ближе других языков, пользуюсь им около двух ле. Я же не написал, что у меня пятнадцатилетний стаж в программировании на шарпе. А про кодировку utf спасибо — буду знать
Zapped
23.02.2017 03:24+2ar[0]=170;
ну, это же не Pascal )))
вот Pascal:
ar[0] := 170;
к слову, идентично
ar[0] := $AA;
команды и данные таких протоколов удобнее для понимания писать в шестнадцатиричной форме
Votming
24.02.2017 05:47Спасибо, что поправили. Не было под рукой ничего, поэтому вписал в статью код «от руки». А на паскале не пишу, поэтому синтаксис в голове не «закрепился». Вот и забыл про присвоение
aamonster
23.02.2017 12:20Без обид, но это одна из классических ошибок новичка, никак не связанных с кардридерами и ком-портами. Если у вас было в институте/школе программирование — то там наверняка упоминали текстовые и бинарные файлы, и запись в них, возможно, даже производилась разными функциями. Вот это оно самое (работать с бинарным файлом, как с текстовым — и так испортить его).
А в сети вы не нашли информацию просто потому, что искали в применении к RS232. А кто работает с RS232 — обычно уже давно на эти грабли не наступает.
Votming
24.02.2017 05:32Да, вы правы, это ошибки новичка. С ком-портами до этого не работал(только с виртуальными). В институте было упоминание про бинарники, но тогда была одна лабораторная на 1ом курсе, где надо было записать и считать данные в\из бинарного файла. Подумал, может тоже у кого будут проблемы похожие: новички, которые не могут разобраться и найти информацию. Уже даже не знаю, нужно ли было писать этот топик
aamonster
24.02.2017 10:02Да нормально, мир не из одних зубров состоит, и на эти грабли новички регулярно наступают (правда, обычно им везёт больше, чем вам — пишут в файл, а не в устройство, и могут посмотреть, что же записалось, так что ошибку видят почти сразу). Если б ещё заголовок придумать такой, чтобы отражал суть проблемы...
DCNick3
24.02.2017 05:28Скорее всего проблема в том, что у c# нативные строки (ну и char тоже) — юникодовые (UCS-2). Поэтому карт-ридеру это и не нравится. Но я-бы для начала попробовал пообщатся с ним через какой-нибудь терминал для COM портов. И мучиться не надо, колдуя над строками, и сразу видно что отвечает…
Shyster
24.02.2017 05:29мне нужно было перенести на Pascal в MS-DOS.
как будто окунулся, лет на 20 с хвостиком. Когда на Поиск1 читал первые карточки ISO7816 через LPT, с помощью паскаля.Votming
24.02.2017 05:49У нас сейчас половина машин на предприятии работает на досе. Забавно понимать, что ломаешь голову над теми проблемами, которые волновали людей 20 лет назад
barker
24.02.2017 15:21Статья не про RS232, а про serial port вообще.
Хотя и не про сериал порт, а про ввод-вывод вообще.
Да и не про ввод-вывод, а про базовый уровень понимания предмета)
Genoik
Стесняюсь спросить, а о чем вообще статья?
Для вас стало открытием, что через Com-порт нужно пересылать Byte, а не char? Мне кажется, что любой человек, более-менее работавший с железом через Com-порт в курсе этого.
Содержание статьи даже не соответствует заголовку, имхо. Разве в ней описано общение? По-моему, вы просто описали проблему, с которой встретились лично вы, и написали ее решение. Конкретно к картридеру эта проблема не имеет никакого отношения. На его месте могла бы быть любая железка. Точно с такими же проблемами, вы бы столкнулись, если бы писали не на Паскале и C#, но и при работе с Qt, например.
Votming
Не мог решить проблему несколько дней. Провёл небольшой ресерч. Решил поделиться с интернетом, может кто-нибудь из таких же новичков как я наткнётся на такую проблему. Эта статья же не мой дипломный проект. И не диссертация. Я всего лишь написал в песочницу, за что такой хейт. Если вы за справедливость, то не подскажете мне, как стоило назвать сей топик? Я бы сменил его, чтоб не нервировать старожилов :)
Genoik
Я могу ошибаться, но такие вещи обычно не в статьях пишутся, а максимум на форумах решаются.
Если перефразировать вас, то эта статья выглядит примерно так:
«Есть код:
int a = 10;
int b = 3;
float c = a / b;
Несколько дней не могу решить проблему, все время неправильно вычислялось значение. И мне пришло в голову написать так: float c = (float) a / (float)b.
Решил написать статью, может поможет новичкам.»
Вы ведь не будете спорить, что это частая ошибка новичка.
Я не против статей, но в последнее время Хабр становится похож на личные блоги с заметками.