本示例使用的发卡器:EM4305 EM4469 ISO11784/85协议125K低频FXD-B动物标签读写发卡器-淘宝网 (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.Runtime.InteropServices; //调用动态库一定要加入这个引用
namespace FDX_B
{
public partial class Form1 : Form
{
//------------------------------------------------------------------------------------------------------------------------------------------------------
//外部函数声明:让设备发出声响
[DllImport("OUR_IDR.dll", EntryPoint = "idr_beep", CallingConvention = CallingConvention.StdCall)]
static extern byte idr_beep(UInt32 xms);//xms单位为毫秒
//------------------------------------------------------------------------------------------------------------------------------------------------------
//读取设备编号,可做为软件加密狗用,也可以根据此编号在公司网站上查询保修期限
[DllImport("OUR_IDR.dll", EntryPoint = "pcdgetdevicenumber", CallingConvention = CallingConvention.StdCall)]
static extern byte pcdgetdevicenumber(byte[] devicenumber);//devicenumber用于返回编号
//------------------------------------------------------------------------------------------------------------------------------------------------------
//EM4205/4305/4469/4569卡读卡
[DllImport("OUR_IDR.dll", EntryPoint = "em4305_read", CallingConvention = CallingConvention.StdCall)]
public static extern byte em4305_read(byte ctrlword, byte[] seria, byte[] key, byte[] blockflag, byte[] readdata);
//------------------------------------------------------------------------------------------------------------------------------------------------------
//EM4205/4305/4469/4569卡写卡
[DllImport("OUR_IDR.dll", EntryPoint = "em4305_write", CallingConvention = CallingConvention.StdCall)]
public static extern byte em4305_write(byte ctrlword, byte[] seria, byte[] key, byte[] blockflag, byte[] writedata);
//------------------------------------------------------------------------------------------------------------------------------------------------------
//EM4205/4305/4469/4569卡锁定块
[DllImport("OUR_IDR.dll", EntryPoint = "em4305_lock", CallingConvention = CallingConvention.StdCall)]
public static extern byte em4305_lock(byte ctrlword, byte[] seria, byte[] key, byte[] blockflag);
//------------------------------------------------------------------------------------------------------------------------------------------------------
//T5557卡读卡
[DllImport("OUR_IDR.dll", EntryPoint = "t5557_read", CallingConvention = CallingConvention.StdCall)]
public static extern byte t5557_read(byte ctrlword, byte[] seria, byte[] key, byte[] blockflag, byte[] readdata);
//------------------------------------------------------------------------------------------------------------------------------------------------------
//T5557卡写卡
[DllImport("OUR_IDR.dll", EntryPoint = "t5557_write", CallingConvention = CallingConvention.StdCall)]
public static extern byte t5557_write(byte ctrlword, byte[] seria, byte[] key, byte[] blockflag, byte[] writedata);
public Form1()
{
InitializeComponent();
}
private void MessageErrInf(byte Errcode)
{
switch (Errcode)
{
case 1:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",卡放得远 或 需要密码才能写卡 或 块已锁定!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 2:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",本卡尚未开启密码功能,函数myctrlword中无需加入NEEDKEY", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 3:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",需要密码才能读卡,函数myctrlword要加入NEEDKEY", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 4:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",卡放得远 或 需要密码才能读卡!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 5:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",密码错误!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 8:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",操作失败,请将卡放在读卡器的感应区!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 12:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",卡放得远 或 密码错误!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 21:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",没有动态库!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 22:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",动态库或驱动程序异常!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 23:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",驱动程序错误或发卡器尚未安装!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 24:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",操作超时,一般是动态库没有反映!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 25:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",发送字数不够!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 28:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",输入错误,可能是启用卡号密码保护而没在页面左上角选择带密码操作!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
default:
MessageBox.Show("错误代码:" + Errcode.ToString() + ",未知的错误信息,错误代码:" + Errcode.ToString(), "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}
private ushort GetCrc16Ccitt(byte[] bytes) //计算crc16ccitt校验码
{
ushort crc = 0x0000;
int i, j;
for (j = 0; j < bytes.Length; j++)
{
crc ^= bytes[j];
for (i = 0; i < 8; i++)
{
if ((crc & 0x0001) > 0)
{
crc = (ushort)((crc >> 1) ^ 0x8408);
}
else { crc = (ushort)(crc >> 1); }
}
}
return crc;
}
private ushort checkcrc16citt(byte[] bytes) // 检测crc16ccitt校验
{
ushort crc = 0x0000;
int i, j;
for (j = 1; j <= 10; j++)
{
crc ^= bytes[j];
for (i = 0; i < 8; i++)
{
if ((crc & 0x0001) > 0)
{
crc = (ushort)((crc >> 1) ^ 0x8408);
}
else { crc = (ushort)(crc >> 1); }
}
}
return crc;
}
private Boolean checkgetbitinf(string bitstr, byte[] info) //检测是否有效的FDX-B协议信息
{
for (int i = 0; i < 14; i++)
{
string thisbit = bitstr.Substring((i + 1) * 9 - 9, 9);
if (thisbit.Substring(0, 1) == "1")
{
info[13 - i] =(byte) Convert.ToInt16(thisbit.Substring(1, 8),2);
}
else { return false; };
}
ushort crcitt = checkcrc16citt(info);
if (crcitt == 0)
{
return true;
}
else { return false; }
}
private void button1_Click(object sender, EventArgs e)
{
byte status; //存放返回值
int j;
byte myctrlword = 0x00; //控制字
byte[] oldpicckey = new byte[4]; //密码
byte[] mypiccserial = new byte[4]; //卡序列号
byte[] mypiccdata = new byte[70]; //读卡数据缓冲:卡无线转输分频比、卡内容长度(字节数),及最多返回12个块的数据
byte[] mypiccblockflag = new byte[2]; //指定读哪一块
string bitstr;
textBox1.Text = "0000";
textBox2.Text = "000000000000";
textBox3.Text = "00000";
textBox4.Text = "00000000";
mypiccblockflag[0] = 224;
mypiccblockflag[1] = 1;
status = em4305_read(myctrlword, mypiccserial, oldpicckey, mypiccblockflag, mypiccdata);
if (status == 0)
{
idr_beep(30);
string blockdata = "";
for (int i = 0; i < mypiccdata[1]; i++)
{
bitstr ="00000000"+ Convert.ToString(mypiccdata[2 + i], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
blockdata =bitstr+ blockdata;
}
byte[] info = new byte[14];
if (checkgetbitinf(blockdata, info))
{
string Serialnumberbit = "";
bitstr = "00000000" + Convert.ToString(info[1], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Serialnumberbit = bitstr + Serialnumberbit;
bitstr = "00000000" + Convert.ToString(info[2], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Serialnumberbit = bitstr + Serialnumberbit;
bitstr = "00000000" + Convert.ToString(info[3], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Serialnumberbit = bitstr + Serialnumberbit;
bitstr = "00000000" + Convert.ToString(info[4], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Serialnumberbit = bitstr + Serialnumberbit;
bitstr = "00000000" + Convert.ToString(info[5], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
string conutrybit = "";
conutrybit = bitstr.Substring(0, 2);
bitstr = bitstr.Substring(bitstr.Length - 6);
Serialnumberbit = bitstr + Serialnumberbit;
Int64 SerialnumberId = Convert.ToInt64(Serialnumberbit, 2);
textBox2.Text = SerialnumberId.ToString("D12");
bitstr = "00000000" + Convert.ToString(info[6], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
conutrybit = bitstr + conutrybit;
Int16 conutryid = Convert.ToInt16(conutrybit, 2);
textBox1.Text = conutryid.ToString("D4");
bitstr = "00000000" + Convert.ToString(info[7], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
if (bitstr.Substring(7, 1) == "1") { checkBox3.Checked = true; } else { checkBox3.Checked = false; }
string Reservedbit = bitstr.Substring(0, 7);
bitstr = "00000000" + Convert.ToString(info[8], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
if (bitstr.Substring(0, 1) == "1") { checkBox4.Checked = true; } else { checkBox4.Checked = false; }
Reservedbit = bitstr.Substring(1, 7) + Reservedbit;
Int16 Reserved = Convert.ToInt16(Reservedbit, 2);
textBox3.Text = Reserved.ToString("D5");
string Extensionbit = "";
bitstr = "00000000" + Convert.ToString(info[11], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Extensionbit = bitstr + Extensionbit;
bitstr = "00000000" + Convert.ToString(info[12], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Extensionbit = bitstr + Extensionbit;
bitstr = "00000000" + Convert.ToString(info[13], 2);
bitstr = bitstr.Substring(bitstr.Length - 8);
Extensionbit = bitstr + Extensionbit;
Int32 Extension = Convert.ToInt32(Extensionbit, 2);
textBox4.Text = Extension.ToString("D8");
}
else
{
MessageBox.Show("不是有效的FDX-B协议标签!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else { MessageErrInf(status); }
}
private void button2_Click(object sender, EventArgs e)
{
Int16 conutryid = Convert.ToInt16(textBox1.Text.Trim());
Int64 SerialnumberId = Convert.ToInt64(textBox2.Text.Trim());
Int16 Reserved = Convert.ToInt16(textBox3.Text.Trim());
Int32 Extension = Convert.ToInt32(textBox4.Text.Trim());
if (conutryid > 1023){
MessageBox.Show("Country国家代码的取值范围是:0~1023!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox1.SelectionStart = 0;
textBox1.SelectionLength = textBox1.Text.Trim().Length;
textBox1.Select();
return;
}
if (SerialnumberId > 274877906943)
{
MessageBox.Show("SerialNumber序列号的取值范围是:0~274877906943!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox2.SelectionStart = 0;
textBox2.SelectionLength = textBox2.Text.Trim().Length;
textBox2.Select();
return;
}
if (Reserved > 16383)
{
MessageBox.Show("Reserved保留信息的取值范围是:0~16383!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox3.SelectionStart = 0;
textBox3.SelectionLength = textBox3.Text.Trim().Length;
textBox3.Select();
return;
}
if (Extension > 16777215)
{
MessageBox.Show("Extension扩展信息的取值范围是:0~16777215!", "示例提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
textBox4.SelectionStart = 0;
textBox4.SelectionLength = textBox4.Text.Trim().Length;
textBox4.Select();
return;
}
string Extensionbit = "000000000000000000000000"+Convert.ToString(Extension, 2);
Extensionbit = Extensionbit.Substring(Extensionbit.Length - 24);
string Reservedbit = "00000000000000" + Convert.ToString(Reserved, 2);
Reservedbit = Reservedbit.Substring(Reservedbit.Length - 14);
if (checkBox4.Checked) { Reservedbit = "1" + Reservedbit; } else { Reservedbit = "0" + Reservedbit; }
if (checkBox3.Checked) { Reservedbit = Reservedbit+"1"; } else { Reservedbit = Reservedbit+"0"; }
string conutrybit = "0000000000" + Convert.ToString(conutryid, 2);
conutrybit = conutrybit.Substring(conutrybit.Length - 10);
string Serialnumberbit = "00000000000000000000000000000000000000" + Convert.ToString(SerialnumberId, 2);
Serialnumberbit = Serialnumberbit.Substring(Serialnumberbit.Length - 38);
string fdxbitstr = "10000000000"; //前导码
fdxbitstr = "1" + Serialnumberbit.Substring(30, 8) + fdxbitstr;
fdxbitstr = "1" + Serialnumberbit.Substring(22, 8) + fdxbitstr;
fdxbitstr = "1" + Serialnumberbit.Substring(14, 8) + fdxbitstr;
fdxbitstr = "1" + Serialnumberbit.Substring(6, 8) + fdxbitstr;
fdxbitstr = "1" + conutrybit.Substring(8, 2) + Serialnumberbit.Substring(0, 6) + fdxbitstr;
fdxbitstr = "1" + conutrybit.Substring(0, 8) + fdxbitstr;
fdxbitstr = "1" + Reservedbit.Substring(8, 8) + fdxbitstr;
fdxbitstr = "1" + Reservedbit.Substring(0, 8) + fdxbitstr;
byte[] info = new byte[8];
for (int i = 0; i < 8; i++)
{
string thisbit = fdxbitstr.Substring((i + 1) * 9 - 9, 9);
if (thisbit.Substring(0, 1) == "1")
{
info[7 - i] = (byte)Convert.ToInt16(thisbit.Substring(1, 8), 2);
}
}
ushort crc16ccitt = GetCrc16Ccitt(info);
string crcbit = "0000000000000000" + Convert.ToString(crc16ccitt, 2);
crcbit = crcbit.Substring(crcbit.Length - 16);
fdxbitstr = "1" + crcbit.Substring(8, 8) + fdxbitstr;
fdxbitstr = "1" + crcbit.Substring(0, 8) + fdxbitstr;
fdxbitstr = "1" + Extensionbit.Substring(16, 8) + fdxbitstr;
fdxbitstr = "1" + Extensionbit.Substring(8, 8) + fdxbitstr;
fdxbitstr = "1" + Extensionbit.Substring(0, 8) + fdxbitstr;
byte[] writebuf = new byte[16];
for (int i = 0; i < 16; i++)
{
string thisbit = fdxbitstr.Substring((i + 1) * 8 - 8, 8);
writebuf[15 - i] = (byte)Convert.ToInt16(thisbit, 2);
}
byte status; //存放返回值
byte myctrlword = 0x00; //控制字
byte[] oldpicckey = new byte[4]; //密码
byte[] mypiccserial = new byte[4]; //卡序列号
byte[] mypiccblockflag = new byte[2]; //指定读哪一块
mypiccblockflag[0] = 224;
mypiccblockflag[1] = 1;
status = em4305_write(myctrlword, mypiccserial, oldpicckey, mypiccblockflag, writebuf);
if (status == 0)
{
if (checkBox2.Checked){
em4305_lock(myctrlword, mypiccserial, oldpicckey, mypiccblockflag);
}
string seriaStr = "";
for (int i = 0; i < 4; i++)
{
seriaStr = seriaStr + mypiccserial[i].ToString("X2");
}
idr_beep(30);
MessageBox.Show("卡号:" + seriaStr + "写FDX-B协议标签成功!", "提示:", MessageBoxButtons.OK , MessageBoxIcon.Information );
if (checkBox1.Checked)
{
SerialnumberId = SerialnumberId + 1;
textBox2.Text = SerialnumberId.ToString("D12");
}
}
else { MessageErrInf(status); }
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8)
{
e.Handled = true;
}
else { e.Handled = false; }
}
private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8)
{
e.Handled = true;
}
else { e.Handled = false; }
}
private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8)
{
e.Handled = true;
}
else { e.Handled = false; }
}
private void textBox4_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8)
{
e.Handled = true;
}
else { e.Handled = false; }
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked)
{
if (MessageBox.Show("选择写卡成功后锁定保护将不能再次更改标签信息,确定要启动保护功能吗!", "提示:", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
{
checkBox2.Checked = false;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
byte status = idr_beep(50);
if(status!=0){
MessageErrInf(status);
}
}
}
}