0

I have to design a software to communicate with a smart card reader ..

as a first step i want to get to receive the data from the card reader and show them in a text box which i can see instantly as it changes (to make sure that there is data has been sent)..

the data(as i used to program it with PLC) sent by card reader is an array of 256 bytes

i did perform the same approach but nothing is shown in my richtextbox..

i'd like you to take a look at my code and tell me whats wrong:

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();

        }
    }
}

i expect to get the following output in the created richtextbox as bellow .. where the whole message appears and the xxx values of each byte of the buffer array is changed according to state of the smart card reader (or in other words according to what card reader sends )...

for example(what i have been trying to do in my code above) .. while there is connection, and a card is inserted in the card reader ,the buffer[0],[1],[2]and[3] values should change instantly from 0's to 48,48,48,48 ( as sent by card reader) .. and so on..

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

instead, the box is empty ...

hope my prob. is clear .. and i really wish to find the solution here .. it's a very important matter to me .. and i have spent a lot of time trying without any success


smart card reader type : KDM9650

dsolimano
  • 8,870
  • 3
  • 48
  • 63
mhmd3210
  • 1
  • 1
  • 2
  • What is s1? Why do you not use serialPort? – PVitt May 03 '12 at 06:22
  • Are you actually receiving anything at all? Set a breakpoint on your DataReceived handler and debug from there. Not getting *any* data is a common mistake made when setting the Handshake property. When you set it to None then you have to set DtrEnable and RtsEnable to true yourself. – Hans Passant May 05 '12 at 12:30

3 Answers3

0

update

run updateTextBox() manualy (add it to 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
    }

Then run your app and, after it stops on a breakpoint check if buffer is empty or not?

Update2 Ok, try this code, and read my comments.

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(); 
        }
    }
}

your problem You have an instance of SerialPort class. The instance name is s1. You have configured it, but you try reading data from new serialPort object. Obviously there is no data there.

Serial ports details

Anton Sizikov
  • 9,105
  • 1
  • 28
  • 39
  • did it and tried other similar functions as well but it didn't work .. The port is opened and i mentioned that i manage to write data to card reader .. since i can send a card-eject sequence .. – mhmd3210 May 02 '12 at 12:29
  • I have tried that but the program never stopped .. i guess that means that the text box is never updated.. right! – mhmd3210 May 05 '12 at 06:43
  • That means that you never call updateTextBox() method. Did you add updateTextBox() call into serialPort_DataReceived()? Could you put a breakpoint in serialPort_DataReceived()? Does the programm stops in it? – Anton Sizikov May 05 '12 at 07:26
  • and please, change this in method: Form1_Load(object sender, EventArgs e) { //serialPort.DataReceived += ... s1.DataReceived += ... } – Anton Sizikov May 05 '12 at 07:29
0

You need to actually read the data in serialPort_DataReceived. You're not doing anything here. Also: There's a button1_Click event and a button1_Click_1 event. Which one is being called by button1? If the first one is not being called, the serial port isn't opened at all.

Please note in addition: The DataReceived event is called in its own thread, so before you update the UI you need to change to the UI thread using this.Invoke (WinForms) or this.Dispatcher.Invoke (WPF).

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
0

I see two problems here:

  1. you are not reading the data from the port..

  2. I think you will have issues with a delegate updating the form as it will be called from another thread.

to get you going you could add a timer and in the timer tick event read the data if there was any at the port:

    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();
        }
    }

A nother SO question just about updating forms from another thread:

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

Community
  • 1
  • 1
  • really.. what happened? did you put any break points in to see if the code was running? –  May 02 '12 at 13:20