232COM串口通讯读写NFC卡C#示例源码

本示例使用的发卡器: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卡扇区密钥的指令已发送...";

        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

津津有味道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值