简体   繁体   中英

reading data from serial port at certain interval?

I have a magnetic card reader with serial port interface.

I used following C#.net code to send command to the card reader.

System.IO.Ports.SerialPort myport = new System.IO.Ports.Serialport("COM1", 9600, Parity.Nonek, 8, StopBits.One);
myport.Open();
// initiates the card reader to read.
myport.write("command to initiate card reader");

// Once the card is swiped it shows the read data.
MessageBox.Show(myport.ReadExisting());
myport.Close();

The above code will work well when i have some pause before Messagebox. But I don't want pause.Rather I want to initiate messagebox whenever the card is swiped.

How can we do so?

I am implementing this in user login system.

I assume you have some kind of GUI that you want to update on card swipe. I will assume you have a form with a single text box called "textBox1" and a button labelled "Start" (button1).

using System;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace SerialPortExample {
    public partial class Form1 : Form {

        SerialPort myport;

        public Form1() {
            InitializeComponent();

            myport = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
            myport.DataReceived += new SerialDataReceivedEventHandler(myport_DataReceived);
            myport.ErrorReceived += new SerialErrorReceivedEventHandler(myport_ErrorReceived);
        }

        delegate void SerialDataReceivedDelegate(object sender, SerialDataReceivedEventArgs e);
        delegate void SerialErrorReceivedDelegate(object sender, SerialErrorReceivedEventArgs e);

        void myport_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) {
            if (this.InvokeRequired) {
                this.Invoke(new SerialErrorReceivedDelegate(myport_ErrorReceived_Client), sender, e);
            } else {
                myport_ErrorReceived_Client(sender, e);
            }
        }

        void myport_ErrorReceived_Client(object sender, SerialErrorReceivedEventArgs e) {
            MessageBox.Show("Error recieved: " + e.EventType);
        }



        void myport_DataReceived(object sender, SerialDataReceivedEventArgs e) {
            if (this.InvokeRequired) {
                this.Invoke(new SerialDataReceivedDelegate(myport_DataRecieved_Client), sender, e);
            } else {
                myport_DataRecieved_Client(sender, e);
            }
        }

        void myport_DataRecieved_Client(object sender, SerialDataReceivedEventArgs e) {
            textBox1.Text = myport.ReadExisting();
        }

        private void button1_Click(object sender, EventArgs e) {
            try {
                if (myport.IsOpen) {
                    myport.Close();
                    button1.Text = "Start";
                } else {
                    myport.Open();
                    button1.Text = "Stop";
                }
            } catch (IOException ex) {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

I don't have a serial device to test this code on, but it should be correct.

Breaking it down, the important part is the method myport_DataRecieved . This method is called whenever data arrives on the serial port, ie when a card is swiped.

Other areas of interests are the Form1 constructor, where we initialize the SerialPort (but, not open it yet), and the method button1_Click where we open/close the port (and change the button's text to reflect that. We also handle exceptions, in case we can't open the port for some reason.

Edit: I've updated the answer, thanks to Hans's comment. You cannot directly access the UI controls from the data events, as they run on a different thread. I split the event methods in half, so that I could call Invoke on them, and run them in the proper context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM