本示例使用的发卡器: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);}}}
}