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

news2024/10/6 22:20:32

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

        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1684705.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【技术实操】中标麒麟高级服务器操作系统实例分享,rsync数据同步配置方案

1.rsync介绍 rsync是一款开源的、快速的、多功能的、可实现全量及增量的本地或远程数据同步备份工具。 在守护进程模式&#xff08;daemon mode&#xff09;下&#xff0c;rsync默认监听TCP端口873&#xff0c;以原生rsync传输协议或者通过远程shell如RSH或者SSH提供文件。SS…

App Inventor 2 如何接入ChatGPT:国内访问OpenAI的最佳方式

如何接入OpenAI 由于国内无法访问OpenAI&#xff0c;KX上网可选大陆及香港&#xff08;被屏蔽&#xff09;以外才行。因此对于大多数人来说&#xff0c;想体验或使用ChatGPT就不太便利&#xff0c;不过App Inventor 2 为我们提供了相对便利的一种方式&#xff0c;即“试验性质…

快速搭建SpringMvc项目

一、什么是springMvc 1、介绍 Spring Web MVC是基于Servlet API构建的原始Web框架&#xff0c;从一开始就包含在Spring Framework中。正式名称“Spring Web MVC”来自其源模块的名称&#xff08; spring-webmvc &#xff09;&#xff0c;但它通常被称为“Spring MVC”。 在控制…

MVS net笔记和理解

文章目录 传统的方法有什么缺陷吗&#xff1f;MVSnet深度的预估 传统的方法有什么缺陷吗&#xff1f; 传统的mvs算法它对图像的光照要求相对较高&#xff0c;但是在实际中要保证照片的光照效果很好是很难的。所以传统算法对镜面反射&#xff0c;白墙这种的重建效果就比较差。 …

京准电子、NTP网络时间服务器工作原理及应用领域分析

京准电子、NTP网络时间服务器工作原理及应用领域分析 京准电子、NTP网络时间服务器工作原理及应用领域分析 Network Time Protocol&#xff08;NTP&#xff09;是一种用于在计算机网络中同步时钟的协议。它旨在确保在网络中的各个设备之间维持准确的时间。NTP的设计目标是允许…

qmt量化交易策略小白学习笔记第10期【qmt编程之获取股票订单流数据--内置Python】

qmt编程之获取股票订单流数据 qmt更加详细的教程方法&#xff0c;会持续慢慢梳理。 也可找寻博主的历史文章&#xff0c;搜索关键词查看解决方案 &#xff01; 感谢关注&#xff0c;需免费开通量化回测与咨询实盘权限&#xff0c;可以和博主联系&#xff01; 获取股票订单流…

鹧鸪云光伏业务管理软件:引领光伏行业四个信息化变革

随着全球对可再生能源的日益重视和光伏技术的快速发展&#xff0c;光伏业务管理正面临着前所未有的挑战与机遇。在这个大背景下&#xff0c;鹧鸪云光伏业务管理软件以其独特的优势&#xff0c;通过四个信息化变革&#xff0c;为光伏行业带来了前所未有的效率提升和智能化管理。…

hypermesh二次开发tcl脚本

hypermesh二次开发tcl脚本 1、tcl读csv文件,得到list,再转成二维数组2、tcl写csv文件3、hypermesh tcl根据读入的节点坐标建节点, 再显示节点号4、hypermesh tcl根据节点号建节点set5、hypermesh tcl根据节点set读取节点号&#xff0c;再根据节点号读取节点坐标&#xff0c;再将…

vue 点击复制文本到剪贴板

一、首先在vue文件的template中定义复制按钮 <div size"small" v-if"item.prop jadeCode" class"cell-container"><span>{{ scope.row.jadeCode }}</span> <button click"handleCopy(scope.row.jadeCode)" clas…

FreeRTOS_事件组_学习笔记

事件组 原文链接 事件组是一个整数&#xff0c;其中的高8位留给内核&#xff0c;只能用其他位来表示时间 每一位代表一个事件&#xff0c;且每个时间的含义由程序员决定 1为发生&#xff0c;0为未发生 一个/多个任务或ISR都能读写这些位 可以等待某一位&#xff0c;也可以等待…

详细分析Element中的Drawer(附Demo)

目录 前言1. 基本知识2. Demo2.1 基本用法2.2 不同方向2.3 自定义大小2.4 嵌入表单2.5 嵌套抽屉 3. 实战4. Element Plus&#xff08;Drawer&#xff09; 前言 对于该组件针对Vue2比较多&#xff0c;而Element Plus中的Drawer针对Vue3比较多 此处的Demo主要偏向Vue2 后续的El…

五一期间吉祥桥再创新高,抢占宴席酒市场高位

“人生过三桥&#xff0c;必喝吉祥桥”“古韵吉祥桥&#xff0c;今喜结良缘”“吉祥桥下酒香飘&#xff0c;东方韵味醉心田”…… 这个五一&#xff0c;吉祥桥酒商的朋友圈热闹起来了&#xff0c;一边刷屏式宣传自家主打的宴席产品&#xff0c;一边炫耀式的发布每天的宴席成绩…

08.CNN

文章目录 Observation 1Pooling - Max PoolingFlattenApplication&#xff1a;Playing Go使用验证集选择模型食物分类 Observation 1 Pooling - Max Pooling Pooling主要为了降低运算量&#xff0c;现在一般不用了&#xff0c;全convolution Flatten Application&#xff1a;P…

一文了解安卓内存抖动

目录 目录一、什么是内存抖动&#xff1f;1.1 Android里的内存抖动1.2 如何直观查看这种现象1.3 内存抖动带来的风险 二、如何避免内存抖动 目录 一、什么是内存抖动&#xff1f; 在程序里&#xff0c;每创建一个对象&#xff0c;就会有一块内存分配给它&#xff0c;每分配一…

使用 RisingWave 和 Redash 处理和可视化实时数据

在创建流处理管道时&#xff0c;需要两个关键组件&#xff1a;一个用于处理和转换数据&#xff0c;一个用于数据可视化。RisingWave 和 Redash 就提供了一个优秀的解决方案。 RisingWave 是一个支持实时数据处理的分布式 SQL 流数据库。它提供增量更新的物化视图&#xff0c;使…

【MySQL精通之路】MySQL8.0新增功能-原子DDL语句支持

太长不看系列&#xff1a; 本文一句话总结&#xff0c;MySQL8.0支持多条DDL语句执行时的原子性了&#xff08;仅限Innodb&#xff09; 本文属于下面这篇博客的子博客&#xff1a; 【MySQL精通之路】MySQL8.0官方文档-新增功能 1.意义描述 MySQL 8.0支持原子数据定义语言&…

实用的TypeScript开发工具

1、根据接口数据自动定义类型变量&#xff1a;https://wulunyi.github.io/typeof-sjsonc-web/build/index.html ……&#xff08;持续更新中&#xff09;

Vue 离线地图实现

效果图&#xff1a; 一、获取市的地图数据 DataV.geoAtlas 获取市地图数据 点击地图缩放至想要的市区域&#xff0c;通过右侧的链接打开网址&#xff0c;复制json数据。 二、获取镇地图数据 选择你想要的镇数据&#xff0c;点击下载 选择级别&#xff08;清晰度&#xff09…

关闭以及启动ubuntu图形界面

关闭以及启动ubuntu图形界面 文章目录 关闭以及启动ubuntu图形界面1. 关闭图形界面2. 打开图形界面 如果你误杀了Xorg进程&#xff0c;需要重新启动图形界面&#xff0c;可以按照以下步骤操作&#xff1a; 1. 关闭图形界面 查看当前启动的图形界面&#xff1a; 使用下面命令…

【linux系统学习教程 Day03】网络安全之Linux系统学习教程,用户和用户组管理,创建用户,删除用户,创建组,删除组....

1.7 用户和用户组管理 1.7.1 用户管理 1-1 创建用户 #创建用户 useradd #创建一个用户 例子1&#xff1a;useradd test1 #创建用户 useradd #创建一个用户 例子1&#xff1a;useradd dilnur 1-2 设置密码 passwd 例子1&#xff1a;passwd dilnur #用root用户给…