Click here to Skip to main content
15,867,771 members
Please Sign up or sign in to vote.
4.00/5 (1 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

Why are you using a timer for reading? Use the DataReceived[^] event handler instead. See, for instance Serial Comms in C# for Beginners[^].
 
Share this answer
 
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.
The first and most obvious thing that I see is the two timer tick event handlers:

C#
timer1_Tick

C#
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
C#
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.
:)
 
Share this answer
 
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, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900