本示例使用的发卡器:RS232串口RFID NFC IC卡读写器可二次开发编程发卡器USB转COM-淘宝网 (taobao.com)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace MSCommReader
{
delegate void ThreaUI(byte[] bytes, int byteslen); //定义一个线程内处理数据的委托
public partial class Form1 : Form
{
int SendCode = 0;
int S70Page; //s70扇区号
int S70block; //S70绝对块地址
byte[] S70buffdata = new byte[300]; //S70数据缓冲
int S70buffp; //s70数据指针
string wstr; //s70写卡数据
public Form1()
{
InitializeComponent();
}
private static bool ishexstr(string inputstr,int strlen)
{
bool status;
try
{
for (int i = 0; i < strlen; i++)
{
byte bytedata = Convert.ToByte(Convert.ToInt32(inputstr.Substring(i * 2, 2), 16));
}
status = true;
}
catch{
status = false ;
}
return status;
}
private void Form1_Load(object sender, EventArgs e)
{
Serial_init();
comboBoxrw.SelectedIndex = 0;
comboBoxauth.SelectedIndex =0;
comboBoxinit.SelectedIndex = 1;
comboBoxSector.SelectedIndex = 1;
comboBoxAuthAB.SelectedIndex = 1;
comboBoxchangekey.SelectedIndex = 1;
}
private void Serial_init()
{
string[] ports = System.IO.Ports.SerialPort.GetPortNames(); // 获取本机可用串口端口
comboBoxPort.Items.AddRange(ports);
comboBoxPort.SelectedIndex = comboBoxPort.Items.Count > 0 ? comboBoxPort.Items.Count-1 : -1; // 有可用端口显示第一个
comboBoxBaud.SelectedIndex = 4;
comboBoxData.SelectedIndex = 0;
comboBoxStop.SelectedIndex = 0;
comboBoxCheck.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
if (comboBoxPort.Items.Count < 1)
{
MessageBox.Show("没用任何串口可供使用!", "提示");
return;
}
try
{
serialPort1.PortName = comboBoxPort.Text;
serialPort1.BaudRate = int.Parse(comboBoxBaud.Text);
serialPort1.DataBits = int.Parse(comboBoxData.Text);
switch (comboBoxStop.SelectedIndex)
{
case 0:
serialPort1.StopBits = StopBits.One;
break;
case 1:
serialPort1.StopBits = StopBits.OnePointFive;
break;
default:
serialPort1.StopBits = StopBits.Two ;
break;
}
switch (comboBoxCheck.SelectedIndex)
{
case 0:
serialPort1.Parity = Parity.None;
break;
case 1:
serialPort1.Parity = Parity.Odd ;
break;
case 2:
serialPort1.Parity = Parity.Even ;
break;
case 3:
serialPort1.Parity = Parity.Mark ;
break;
default:
serialPort1.Parity = Parity.Space;
break;
}
serialPort1.ReadTimeout =1000;
serialPort1.Open();
button1.Text = "关闭串口";
button1.BackColor = Color.Lime ;
}
catch (Exception err)
{
MessageBox.Show("串口打开失败!" + err.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
try
{
serialPort1.Close ();
}
catch (Exception){}
button1.Text = "打开串口";
button1.BackColor = Color.Red;
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(50); //这个延时很有必要,防止接收数据不全
int len = serialPort1.BytesToRead;
byte[] buff = new byte[len];
serialPort1.Read(buff, 0, len);
if (len > 0)
{
this.BeginInvoke(new ThreaUI(ThreaUIPriv), buff, len); //使用委托处理接收到的数据
}
}
private void ThreaUIPriv(byte[] buff, int len)
{
string hexstr = DateTime.Now.ToLocalTime().ToString("HH:mm:ss.fff") + " Rece : ";
for (int i = 0; i < len; i++)
{
hexstr = hexstr + buff[i].ToString("X2") + " ";
}
listBox1.Items.Add(hexstr);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
byte crc = 0;
for (int i = 1; i < len; i++)
{
crc = (byte)(crc ^ buff[i]);
}
if (crc == 0)
{
string cardnohex = "";
string dispstr = "";
switch (SendCode)
{
case 1: //驱动发卡器响声的回应
dispstr = "发卡器已响应发出响声的指令!";
break;
case 2: //轻松读Ntag卡的回应
switch (buff[1])
{
case 0x00:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "读Ntag卡成功,卡号:" + cardnohex + ",起始页:" + buff[9].ToString("D") + ",总计页数:" + buff[10].ToString("D");
string datahex = "";
for (int i=11;i<len-1;i++){
datahex = datahex + buff[i].ToString("X2") + " ";
}
textBoxData.Text = datahex;
break;
case 0x08:
dispstr = "未寻到卡!";
break;
case 0x09:
dispstr = "读卡失败!两张以上卡片同时在感应区发生冲突!";
break;
case 0x0C:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "密码认证失败,卡号:" + cardnohex;
break;
case 0x0D:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "读卡失败,可能要带密码操作,卡号:" + cardnohex;
break;
default:
dispstr = "读卡失败,返回代码:" + buff[1].ToString("D");
break;
}
break;
case 3: // 写Ntag卡的回应
switch (buff[1])
{
case 0x00:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "写Ntag卡成功,卡号:" + cardnohex;
break;
case 0x08:
dispstr = "未寻到卡!" ;
break;
case 0x09:
dispstr = "写卡失败!两张以上卡片同时在感应区发生冲突!";
break;
case 0x0C:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "密码认证失败,卡号:" + cardnohex;
break;
case 0x0E:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") + buff[6].ToString("X2") + buff[7].ToString("X2") + buff[8].ToString("X2");
dispstr = "写卡错误,可能要带密码操作,卡号:" + cardnohex;
break;
default:
dispstr = "写卡失败,返回代码:" + buff[1].ToString("D");
break;
}
break;
case 4: //读取M1卡序列号的回应
case 5: //轻松读M1卡扇区数据的回应
case 6: //轻松写M1卡扇区数据的回应
case 7: //修改扇区密码的回应
switch (buff[0])
{
case 1:
switch (buff[1])
{
case 8:
dispstr = "未寻到卡!" ;
break;
case 9:
dispstr = "两张以上卡片同时在感应区,发生冲突!" ;
break;
case 10:
dispstr = "无法选择激活卡片!" ;
break;
case 11:
dispstr = "密码装载失败,卡片序列号已知!";
break;
default :
dispstr = "操作卡失败,返回代码:" + buff[1].ToString("D");
break;
}
break;
case 5:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2") ;
switch (buff[1])
{
case 0:
if (SendCode == 4) {
dispstr = "读卡序列号成功,卡号:" + cardnohex;
}
else if (SendCode == 5)
{
dispstr = "读扇区数据成功,卡号:" + cardnohex;
}
else if (SendCode == 6) {
if (S70Page > 31 && S70block < 15)
{ //写s70大扇区
byte[] SendBuf = new byte[20];
SendBuf[0] = 0x12;
SendBuf[1] = 0xA5;
SendBuf[2] = (byte)(128 + (S70Page - 32) * 16 + S70block);
crc = (byte)(SendBuf[1] ^ SendBuf[2]);
for (int i = 0; i < 16; i++)
{
SendBuf[3 + i] = Convert.ToByte(Convert.ToInt32(wstr.Substring((S70buffp-1) * 2 , 2), 16));
crc = (byte)(crc ^ SendBuf[3 + i]);
S70buffp = S70buffp + 1;
}
SendBuf[19] = crc;
SendCode = 16; //写S70的大扇区
serialPort1.Write(SendBuf, 0, 20);
ListSendData(SendBuf, 20);
S70block = S70block + 1;
}
else
{
dispstr = "写扇区数据成功,卡号:" + cardnohex;
}
}
else if (SendCode == 7)
{
dispstr = "修改扇区密码成功,卡号:" + cardnohex;
}
break;
case 1:
dispstr = "密码认证成功,但读取扇区内容失败!卡号:" + cardnohex;
break;
case 2:
dispstr = "第0块读出,但第1、2块没读出,仅扇区内容前16个字节的数据有效!卡号:" + cardnohex;
break;
case 3:
dispstr = "第0、1块读出,但第2块没读出,仅扇区内容前32个字节的数据有效!卡号:" + cardnohex;
break;
case 8:
dispstr = "未寻到卡!";
break;
case 9:
dispstr = "两张以上卡片同时在感应区,发生冲突!";
break;
case 10:
dispstr = "无法选择激活卡片!";
break;
case 11:
dispstr = "密码装载失败,卡片序列号已知!";
break;
case 12:
dispstr = "密码认证失败,卡号:" + cardnohex;
break;
default:
dispstr = "操作卡失败,返回代码:" + buff[1].ToString("D");
break;
}
break;
case 53:
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2");
dispstr = "读M1卡扇区数据成功,卡号:" + cardnohex;
if (S70Page > 31 && S70block < 15)
{
for (int i = 6; i < len - 1; i++)
{
S70buffdata[S70buffp] = buff[i];
S70buffp=S70buffp+1;
}
byte[] SendBuf = new byte[4];
SendBuf[0] = 0x02;
SendBuf[1] = 0xB4;
SendBuf[2] = (byte)(128 + (S70Page - 32) * 16 + S70block);
SendBuf[3] =(byte)( SendBuf[1] ^ SendBuf[2]);
SendCode = 15; //读S70的大扇区
serialPort1.Write(SendBuf, 0, 4);
ListSendData(SendBuf, 4);
S70block=S70block+1;
}
else
{
string datahex = "";
for (int i = 6; i < len - 1; i++)
{
datahex = datahex + buff[i].ToString("X2") + " ";
}
textBoxM1Data.Text = datahex;
}
break;
case 54: //兼容以前的读写器
cardnohex = buff[2].ToString("X2") + buff[3].ToString("X2") + buff[4].ToString("X2") + buff[5].ToString("X2");
dispstr = "读M1卡扇区数据成功,卡号:" + cardnohex;
if (S70Page > 31 && S70block < 15)
{
for (int i = 7; i < len - 1; i++)
{
S70buffdata[S70buffp] = buff[i];
S70buffp=S70buffp+1;
}
byte[] SendBuf = new byte[4];
SendBuf[0] = 0x02;
SendBuf[1] = 0xB4;
SendBuf[2] = (byte)(128 + (S70Page - 32) * 16 + S70block);
SendBuf[3] =(byte)( SendBuf[1] ^ SendBuf[2]);
SendCode = 15; //读S70的大扇区
serialPort1.Write(SendBuf, 0, 4);
ListSendData(SendBuf, 4);
S70block=S70block+1;
}
else
{
string datahex = "";
for (int i = 7; i < len - 1; i++)
{
datahex = datahex + buff[i].ToString("X2") + " ";
}
textBoxM1Data.Text = datahex;
}
break;
}
break;
case 15: 读S70的大扇区的返回
if (buff[1] == 0)
{
for (int i = 2; i < len - 1; i++)
{
S70buffdata[S70buffp] = buff[i];
S70buffp = S70buffp + 1;
}
if (S70block > 14)
{
string datahex = "";
for (int i = 0; i < S70buffp; i++)
{
datahex = datahex + S70buffdata[i].ToString("X2") + " ";
}
textBoxM1Data.Text = datahex;
dispstr = "读S70卡扇区数据成功!";
}
if (S70block < 15)
{
byte[] SendBuf = new byte[4];
SendBuf[0] = 0x02;
SendBuf[1] = 0xB4;
SendBuf[2] = (byte)(128 + (S70Page - 32) * 16 + S70block);
SendBuf[3] = (byte)(SendBuf[1] ^ SendBuf[2]);
SendCode = 15; //读S70的大扇区
serialPort1.Write(SendBuf, 0, 4);
ListSendData(SendBuf, 4);
S70block = S70block + 1;
}
}
else { dispstr = "读S70卡扇区数据失败,错误代码" + buff[1].ToString(); }
break;
case 16: //写S70的大扇区
if (buff[1] == 0)
{
if (S70Page > 31 && S70block < 15)
{
byte[] SendBuf = new byte[20];
SendBuf[0] = 0x12;
SendBuf[1] = 0xA5;
SendBuf[2] = (byte)(128 + (S70Page - 32) * 16 + S70block);
crc = (byte)(SendBuf[1] ^ SendBuf[2]);
for (int i = 0; i < 16; i++)
{
SendBuf[3 + i] = Convert.ToByte(Convert.ToInt32(wstr.Substring((S70buffp - 1) * 2, 2), 16));
crc = (byte)(crc ^ SendBuf[3 + i]);
S70buffp = S70buffp + 1;
}
SendBuf[19] = crc;
SendCode = 16; //写S70的大扇区
serialPort1.Write(SendBuf, 0, 20);
ListSendData(SendBuf, 20);
S70block = S70block + 1;
}
else
{
dispstr = "写S70卡扇区数据成功!";
}
}
else { dispstr = "写S70卡扇区数据失败,错误代码" + buff[1].ToString(); }
break;
}
DispLabel.Text = dispstr;
}
}
private void ListSendData(byte[] sendbuff,int datalen)
{
if (listBox1.Items.Count > 50) { listBox1.Items.Clear(); }
string liststr = DateTime.Now.ToLocalTime().ToString("HH:mm:ss.fff")+" Send : ";
for (int i = 0; i < datalen; i++)
{
liststr = liststr + sendbuff[i].ToString("X2") + " ";
}
listBox1.Items.Add (liststr);
listBox1.SelectedIndex =listBox1.Items.Count -1;
}
private void button2_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!" , "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
UInt32 Deepdelay =Convert.ToUInt32( beepdelay .Value ) ;
byte[] SendBuf = new byte[5];
SendBuf[0] = 0x03;
SendBuf[1] = 0x0F;
SendBuf[2] =(byte)( Deepdelay % 256);
SendBuf[3] = (byte)(Deepdelay / 256);
SendBuf[4] = (byte)(SendBuf[1] ^ SendBuf[2] ^ SendBuf[3]);
serialPort1.Write(SendBuf,0,5) ;
SendCode = 1;
ListSendData(SendBuf, 5);
DispLabel.Text = "驱动发卡器响声的指令已发送...";
}
private void button3_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string authkey = "";
if (comboBoxauth.SelectedIndex == 0){
authkey = "00000000"; //不认证密码操作
}
else{
authkey = textBox1.Text.Trim();
if (ishexstr(authkey, 4) == false){
MessageBox.Show("请输入8位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox1.Select();
return;
}
}
string newkey = textBox2.Text.Trim();
if (ishexstr(newkey, 4) == false)
{
MessageBox.Show("请输入8位16进制新密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox2.Select();
return;
}
byte myctrlword;
if (comboBoxauth.SelectedIndex == 0)
{
myctrlword = 0x00; //控制字 0x00 表示无需密码操作任意卡; +8 表示指定卡;+16表示 带密码操作
}
else
{
myctrlword = 0x10; //控制字 0x10 表示带密码操作
}
byte[] configdata = new byte[16];
if (comboBoxinit.SelectedIndex == 0) //开启密码保护功能
{
configdata[0] = 0; //MIRROR
configdata[1] = 0; //RFUI
configdata[2] = 0; //MIRROR_PAGE
configdata[3] = (byte)(beginpage.Value); //起始保护页
configdata[4] = (byte)(errlimit.Value); //启用密码认证次数限制
if (comboBoxrw.SelectedIndex == 1) { configdata[4] =(byte)(configdata[4] + 0x80); } //开启读卡也要带密码操作
configdata[5] = 0;
configdata[6] = 0;
configdata[7] = 0;
for (int i = 0; i < 4; i++)
{
configdata[8 + i] = Convert.ToByte(Convert.ToInt32(newkey.Substring(i * 2, 2), 16));
}
configdata[12] = 0x16; //PACK
configdata[13] = 0x16; //PACK
configdata[14] = 0; //RFUI
configdata[15] = 0; //RFUI
myctrlword =(byte)(myctrlword + 7);
}
else
{
myctrlword = (byte)(myctrlword + 3);
configdata[3] = 0xff;
}
byte[] SendBuf = new byte[31];
SendBuf[0] = 0x1D; //指令长度
SendBuf[1] = 0x16; //功能码
SendBuf[2] = myctrlword;//控制位
SendBuf[3] = 0x00; //指定7个字节要操作的卡号,如7字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = 0x00;
SendBuf[8] = 0x00;
SendBuf[9] = 0x00;
for (int i = 0; i < 4; i++) { SendBuf[10 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); }
for (int i = 0; i < 16; i++)
{
SendBuf[14 + i] = configdata[i];
}
byte crc = 0;
for (int i = 1; i < 30; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[30] = crc;
SendCode = 3;
serialPort1.Write(SendBuf, 0, 31);
ListSendData(SendBuf, 31);
DispLabel.Text = "设置Ntag卡密码保护机制的指令已发送...";
}
private void button4_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (rwpages.Value > 12 || rwpages.Value < 1)
{
MessageBox.Show("每次读卡页数必须大于1,小于13!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
byte myctrlword;
string authkey = "";
if (comboBoxauth.SelectedIndex == 0)
{
authkey = "00000000"; //不认证密码操作
myctrlword = 0x00;
}
else
{
authkey = textBox1.Text.Trim();
if (ishexstr(authkey, 4) == false)
{
MessageBox.Show("请输入8位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox1.Select();
return;
}
myctrlword = 0x10;
}
byte[] SendBuf = new byte[17];
SendBuf[0] = 0x0F; //指令长度
SendBuf[1] = 0x1B; //功能码
SendBuf[2] = myctrlword;//控制位
SendBuf[3] = 0x00; //指定7个字节要操作的卡号,如7字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = 0x00;
SendBuf[8] = 0x00;
SendBuf[9] = 0x00;
for (int i = 0; i < 4; i++) { SendBuf[10 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); }
SendBuf[14] = (byte)(rwbegin.Value);
SendBuf[15] = (byte)(rwpages .Value);
byte crc = 0;
for (int i = 1; i < 16; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[16] = crc;
SendCode = 2;
serialPort1.Write(SendBuf, 0, 17);
ListSendData(SendBuf, 17);
DispLabel.Text = "读Ntag卡块数据的指令已发送...";
}
private void button7_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
private void comboBoxPort_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
serialPort1.Close();
}
catch (Exception) { }
button1.Text = "打开串口";
button1.BackColor = Color.Red;
}
private void button5_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (rwpages.Value > 11 || rwpages.Value < 1)
{
MessageBox.Show("每次写卡页数必须大于1,小于12!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
bool NotEnough=false ;
int wlen = (int)(rwpages.Value * 4);
string wstr = textBoxData.Text.Trim();
wstr = wstr.Replace(" ", "");
while (wstr.Length< wlen*2){
wstr = wstr + "0";
NotEnough = true;
}
if (ishexstr(wstr, wlen) == false)
{
MessageBox.Show("写卡数据输入错误,请输入" + (wlen*2).ToString("D") + "位16进制写卡数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxData.Select();
return;
}
if (NotEnough)
{
DialogResult result = MessageBox.Show("右边输入的写卡数据不足 " + (rwpages.Value).ToString() + " 页,是否后面补 0 写入?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No) { return; }
}
byte myctrlword;
string authkey = "";
if (comboBoxauth.SelectedIndex == 0)
{
authkey = "00000000"; //不认证密码操作
myctrlword = 0x00;
}
else
{
authkey = textBox1.Text.Trim();
if (ishexstr(authkey, 4) == false)
{
MessageBox.Show("请输入8位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox1.Select();
return;
}
myctrlword = 0x10;
}
byte[] SendBuf = new byte[100];
SendBuf[0] = (byte)(15 + wlen); //指令长度
SendBuf[1] = 0x1C; //功能码
SendBuf[2] = myctrlword;//控制位
SendBuf[3] = 0x00; //指定7个字节要操作的卡号,如7字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = 0x00;
SendBuf[8] = 0x00;
SendBuf[9] = 0x00;
for (int i = 0; i < 4; i++) { SendBuf[10 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); }
SendBuf[14] = (byte)(rwbegin.Value);
SendBuf[15] = (byte)(rwpages.Value);
for (int i = 0; i < wlen; i++)
{
SendBuf[16 + i] = Convert.ToByte(Convert.ToInt32(wstr.Substring(i * 2, 2), 16));
}
byte crc = 0;
for (int i = 1; i <=15+wlen; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[16+wlen] = crc;
SendCode = 3;
serialPort1.Write(SendBuf, 0, 17+wlen);
ListSendData(SendBuf, 17 + wlen);
DispLabel.Text = "写数据到Ntag卡块内的指令已发送...";
}
private void button6_Click(object sender, EventArgs e)
{
if (listBox1.Items.Count < 1) { return; }
string copystr;
copystr = "";
for (int i = 0; i <= listBox1.Items.Count - 1; i++)
{
copystr = copystr + (string)listBox1.Items[i] + "\r\n";
}
Clipboard.Clear();
Clipboard.SetDataObject(copystr);
MessageBox.Show("显示的数据报文已拷贝到剪切板!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void button8_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
byte[] SendBuf = new byte[3];
SendBuf[0] = 0x01;
SendBuf[1] = 0xF0;
SendBuf[2] = 0xF0;
serialPort1.Write(SendBuf, 0, 3);
SendCode = 4;
ListSendData(SendBuf, 3);
DispLabel.Text = "读取M1卡序列号的指令已发送...";
}
private void button9_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string authkey = textBoxM1Key.Text.Trim();
if (ishexstr(authkey, 6) == false)
{
MessageBox.Show("请输入12位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxM1Key.Select();
return;
}
byte[] SendBuf = new byte[16];
SendBuf[0] = 0x0E ; //指令长度
SendBuf[1] = 0x78; //功能码
SendBuf[2] = 0x17; //控制位
SendBuf[3] = 0x00; //指定4个字节要操作的卡号,如4字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = (byte)(comboBoxSector.SelectedIndex); //扇区号
SendBuf[8] = (byte)(comboBoxAuthAB.SelectedIndex); //密码认证方式,A or B
for (int i = 0; i < 6; i++) { SendBuf[9 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); } //密钥
byte crc = 0;
for (int i = 1; i <= 14; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[15] = crc;
S70block = 3;
S70Page = comboBoxSector.SelectedIndex;
S70buffp = 0;
SendCode = 5;
serialPort1.Write(SendBuf, 0, 16);
ListSendData(SendBuf, 16);
DispLabel.Text = "轻松读M1卡扇区内数据的指令已发送...";
}
private void button10_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string authkey = textBoxM1Key.Text.Trim();
if (ishexstr(authkey, 6) == false)
{
MessageBox.Show("请输入12位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxM1Key.Select();
return;
}
int wlen = 48;
if (comboBoxSector.SelectedIndex > 31) { wlen = 240; } //S70
bool NotEnough = false;
wstr = textBoxM1Data.Text.Trim();
wstr = wstr.Replace(" ", "");
while (wstr.Length < wlen*2)
{
wstr = wstr + "0";
NotEnough = true;
}
if (ishexstr(wstr, wlen) == false)
{
MessageBox.Show("写卡数据输入错误,请输入" + (wlen * 2).ToString() + "位16进制写卡数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxM1Data.Select();
return;
}
if (NotEnough)
{
DialogResult result = MessageBox.Show("右边输入的写卡数据不足,是否后面补 0 写入?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No) { return; }
}
byte[] SendBuf = new byte[64];
SendBuf[0] = 0x3E; //指令长度
SendBuf[1] = 0x69; //功能码
SendBuf[2] = 0x17; //控制位
SendBuf[3] = 0x00; //指定4个字节要操作的卡号,如4字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = (byte)(comboBoxSector.SelectedIndex); //扇区号
SendBuf[8] = (byte)(comboBoxAuthAB.SelectedIndex); //密码认证方式,A or B
for (int i = 0; i < 6; i++) { SendBuf[9 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); } //密钥
for (int i = 0; i < 48; i++)
{
SendBuf[15 + i] = Convert.ToByte(Convert.ToInt32(wstr.Substring(i * 2, 2), 16));
}
byte crc = 0;
for (int i = 1; i <= 62; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[63] = crc;
S70block = 3;
S70Page = comboBoxSector.SelectedIndex;
S70buffp = 49;
SendCode = 6;
serialPort1.Write(SendBuf, 0, 64);
ListSendData(SendBuf, 64);
DispLabel.Text = "写数据到M1卡扇区内的指令已发送...";
}
private void button11_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
MessageBox.Show("请先选择打开与发卡器相连的串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string authkey = textBoxM1Key.Text.Trim();
if (ishexstr(authkey, 6) == false)
{
MessageBox.Show("请输入12位16进制认证密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxM1Key.Select();
return;
}
string keyA = textBoxnewkeyA.Text.Trim();
if (ishexstr(keyA, 6) == false)
{
MessageBox.Show("请输入12位16进制新A密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxnewkeyA.Select();
return;
}
string ctrlword = textBoxctrlword.Text.Trim();
if (ishexstr(ctrlword, 4) == false)
{
MessageBox.Show("请输入8位16进制新控制位!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxctrlword.Select();
return;
}
string keyB = textBoxnewkeyB.Text.Trim();
if (ishexstr(keyB, 6) == false)
{
MessageBox.Show("请输入12位16进制新B密码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBoxnewkeyB.Select();
return;
}
byte[] SendBuf = new byte[33];
SendBuf[0] = 0x1F; //指令长度
SendBuf[1] = 0xF1; //功能码
SendBuf[2] = 0x17; //控制位
SendBuf[3] = 0x00; //指定4个字节要操作的卡号,如4字节全部取0表示可以操作任意卡
SendBuf[4] = 0x00;
SendBuf[5] = 0x00;
SendBuf[6] = 0x00;
SendBuf[7] = (byte)(comboBoxSector.SelectedIndex); //扇区号
SendBuf[8] = (byte)(comboBoxAuthAB.SelectedIndex); //密码认证方式,A or B
for (int i = 0; i < 6; i++) { SendBuf[9 + i] = Convert.ToByte(Convert.ToInt32(authkey.Substring(i * 2, 2), 16)); } //认证密钥
for (int i = 0; i < 6; i++) { SendBuf[15 + i] = Convert.ToByte(Convert.ToInt32(keyA.Substring(i * 2, 2), 16)); } //新A密钥
for (int i = 0; i < 4; i++) { SendBuf[21 + i] = Convert.ToByte(Convert.ToInt32(ctrlword.Substring(i * 2, 2), 16)); } //新控制码
for (int i = 0; i < 6; i++) { SendBuf[25 + i] = Convert.ToByte(Convert.ToInt32(keyB.Substring(i * 2, 2), 16)); } //新B密钥
SendBuf[31] = (byte)(comboBoxchangekey.SelectedIndex) ;
if (SendBuf[31] > 0) { SendBuf[31] = (byte)(SendBuf[31] + 1); }
byte crc = 0;
for (int i = 1; i <= 31; i++)
{
crc = (byte)(crc ^ SendBuf[i]);
}
SendBuf[32] = crc;
SendCode = 7;
serialPort1.Write(SendBuf, 0, 33);
ListSendData(SendBuf, 33);
DispLabel.Text = "修改M1卡扇区密钥的指令已发送...";
}
}
}