C#中实现实时监听串口设备拔插的方法(Winform)

功能导入:

最近在做一个串口调试工具,需求是:

1、打开串口软件时,获取所有的串口,并显示第一个串口号

2、在程序中没有点击打开串口按钮时(串口关闭状态),实时监控串口拔插,当有串口设备插入时,显示最新插入的那一个串口号,当有串口设备拔出时,显示第一个串口号

3、当程序中已经点击了打开串口按钮(串口打开状态),实时监控串口拔插,当有串口设备插入时,保持打开的串口号不变,当有串口设备拔出时,如果不是打开的串口,继续保持打开的串口号不变,如果拔出的串口时打开的串口号,初始化串口状态(设为串口关闭状态)

解决办法:

采用的方法是,在主窗口的From类下覆盖WndProc,程序示例如下

#region WndProc 重载WndProc,串口设备刷新方法
//事件代码
private const int WM_DEVICECHANGE = 0x219; //设备改变事件
private const int DBT_DEVICEARRIVAL = 0x8000; //检测到新设备
private const int DBT_DEVICEREMOVECOMPLETE = 0x8004; //移除设备

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);//调用父类方法,以确保其他功能正常
    switch (m.Msg)
    {
        case WM_DEVICECHANGE://设备改变事件
             string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新获取串口
             switch ((int)m.WParam)
             {
                 case DBT_DEVICEARRIVAL://检测到新设备
                      //Debug.WriteLine("检测到新设备!!!!");
                      cbSerial.Items.Clear();//清除cbSerial里面的数据
                      cbSerial.Items.AddRange(ports);//给cbSerial添加数据

                      if (btnSwitch.Text == "关闭串口")//用户已经打开串口
                      {
                         //Debug.WriteLine("串口被占用,但检测到新设备");
                         cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
                         if (cbSerial.SelectedIndex >= 0)
                         {
                            //确保当前打开的串口不被改变
                            if (serialPort.PortName == cbSerial.SelectedItem.ToString())//之前打开的串口名与列表中的串口名相同
                            {
                               Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
                            }
                            else
                            {
                               for (int i = 0; i < cbSerial.Items.Count; i++)
                               {
                                   cbSerial.SelectedIndex = i;
                                   if (serialPort.PortName == cbSerial.SelectedItem.ToString())
                                   {
                                       Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
                                       break;
                                   }
                                }
                             }
                         }
                     }
                     else
                     {
                        Debug.WriteLine("串口未被占用,但检测到新设备");
                        cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
                        if (cbSerial.SelectedIndex >= 0)
                        {
                           for(int i=0;i<cbSerial.Items.Count;i++)
                           {
                              cbSerial.SelectedIndex = i;
                              Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
                           }
                           //cbSerial.SelectedIndex = 0;//显示最前面一个
                        }
                     }
                     break;

                     case DBT_DEVICEREMOVECOMPLETE://有设备移除
                          //Debug.WriteLine("有设备移除!!!!");
                          cbSerial.Items.Clear();//清除cbSerial里面的数据
                          cbSerial.Items.AddRange(ports);//给cbSerial添加数据

                          if (btnSwitch.Text == "关闭串口")//用户已经打开串口
                          {
                             //Debug.WriteLine("串口被占用,用但检测设备移除");
                             //serialPort.Dispose();//释放掉原先的串口资源
                             //用户打开过一个串口
                             cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
                             if (cbSerial.SelectedIndex >= 0)
                             {
                                //确保当前打开的串口不被改变
                                int temp_flag = 0;//标记串口状态   0:未检测到此串口   1:检测到此串口
                                for (int i = 0; i < cbSerial.Items.Count; i++)
                                {
                                    cbSerial.SelectedIndex = i;
                                    if (serialPort.PortName == cbSerial.SelectedItem.ToString())
                                    {
                                        Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
                                        temp_flag = 1;
                                        break;
                                    }
                                 }
                                 if (temp_flag == 0)//执行初始化串口状态程序
                                 {
                                    //如果串口为打开状态,就先关闭一下来初始化串口
                                    if (serialPort.IsOpen == true)
                                    {
                                       serialPort.Close();
                                    }
                                    //设置按钮内容为"打开串口"
                                    btnSwitch.Text = "打开串口";

                                    //恢复控件功能,设置必要控件为可用状态
                                    SettingControls(1);
                                  }
                                }
                                else
                                {
                                    //如果串口为打开状态,就先关闭一下来初始化串口
                                    if (serialPort.IsOpen == true)
                                    {
                                        serialPort.Close();
                                    }
                                    //设置按钮内容为"打开串口"
                                    btnSwitch.Text = "打开串口";

                                    //恢复控件功能,设置必要控件为可用状态
                                    SettingControls(1);
                                }
                            }
                            else
                            {
                                //Debug.WriteLine("串口未被占用,用但检测设备移除");
                                cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
                                if (cbSerial.SelectedIndex >= 0)
                                {
                                    for (int i = 0; i < cbSerial.Items.Count; i++)
                                    {
                                        cbSerial.SelectedIndex = i;
                                        Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
                                    }
                                    cbSerial.SelectedIndex = 0;//显示最前面一个
                                }
                            }
                            break;
                    }
                    break;
      }
}
#endregion

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以通过使用System.IO.Ports命名空间的SerialPort类来实现串口的自动识别。具体的做法是在程序使用一个定时器,每隔一定的时间就遍历系统所有可用的串口,如果发现新的串口,则触发入事件,如果发现串口被移除,则触发出事件。在实现时,需要注意以下几点: 1. 在程序引入System.IO.Ports命名空间; 2. 初始化SerialPort类,设置串口号、波特率等参数; 3. 注册串口入事件和出事件; 4. 使用定时器遍历系统所有可用的串口,如果发现新的串口,则触发入事件,如果发现串口被移除,则触发出事件。 以下是一个简单的示例代码,可以供参考: ``` using System; using System.IO.Ports; namespace SerialPortDemo { public partial class Form1 : Form { private SerialPort serialPort; private string[] portNames; public Form1() { InitializeComponent(); InitSerialPort(); } private void InitSerialPort() { serialPort = new SerialPort(); serialPort.PortName = "COM1"; serialPort.BaudRate = 9600; serialPort.DataBits = 8; serialPort.StopBits = StopBits.One; serialPort.Parity = Parity.None; serialPort.Open(); portNames = SerialPort.GetPortNames(); foreach (string portName in portNames) { serialPort = new SerialPort(portName); serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived); serialPort.Open(); } timer1.Interval = 1000; timer1.Enabled = true; timer1.Tick += new EventHandler(Timer1_Tick); } private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { // 处理串口数据 } private void Timer1_Tick(object sender, EventArgs e) { string[] currentPortNames = SerialPort.GetPortNames(); foreach (string portName in currentPortNames) { if (!portNames.Contains(portName)) { // 新串口入 serialPort = new SerialPort(portName); serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived); serialPort.Open(); } } foreach (string portName in portNames) { if (!currentPortNames.Contains(portName)) { // 串口移除 serialPort = new SerialPort(portName); serialPort.Close(); } } portNames = currentPortNames; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值