在多个表单上使用相同的串口实例 [英] Using same serial port instances on multiple forms

查看:44
本文介绍了在多个表单上使用相同的串口实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 C# 很陌生,我正在尝试将一个通用串行端口用于 3 种不同的表单:Form2、Form3、Form4

I am quite new to C# and I am trying to use one common serial port for 3 different forms: Form2, Form3, Form4

Form1.cs 不需要,因为它只需要启动其他表单的程序.基本上,所有3种形式都必须同时从同一个串口接收数据.我面临的问题是只有一种形式可以从串口接收数据,而其他两种形式则不能.

Form1.cs isn't needed for this because it's just needed to launch the programs of the other forms. Basically, all 3 forms must receive data from the same serial port at the same time. The problem I am facing is that only one form can receive data from the serial port, but the other two forms can't.

我发现了一个类似的问题:

I found a question similar to this:

在两种不同形式上使用相同的串口数据接收事件

那个问题和我的一样吗?如果是,我可以知道我应该将示例代码放在我代码的上述链接中的什么位置吗?

Is that problem similar to mine? If yes, can I know where should I place the sample code in the aforementioned link in my code?

有人可以帮忙吗?提前致谢!

Can someone please help with this? Thanks in advance!

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 f2 = new Form2();
        f2.Show();
        Form3 f3 = new Form3();
        f3.Show();
        Form4 f4 = new Form4();
        f4.Show();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        this.Close();
    }
}

表格 2:

public partial class Form2 : Form
{
    GMapControl MainMap = new GMapControl();
    //Initialise data type for latituide and longitude
    double lat, lng;
    //Initialise customise marker (plane maker). Declared as m.
    GMapMarkerImage m = new GMapMarkerImage(new PointLatLng());
    GMapOverlay overlayOne;

    public Form2()
    {
        InitializeComponent();

        SuspendLayout();

        overlayOne = new GMapOverlay(MainMap, "OverlayOne");
        MainMap.MapProvider = GMapProviders.YahooMap;

        MainMap.SetCurrentPositionByKeywords("Singapore");
        MainMap.MinZoom = 1;
        MainMap.MaxZoom = 24;
        MainMap.Zoom = 13;
        MainMap.CanDragMap = true;
        MainMap.DragButton = MouseButtons.Left;
        MainMap.Dock = DockStyle.Fill;
        MainMap.Manager.Mode = AccessMode.ServerAndCache;

        Controls.Add(MainMap);
        ResumeLayout(true);


    }

    public void button1_Click(object sender, EventArgs e)
    {
        if (!serialPort1.IsOpen)    //if serial port is not open
            try
            {
                serialPort1.Open(); //Open Serial Port
                if (lat != 0 && lng != 0)  //Display marker only when GPS has receive data
                {
                    overlayOne.Markers.Add(m);          //Add marker on the position given to the overlayOne layer
                    MainMap.Overlays.Add(overlayOne);   //Add overlayOne layer to the MainMap layer
                }
            }
            catch
            {
                //A message box will display this message, informing user either a wrong port has been chosen, or have not been plugged in.
                MessageBox.Show("There was an error. Please make sure that the correct port was selected, and the device, plugged in.");
            }

    }

    public void button2_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)                // if Serial Port is open
        {
            serialPort1.Close();               //Close Serial
            overlayOne.Markers.Remove(m);
        }
    }

    //When microsoft visual studio receive data
    public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        this.Invoke(new EventHandler(DoUpdate));    //for function DoUpdate

        //Pause Microsoft Visual Studio for 100 milliseconds from receiving data, 
        //to ensure serialPort can be close successfully
        Thread.Sleep(100);
    }

    //Function for updating data. Declared as DoUpdate.
    public void DoUpdate(object sender, EventArgs e)
    {
        string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function

        lat = Convert.ToDouble(c[9]);               //Convert Latitude string data to double data
        lng = Convert.ToDouble(c[10]);              //Convert Longitude string data to double data

        //Input lat and lng data in m.
        //Updating the position of the marker
        m.Position = new PointLatLng(lat, lng);

    }
}

表格 3:

    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (!serialPort1.IsOpen)    //if serial port is not open
                try
                {
                    serialPort1.Open(); //Open Serial Port

                    //Enable blocks to have colour
                    // ...
                }
                catch
                {
                    //A message box will display this message, informing user either a wrong port has been chosen, or have not been plugged in.
                    MessageBox.Show("There was an error. Please make sure that the correct port was selected, and the device, plugged in.");
                }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)                // if serial port is open
            {
                serialPort1.Close();                   // Close serial Port 

                //Clear data in textboxes
                FrontSonar.Text = "    ";
                LeftSonar.Text = "   ";
                RightSonar.Text = "    ";

                //Clear colours in the boxes
                // ...
            }
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) //When microsoft visual studio receive data
        {
            this.Invoke(new EventHandler(DoUpdate1)); //To update and ensure sonar data infront of UAV can be displayed without error
            this.Invoke(new EventHandler(DoUpdate2)); //To update and ensure sonar data left side of UAV can be displayed without error
            this.Invoke(new EventHandler(DoUpdate3)); //To update and ensure sonar data on the right side of UAV can be displayed without error

            Thread.Sleep(100);
        }

        private void DoUpdate1(object s, EventArgs e) //Display for Sonar infront of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            FrontSonar.Text = c[1] + "\n";
            double d = Convert.ToDouble(c[1]);

            if (d > 500)
            {
                //Fill blocks with green
                this.rectangleShape1.FillColor = System.Drawing.Color.Green;
                this.rectangleShape2.FillColor = System.Drawing.Color.Green;
                this.rectangleShape3.FillColor = System.Drawing.Color.Green;
            }
            else
                if (d > 400 && d <= 500)
                {
                    //Fill block with Orange colour
                    this.rectangleShape1.FillColor = System.Drawing.Color.Orange;
                    this.rectangleShape2.FillColor = System.Drawing.Color.Orange;

                    //Fill block with Lavender colour
                    this.rectangleShape3.FillColor = System.Drawing.Color.Lavender;
                }
                else
                    if (d <= 400)
                    {
                        //Fill block with red colour
                        this.rectangleShape1.FillColor = System.Drawing.Color.Red;

                        //Fill block with Lavender colour
                        this.rectangleShape2.FillColor = System.Drawing.Color.Lavender;
                        this.rectangleShape3.FillColor = System.Drawing.Color.Lavender;
                    }

        }


        private void DoUpdate2(object s, EventArgs e) //Display for Sonar on the left side of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            // ....

        }

        private void DoUpdate3(object s, EventArgs e) //Display for Sonar on the right side of UAV
        {
            string[] c = serialPort1.ReadLine().Split(',');  //Stored data seperately by using array & using the Split() function
            // ...
        }    
    }

Form4:(仍在进行中)

public partial class Form4 : Form
{
    public Form4()
    {
        InitializeComponent();
    }
}

推荐答案

是的,你可以.以下是实现这一目标的关键点:

Yes, you can. Below is key points to achieve this:

  1. 打开串口一次,你的方法if (!port.IsOpened) { port.Open();} 是对的,在静态方法中提取它并以每种形式(f2,f3,f4)调用以避免复制/粘贴此代码片段.

  1. Open serial port once, your approach if (!port.IsOpened) { port.Open(); } is right, extract this in a static method and call in each form (f2, f3, f4) to avoid copy/paste of this code snippet.

serialPort 变量应该在所有三种形式之间共享,因此所有形式都可以访问相同的打开和初始化的端口实例.考虑到您提供的代码,创建并初始化,在Form1 类中打开端口,然后通过构造函数注入将serialPort 的初始化实例传递给其他表单类,基本上添加SerialPort port 构造函数Form2,3,4 类的参数,然后:

serialPort variable should be shared across all three forms, so the same opened and initialized port instance would be accessible for all forms. Considering code you've provided, create and initialize, open port in Form1 class, then pass initialized instance of serialPort into other form classes via constructor injection, basically add SerialPort port constructor parameter for Form2,3,4 classes and then:

// renamed button1_Click
private void OnSetup(object sender, EventArgs e)
{
    this.port = new SerialPort(...);
    // TODO: initialize port

    Form2 f2 = new Form2(this.port);
    f2.Show();
    Form3 f3 = new Form3(this.port);
    f3.Show();
    Form4 f4 = new Form4(this.port);
    f4.Show();
}

  • 然后在每个表单构造函数中订阅 serialPort.DataReceived 事件就可以了.

    public Form2(SerialPort port)
    {
         port.DataReceived += ...
    }
    

  • 一些建议,

    • 赋予变量和方法更具描述性的名称,而不是form1form2cdbutton2_Click
    • 避免幻数,提取变量中的常量并给出描述性名称,例如400500多次出现的幻数,不清楚它们是什么
    • 在对代码的评论中,您说Pause Microsoft Visual Studio...microsoft Visual Studio 接收数据...,这是不正确的,正在执行您的应用程序(但不是 Visual Studio)将暂停,而 Thread.Sleep() 并且您的应用程序将收到传入的串行端口数据,Visual Studio 只是一个开发环境,在这种情况下不涉及端口直接沟通.
    • Give variables and methods more descriptive names rather than form1, form2, c, d, button2_Click
    • Avoid magic numbers, extract constants in variables and give descriptive names, for instance there are multiple occurences of 400, 500 magic numbers, it is not clear for what they are.
    • In comments to a code you saying Pause Microsoft Visual Studio..., microsoft visual studio receives data..., this is not correct, execution of your application (but not Visual Studio) will be paused while Thread.Sleep() and your applciation will receive an incomming serial port data, Visual Studio is just a development environment and in such cases dos not involved in a port communication directly.

    这篇关于在多个表单上使用相同的串口实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆