通过串行连接从智能卡读卡器接收数据(C#)

Posted

技术标签:

【中文标题】通过串行连接从智能卡读卡器接收数据(C#)【英文标题】:receiving data from smart card reader through serial connection (C#) 【发布时间】:2012-05-02 11:24:01 【问题描述】:

我必须设计一个与智能卡读卡器通信的软件..

作为第一步,我想从读卡器接收数据并将它们显示在一个文本框中,当它发生变化时我可以立即看到它(以确保已发送数据)..

读卡器发送的数据(我用PLC编程)是一个256字节的数组

我确实执行了相同的方法,但我的richtextbox 中没有显示任何内容..

我希望你看看我的代码并告诉我有什么问题:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;

namespace mycard

    public partial class Form1 : Form
    
        byte[] memo = new byte[256];
        byte[] buffer = new byte[255];

        private SerialPort serialPort = new SerialPort();

        public Form1()
        
            InitializeComponent();
        

        private void Form1_Load(object sender, EventArgs e)
        
            serialPort.DataReceived += 
                new SerialDataReceivedEventHandler(serialPort_DataReceived);
        

        //open port
        private void button1_Click(object sender, EventArgs e)
        
            if (s1.IsOpen)
            
                s1.Close();
            
            s1.Open();
        


        //Eject order which is working fine
        private void button1_Click_1(object sender, EventArgs e)
        
            byte[] data= new byte[4];

            memo[0]=0x60;
            memo[1]=0x00;
            memo[2]=0x02;
            memo[3]=0x43;
            memo[4]=0x31; //32
            memo[5]=0x10; //13

            s1.Write(memo,0,6);
        

        //close port
        private void button2_Click(object sender, EventArgs e)
        
            s1.Close();
        

        private void button3_Click(object sender, EventArgs e)
        
            txtDataReceived.Text = "\r\n";
        

        public delegate void myDelegate();
        public void updateTextBox()
        

            byte[] buffer = new byte[255];

            serialPort.Read(buffer, 0, 4);
            txtDataReceived.Text = (buffer[0].ToString() + Environment.NewLine 
                + buffer[1].ToString() + Environment.NewLine 
                + buffer[2].ToString() + Environment.NewLine 
                + buffer[3].ToString() + Environment.NewLine);

            // i have tried the following code as well but i got nothing as well
            // txtDataReceived.AppendText(serialPort.ReadExisting());
            // txtDataReceived.ScrollToCaret();

        
    

我希望在创建的 Richtextbox 中得到以下输出,如下所示 .. 其中出现了整个消息,并且缓冲区数组的每个字节的 xxx 值根据智能卡读卡器的状态(或换句话说根据读卡器发送的内容)...

例如(我在上面的代码中一直在尝试做的事情).. 当有连接并且卡插入读卡器时,缓冲区 [0]、[1]、[2] 和 [ 3] 值应立即从 0 变为 48,48,48,48(由读卡器发送).. 等等..

buffer:
[0]=xxx
[1]=xxx
[2]=xxx
[3]=xxx
[4]=xxx
[5]=xxx
[6]=xxx
...
...
...
[255]=xxx

相反,盒子是空的……

希望我的概率。很清楚..我真的很想在这里找到解决方案..这对我来说是一件非常重要的事情..我花了很多时间尝试但没有任何成功


智能卡读卡器类型:KDM9650

【问题讨论】:

什么是 s1?为什么不使用serialPort? 你真的收到什么了吗?在 DataReceived 处理程序上设置断点并从那里进行调试。设置 Handshake 属性时,不获取 any 数据是一个常见错误。当您将其设置为 None 时,您必须自己将 DtrEnable 和 RtsEnable 设置为 true。 【参考方案1】:

您需要实际读取serialPort_DataReceived 中的数据。你在这里什么都没做。另外:还有一个button1_Click 事件和一个button1_Click_1 事件。 button1 呼叫的是哪一个?如果第一个没有被调用,则串口根本没有打开。

另外请注意:DataReceived 事件在其自己的线程中调用,因此在更新 UI 之前,您需要使用 this.Invoke (WinForms) 或 this.Dispatcher.Invoke (WPF) 更改为 UI 线程。

【讨论】:

【参考方案2】:

我在这里看到两个问题:

    你没有从端口读取数据..

    我认为您会在委托更新表单时遇到问题,因为它将从另一个线程调用。

为了让您继续前进,您可以添加一个计时器,并在计时器滴答事件中读取数据(如果端口有数据):

    private void timer1_Tick(object sender, EventArgs e)
    
        if (s1.BytesToRead > 0)
        
            //write text to text box

            //e.g. maybe as a start try
            txtDataReceived.Text += s1.ReadExisting();
        
    

一个 另一个关于从另一个线程更新表单的问题:

How to update the GUI from another thread in C#?

【讨论】:

真的……发生了什么事?是否设置了断点来查看代码是否正在运行?【参考方案3】:

更新

手动运行updateTextBox()(将其添加到ButtonClick EventHandler)

public void updateTextBox()
    
        byte[] buffer = new byte[255];

        serialPort.Read(buffer, 0, 4); 
        var i = 0; //Press F9 here, it will put a breakpoint here
    

然后运行您的应用程序,并在断点处停止后检查缓冲区是否为空?

更新2 好的,试试这段代码,然后阅读我的 cmets。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;

namespace mycard

    public partial class Form1 : Form
    
        byte[] memo = new byte[256];
        byte[] buffer = new byte[255];

        //private SerialPort serialPort = new SerialPort();
        //We don't need this object. We never configure it, it's not the 
        //same object which you use to write 'eject bytes'!
        public Form1()
        
            InitializeComponent();
        

        private void Form1_Load(object sender, EventArgs e)
        
           //subscribe on data received event here. IMPORTANT: we 'listen' s1 object here!
            s1.DataReceived += 
                new SerialDataReceivedEventHandler(serialPort_DataReceived);
        

        //open port
        private void button1_Click(object sender, EventArgs e)
        
            if (s1.IsOpen)
            
                s1.Close();
            
            s1.Open();
        

        //Eject order which is working fine
        private void button1_Click_1(object sender, EventArgs e)
        
            byte[] data= new byte[4];

            memo[0]=0x60;
            memo[1]=0x00;
            memo[2]=0x02;
            memo[3]=0x43;
            memo[4]=0x31; //32
            memo[5]=0x10; //13

            s1.Write(memo,0,6);
        

        //close port
        private void button2_Click(object sender, EventArgs e)
        
            s1.Close();
        

        private void button3_Click(object sender, EventArgs e)
        
            txtDataReceived.Text = "\r\n";
        

        public void updateTextBox()
        
            byte[] buffer = new byte[255];

            //we must read from s1, not from serealPort!!!
            s1.Read(buffer, 0, 4);
            txtDataReceived.Text = (buffer[0].ToString() + Environment.NewLine 
                + buffer[1].ToString() + Environment.NewLine 
                + buffer[2].ToString() + Environment.NewLine 
                + buffer[3].ToString() + Environment.NewLine);
        

        //data received, let's read it!
        private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        
          updateTextBox(); 
        
    

您的问题 您有一个 SerialPort 类的实例。实例名称为s1。您已配置它,但您尝试从新的serialPort 对象读取数据。显然那里没有数据。

Serial ports details

【讨论】:

做了它并尝试了其他类似的功能,但它没有工作..端口已打开,我提到我设法将数据写入读卡器..因为我可以发送卡-弹出序列.. 我试过了,但是程序从来没有停止过..我猜这意味着文本框永远不会更新..对! 这意味着你永远不会调用 updateTextBox() 方法。您是否将 updateTextBox() 调用添加到 serialPort_DataReceived() 中?你能在 serialPort_DataReceived() 中设置一个断点吗?程序是否在其中停止? 请在方法中更改:Form1_Load(object sender, EventArgs e) //serialPort.DataReceived += ... s1.DataReceived += ...

以上是关于通过串行连接从智能卡读卡器接收数据(C#)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中从智能卡中读取名称和地址等基本数据?

从智能卡发送/接收数据

从Web浏览器访问智能卡读卡器?

使用 C# 从 PKI 智能卡读取证书

连接金雅拓智能卡时出现错误 6

如何通过 WMI 获取系统上的所有智能卡读卡器?