JSC100 V5.0读写器通讯协议
一、通讯格式
波特率:9600 8 1 N
数据包长度L(1byte) 命令字C(1byte) 数据包D(L-1bytes)
通讯方向:
-> 下位机(读卡器)送给上位机(PC)
<- 上位机(PC)送给下位机(读卡器)
二、单步读卡命令说明(以下数据全为16进制数据)
1) 启动(风鸣器响)
<- 02 0B 0F (02为长度,0B为命令字,测试凤鸣器,0F凤鸣器响的时间)
-> 01 00 (01为长度,00为测试成功)
2) 寻卡(返回卡的类型)
<- 02 02 26 (02为命令字,26为RegMfOutSelect)
-> 03 00 04 00 (00为命令成功代码,04表示Mifare One卡)
3) 防冲突(返回卡的系列号)
<- 01 03 (03为命令字)
-> 05 00 52 00 75 7A (52 00 75 7A为卡号CardSerialNo)
4) 选择
<- 01 04 (04为命令字)
-> 03 00 80 00
5) 终止(使卡休眠)
<- 01 01 (01为命令字)
-> 01 00
6) 密码下载(新卡的密码为6个字节的FF)
<- 09 06 60 01 FF FF FF FF FF FF (06为命令字,60为密码A(61为密码B),01为扇区号,12个F为密码)
-> 01 00
7) 数据读
<- 02 02 52 (02为命令字,52为PICC_REQALL)
-> 03 00 04 00 (04为RegFIFOLength)
<- 01 03 (03为命令字)
-> 05 00 52 00 75 7A (52 00 75 7A为卡号)
<- 01 04 (04为命令字)
-> 03 00 08 00
<- 04 05 60 01 04 (校验密码,05为命令字,60为密码A(61为密码B),01为扇区1,04为RegFIFOLength)
-> 01 00
<- 02 08 04 (08为命令字读命令,04为块号)
-> 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (16个00为数据)
<- 02 08 05 (08为命令字,05为块号)
-> 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (16个00为数据)
<- 02 08 06 (08为命令字,06为块号)
-> 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (16个00为数据)
<- 02 08 07 (08为命令字,07为块号)
-> 11 00 00 00 00 00 00 00 ff 07 80 69 ff ff ff ff ff ff (第一个00为返回代码,后面6个00为密码A[不可现],ff 07 80 69为控制位,后面6个ff为密码B[可现])
8) 数据写
<- 12 09 04 12 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (09为命令字写命令,04为块号,12开始的16个字节为要写的数据)
-> 01 00
<- 12 09 05 45 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (09为命令字,05为块号,45开始的16个字节为要写的数据)
-> 01 00
<- 12 09 06 78 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (09为命令字,06为块号,78开始的16个字节为要写的数据)
-> 01 00
<- 12 09 07 11 11 11 11 11 11 ff 07 80 69 11 11 11 11 11 11 (09为命令字,07为块号,把密码A和密码B都修改成1)[可看成改密码的命令]
-> 01 00
9) 块值操作(初始化)
<- 12 09 04 11 11 11 11 EE EE EE EE 11 11 11 11 04 FB 04 FB (09为命令字块值初始化,04为块号,11开始的16个字节为要写的数据)
-> 01 00
10) 块值操作(读出)
<- 02 08 04 (08为命令字块值读出,04为块号)
-> 11 00 11 11 11 11 EE EE EE EE 11 11 11 11 04 FB 04 FB (11后面的16个自己是读出来的数据)
11) 块值操作(加值)
<- 08 0A C1 04 22 22 22 22 04 (0A为命令字块值加值,C1为PICC_INCREMENT,04为块号,4个字节的22是要加值的数据,04为块号)
-> 01 00
12) 块值操作(减值)
<- 08 0A C0 04 11 11 11 11 04 (0A为命令字,C1为PICC_DECREMENT为块号,4个字节的11是要减值的数据,04为块号)
-> 01 00
13) 修改密码
<- 02 02 26 (02为命令字,26为RegMfOutSelect)
-> 03 00 04 00
<- 01 03 (03为命令字)-> 05 00 52 00 75 7A (52 00 75 7A为卡号)
<- 01 04 (04为命令字)
-> 03 00 80 00
<- 04 05 60 01 04 (05为命令字,60为密码A(61为密码B),01为扇区号,04为RegFIFOLength)
-> 01 00
<- 12 09 07 33 33 33 33 33 33 ff 07 80 69 33 33 33 33 33 33 (09为命令字,07为块号,33后面的12个字节为新密码)
-> 01 00
14) 自动寻卡
<- 02 0E 26 (0E为命令字,26为RegMfOutSelect)
-> 03 00 04 00 (00为命令成功代码,04表示Mifare One卡)
15) 进入软件掉电模式(内部电流消耗模块包括晶振在内关闭)
<- 01 10 (0C为命令字)
-> 01 00
16) 退出软件掉电模式
<- 01 11 (0C为命令字)
-> 01 00
代码
using System;
using
System.Collections.Generic;
using
System.Text;
using
System.IO.Ports;
namespace
Card.Utility
{
///
<summary>
///
摘要:读写卡操作基础类
///
</summary>
public
class
CardManagerUtil
{
private
static
SerialPort _serialPort;
#region
CardManagerUtil 成员
///
<summary>
///
初始化
///
</summary>
///
<param name="port">
端口号
</param>
///
<param name="baud">
波特率
</param>
///
<returns></returns>
public
static
int
rf_init(
int
port,
long
baud)
{
string
portName
=
GetPortName(port);
if
(_serialPort
!=
null
)
{
if
(_serialPort.IsOpen)
_serialPort.Close();
}
_serialPort =
new
SerialPort(portName, Convert.ToInt32(baud));
_serialPort.Parity =
Parity.None;
_serialPort.StopBits =
StopBits.One;
_serialPort.DataBits =
8
;
_serialPort.WriteTimeout =
1
;
try
{
if
(_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Open();
return
100
;
}
catch
{
return
-
1
;
}
}
///
<summary>
///
重置读卡器
///
</summary>
///
<param name="icdev">
设备号
</param>
///
<param name="_Msec"></param>
///
<returns></returns>
public
static
int
rf_reset(
int
icdev,
int
_Msec)
{
try
{
if
(icdev
!=
100
)
return
1
;
if
(_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Open();
return
0
;
}
catch
{
return
-
1
;
}
}
///
<summary>
///
成功返回0
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Msec"></param>
///
<returns>
成功返回0否则返回1
</returns>
public
static
int
rf_beep(
int
icdev,
int
_Msec)
{
if
(icdev
!=
100
)
return
1
;
byte
[] beepData
=
{
0x02
,
0x0B
,
0x0F
};
byte
[] buffer;
int
bufLength
=
WriteAndRead(beepData,
0
, beepData.Length,
2
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
2
)
{
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
返回卡号
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Mode"></param>
///
<param name="_Snr"></param>
///
<returns></returns>
public
static
int
rf_card(
int
icdev,
byte
_Mode,
out
uint
_Snr)
{
int
cardType
=
0
;
_Snr =
0
;
if
(rf_request(icdev,
0
,
out
cardType)
!=
0
)
return
1
;
rf_anticoll(icdev, 0
,
out
_Snr);
return
1
;
}
///
<summary>
///
终止卡(卡休眠)
///
</summary>
///
<param name="icdev"></param>
///
<returns></returns>
public
static
int
rf_halt(
int
icdev)
{
if
(icdev
!=
100
)
return
1
;
byte
[] haltData
=
{
0x01
,
0x01
};
byte
[] buffer;
int
bufLength
=
WriteAndRead(haltData,
0
, haltData.Length,
2
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
2
)
{
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
寻卡
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Mode"></param>
///
<param name="TagType"></param>
///
<returns></returns>
public
static
int
rf_request(
int
icdev,
byte
_Mode,
out
int
TagType)
{
TagType =
0
;
if
(icdev
!=
100
)
return
1
;
byte
[] requestData
=
{
0x02
,
0x02
,
0x52
};
byte
[] buffer
=
new
byte
[
4
];
int
bufLength
=
WriteAndRead(requestData,
0
, requestData.Length,
4
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
4
)
{
TagType =
(
int
)buffer[
2
];
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
卡防冲突
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Bcnt">
0
</param>
///
<param name="_Snr"></param>
///
<returns></returns>
public
static
int
rf_anticoll(
int
icdev,
byte
_Bcnt,
out
uint
_Snr)
{
_Snr =
0
;
if
(icdev
!=
100
)
return
1
;
byte
[] anticollData
=
{
0x01
,
0x03
};
byte
[] buffer;
int
bufLength
=
WriteAndRead(anticollData,
0
, anticollData.Length,
6
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
6
)
{
if
(buffer[
1
]
==
0x00
)
{
List <
byte
>
tempSnr
=
new
List
<
byte
>
();
for
(
int
i
=
5
; i
>
1
; i
--
)
//
低位在前高位在后
{
tempSnr.Add(buffer[i]);
}
if
(tempSnr.Count
==
4
)
_Snr =
BitConverter.ToUInt32(tempSnr.ToArray(),
0
);
return
0
;
}
}
return
1
;
}
///
<summary>
///
选择卡
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Snr"></param>
///
<param name="_Size"></param>
///
<returns></returns>
public
static
int
rf_select(
int
icdev,
uint
_Snr,
out
byte
_Size)
{
_Size =
8
;
if
(icdev
!=
100
)
return
1
;
byte
[] selectData
=
{
0x01
,
0x04
};
byte
[] buffer;
int
bufLength
=
WriteAndRead(selectData,
0
, selectData.Length,
4
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
4
)
{
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
加载密码
///
</summary>
///
<param name="icdev">
设备号
</param>
///
<param name="_Mode">
60为密码A(61为密码B)
</param>
///
<param name="_SecNr">
扇区号
</param>
///
<param name="key">
密码
</param>
///
<returns></returns>
public
static
int
rf_load_key(
int
icdev,
byte
_Mode,
byte
_SecNr,
byte
[] key)
{
if
(icdev
!=
100
)
return
1
;
byte
[] keycmd
=
{
0x09
,
0x06
, _Mode, _SecNr };
List <
byte
>
keyData
=
new
List
<
byte
>
();
if
(key.Length
!=
6
)
//
6字节的密码
{
return
1
;
}
else
{
keyData.AddRange(keycmd);
keyData.AddRange(key);
}
byte
[] buffer;
int
bufLength
=
WriteAndRead(keyData.ToArray(),
0
, keyData.Count,
2
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
2
)
{
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
验证密码
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Mode">
密码组60为A组,61为B组
</param>
///
<param name="_SecNr"></param>
///
<returns></returns>
public
static
int
rf_authentication(
int
icdev,
byte
_Mode,
byte
_SecNr)
{
byte
RegFIFOLength
=
(
byte
)(((
int
)_SecNr)
*
4
);
if
(icdev
!=
100
)
return
1
;
byte
[] authData
=
{
0x04
,
0x05
, _Mode, _SecNr, RegFIFOLength };
byte
[] buffer;
int
bufLength
=
WriteAndRead(authData,
0
, authData.Length,
2
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
2
)
{
if
(buffer[
1
]
==
0x00
)
return
0
;
}
return
1
;
}
///
<summary>
///
从某个扇区读取数据
///
</summary>
///
<param name="icdev">
设备号
</param>
///
<param name="_Adr">
块号
</param>
///
<param name="_Data">
读取到的数据
</param>
///
<returns></returns>
public
static
int
rf_read(
int
icdev,
byte
_Adr,
ref
byte
[] _Data)
{
if
(icdev
!=
100
)
return
1
;
byte
[] readCmdData
=
{
0x02
,
0x08
, _Adr };
byte
[] buffer;
int
bufLength
=
WriteAndRead(readCmdData,
0
, readCmdData.Length,
18
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
18
)
{
if
(buffer[
1
]
==
0x00
)
{
List <
byte
>
tempData
=
new
List
<
byte
>
();
for
(
int
i
=
2
; i
<
18
; i
++
)
{
tempData.Add(buffer[i]);
}
_Data =
tempData.ToArray();
return
0
;
}
}
return
1
;
}
///
<summary>
///
向某个扇区写入数据
///
</summary>
///
<param name="icdev"></param>
///
<param name="_Adr">
块号
</param>
///
<param name="_Data">
要写的数据
</param>
///
<returns></returns>
public
static
int
rf_write(
int
icdev,
byte
_Adr,
byte
[] _Data)
{
if
(icdev
!=
100
)
return
1
;
byte
[] writeCmdData
=
{
0x12
,
0x09
, _Adr };
List <
byte
>
cmdData
=
new
List
<
byte
>
();
if
(_Data.Length
!=
16
)
//
16字节的数据
{
return
1
;
}
else
{
cmdData.AddRange(writeCmdData);
cmdData.AddRange(_Data);
}
byte
[] buffer;
int
bufLength
=
WriteAndRead(cmdData.ToArray(),
0
, cmdData.Count,
2
,
out
buffer);
if
(bufLength
==
0
)
return
1
;
if
(buffer.Length
==
2
)
{
if
(buffer[
1
]
==
0x00
)
{
return
0
;
}
}
return
1
;
}
///
<summary>
///
关闭串口
///
</summary>
///
<param name="icdev"></param>
///
<returns></returns>
public
static
int
rf_exit(
int
icdev)
{
if
(_serialPort
!=
null
)
{
if
(_serialPort.IsOpen)
_serialPort.Close();
return
0
;
}
return
1
;
}
#endregion
#region
私有方法
///
<summary>
///
向串口写数据并阻塞等待数据返回
///
</summary>
///
<param name="buffer"></param>
///
<param name="offset"></param>
///
<param name="count"></param>
///
<param name="ReadRoom"></param>
///
<param name="readBuf"></param>
///
<param name="ByteTime"></param>
///
<returns></returns>
static
int
WriteAndRead(
byte
[] buffer,
int
offset,
int
count,
int
ReadRoom,
out
byte
[] readBuf)
{
_serialPort.Write(buffer, offset, count);
int
val
=
ReadBlock(ReadRoom,
out
readBuf,
500
);
return
val;
}
static
string
GetPortName(
int
port)
{
string
portName
=
string
.Empty;
switch
(port)
{
case
0
:
portName =
"
COM1
"
;
break
;
case
1
:
portName =
"
COM2
"
;
break
;
case
2
:
portName =
"
COM3
"
;
break
;
case
3
:
portName =
"
COM4
"
;
break
;
case
4
:
portName =
"
COM5
"
;
break
;
default
:
portName =
"
COM1
"
;
break
;
}
return
portName;
}
///
<summary>
///
串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据,靠字符间间隔超时确定没有数据)
///
</summary>
///
<param name="ReadRoom">
串口数据缓冲空间大小
</param>
///
<param name="ByteTime">
字节间隔最大时间
</param>
///
<returns>
从串口实际读入的字节
</returns>
private
static
int
ReadBlock(
int
ReadRoom,
out
byte
[] readBuf,
int
ByteTime)
{
readBuf =
new
Byte[ReadRoom];
Array.Clear(readBuf, 0
, readBuf.Length);
sbyte
nBytelen;
if
(_serialPort.IsOpen
==
false
)
return
0
;
nBytelen =
0
;
_serialPort.ReadTimeout =
ByteTime;
while
(nBytelen
<
ReadRoom)
{
try
{
readBuf[nBytelen] =
(
byte
)_serialPort.ReadByte();
nBytelen ++
;
}
catch
{
return
0
;
}
}
return
nBytelen;
}
#endregion
}
}
jquery 读卡器监听 js 读卡器
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
读卡器生产厂,什么是读卡器
读卡器的专业生产厂
职场 休闲 读卡器 -
读卡器获取卡 java 读卡器程序
# pip install netifacesimport subprocessimport structimport threadingfrom PyQt5.QtGui import QFontimport osimport socketimport reimport datetimeimport netifacesfrom PyQt5 import QtCore, QtG
读卡器获取卡 java Python Socket Python Udp Python tcp/udp Python网络