Click here to Skip to main content
14,332,889 members
Rate this:
Please Sign up or sign in to vote.
Hi guys, i wrote a code about serial port communication and i wanna use timer because i i should read the sentdata continuously without missing any data.Read and write data are in the same code.I open interface 2 times and after clicking start button , i clicked send button.The data is starting to send and at the same interface the data is receiving also i set up the received time interval is 250 and the send time interval is 500 but i still miss a data.Also sometimes there can be a lag in code.Where is my fault ?Probably there is a something wrong in while but I'm not sure.I m waiting for your answers.Sorry for my English.

What I have tried:

namespace SeriPort
{

    public partial class Form1 : Form
    {

        int i = 0;
        int offsetIndex = 0;
        byte[] sentData = new byte[10];
        byte[] message = new byte[10];
        byte[] byte_buffer = new byte[2048];
        int receivedValidMessageCounter = 0;
        string trial = "";
        int Freq = 0;
        
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

        }
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {


            int bufferSize = serialPort1.BytesToRead;
            if (bufferSize > 0 && offsetIndex + 10 < byte_buffer.Length)
            {
                serialPort1.Read(byte_buffer, offsetIndex, message.Length);
                offsetIndex = offsetIndex + message.Length;//Read Index
                                                          
            }
            else
            {
                //int a = 0;
            }

        }
        private void timer1_Tick(object sender, EventArgs e)
        {

            if (serialPort1.IsOpen)
            {
                sentData[0] = 0xF1;

                sentData[1] ++;
                sentData[2] = 70;
                sentData[3] = 11;
                sentData[4] = 85;
                sentData[5] = 74;
                sentData[6] = 11;
                sentData[7] = 10;
                sentData[8] = 154;
                sentData[9] = CalCheckSum(sentData);

                serialPort1.Write(sentData, 0, 10);

            }
            else { }


        }
        private void timer2_Tick(object sender, EventArgs e)
        {


            try
            {
                //serialPort1.ReadTimeout = 10;
                timerReceive.Stop();
                while (IsReceivedMessageValid()) // burada headerı ve byte ı kontrol ettiren fonksioyon yaz
                {

                    message[0] = byte_buffer[i];
                    message[1] = byte_buffer[i + 1];
                    message[2] = byte_buffer[i + 2];
                    message[3] = byte_buffer[i + 3];
                    message[4] = byte_buffer[i + 4];
                    message[5] = byte_buffer[i + 5];
                    message[6] = byte_buffer[i + 6];
                    message[7] = byte_buffer[i + 7];
                    message[8] = byte_buffer[i + 8];
                    message[9] = byte_buffer[i + 9];//crc
                    Freq++;
                    receivedValidMessageCounter++;

                    for (int t = 0; t < 10; t++)
                    {
                        trial += message[t].ToString() + "\t";

                        i++;
                    }

                    trial += "\r\n";
                    Freq = 1000 * Freq / timerReceive.Interval;

                }
                textBox2.Text = trial;
                //Application.DoEvents();

                this.Text = "Frequency: " + Freq.ToString() + "Hz" + "- TotalDataReceived:" + receivedValidMessageCounter.ToString();
                Freq = 0;
                //timerReceive.Start();
                timerReceive.Start();
            }

            catch { }

        }

        private bool IsReceivedMessageValid()
        {
            //int bufferSize = serialPort1.BytesToRead;
            if (byte_buffer[i] == 0xF1)
            {
                byte control = 0x00;
                for (int l = 0; l < 9; l++)
                {
                    control ^= byte_buffer[i + l];
                }
                if (control == byte_buffer[i + 9])
                    return true;

            }
            i++;
            return false;





            // header crc kontrolu
            // mesaj byte sayısı kontrolu
            //

        }

        private void Form1_Load(object sender, EventArgs e)
        {


            string[] portlar = SerialPort.GetPortNames();
            comboBox1.Items.AddRange(portlar);

            textBox1.Text = Properties.Settings.Default.textbox;
            //comboBox1.Text = Properties.Settings.Default.combobox;

            if (comboBox1.Items.Contains(Properties.Settings.Default.combobox))
                comboBox1.SelectedIndex = comboBox1.Items.IndexOf(Properties.Settings.Default.combobox);
        }
        bool c = false;

        private void button1_Click(object sender, EventArgs e)
        {

            if (c)
            {
                c = false;

                button1.Text = "Start";
                textBox1.ReadOnly = false;
                comboBox1.Enabled = true;
                label9.Text = "Paused";
                label9.ForeColor = Color.Red;
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();

                }
                else { }
                timerSend.Stop();
                timerReceive.Stop();
            }
            else
            {
                c = true;
                try
                {

                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(textBox1.Text);
                    serialPort1.DataBits = 8;
                    serialPort1.Parity = Parity.None;
                    serialPort1.StopBits = StopBits.One;
                    if (!serialPort1.IsOpen)
                    {
                        serialPort1.Open();
                        // serialPort1.ReadTimeout = 1200;

                    }

                    else
                    {

                    }

                    button1.Text = "Stop";
                    textBox1.ReadOnly = true;
                    comboBox1.Enabled = false;
                    label9.Text = "Sending...";
                    label9.ForeColor = Color.Green;
                    timerReceive.Start();



                }
                catch
                {
                    MessageBox.Show("Please enter number", "Error");
                    c = false;
                }
            }
        }
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (checkBox1.Checked)
            {

                Properties.Settings.Default.textbox = textBox1.Text;
                Properties.Settings.Default.combobox = comboBox1.Text;
                Properties.Settings.Default.Save();
            }
            else { }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            timerSend.Start();

        }
        static private byte CalCheckSum(byte[] byteBuffer)
        {
            byte _CheckSumByte = 0x00;
            for (int a = 0; a < byteBuffer.Length - 1; a++) //CheckSumı headerdan itibaren kontrol ettir!
                _CheckSumByte ^= byteBuffer[a];

            return _CheckSumByte;
        }



    }
}
Posted
Updated 22-Jul-19 17:52pm
Rate this:
Please Sign up or sign in to vote.

Solution 2

Why are you using a timer for reading? Use the DataReceived[^] event handler instead. See, for instance Serial Comms in C# for Beginners[^].
   
Comments
TheRealSteveJudge 23-Jul-19 4:02am
   
Good advice! 5*
CPallini 23-Jul-19 5:00am
   
Thank you, Steve.
JohnOz 23-Jul-19 8:05am
   
My director said me i should use timer ,actually also i dont know why i should use timer:(
CPallini 23-Jul-19 8:25am
   
You shouldn't.
Richard MacCutchan 25-Jul-19 4:46am
   
Using timers is a bad idea, as you have no idea how fast or slow the serial port will actually operate. Use event handlers as CPallini suggests so you get notified when the system has some data for you to read.
Rate this:
Please Sign up or sign in to vote.

Solution 1

The first and most obvious thing that I see is the two timer tick event handlers:

timer1_Tick

timer2_Tick


Inside those timer handlers you need to stop the timer each time the timer code is running. If you don't, then the timer event handler can be entered again on another thread and your data can get all out of sync, which is probably why you're experiencing missing reads and/or writes.

At the top of the code (in each timer event handler) as soon you enter the handler you want to
private void timer1_Tick(object sender, EventArgs e)
 {
      timer1.Stop();
      try{
         // all your other code here
       }
      finally{
       // finally code will run even if there is an exception so you 
       // want to insure the timer gets started again, so you put it in this 
       /// finally section
       timer1.Start();
      }
}


This will probably fix your code. But there may be other problems. This is just the one thing that I noticed immediately that must be changed to get it to work.
:)
   
Comments
JohnOz 23-Jul-19 8:05am
   
Thanks my man you are my hero :)
raddevus 23-Jul-19 8:25am
   
I have waited so long to be a hero, but I knew I'd make it one day. :D Glad it helped.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100