欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

串口编程之端口

程序员文章站 2022-04-08 15:48:40
软件程序与硬件通过串口交换数据,首先要知道COM口,但是COM口是由计算机动态随机分配的。也就是说COM口的编号是变化的。因此我们在编程时不能将COM的编号写死。针对此问题我们想到的可能是将所有COM口读出来绑定到下拉框,软件启动后从下拉框选择需要的端口。或者写到配置文件,软件启动前在配置文件配置。 ......

软件程序与硬件通过串口交换数据,首先要知道com口,但是com口是由计算机动态随机分配的。也就是说com口的编号是变化的。因此我们在编程时不能将com的编号写死。针对此问题我们想到的可能是将所有com口读出来绑定到下拉框,软件启动后从下拉框选择需要的端口。或者写到配置文件,软件启动前在配置文件配置。不用说这两种方法都不是很理想。后来通过查询资料原来com口的变化会在注册表中记录。如图。

串口编程之端口

这样我们就有一个想法,能不能通过监控注册表来监测com口。于是有了下面代码。

  1 using microsoft.win32;
  2 using system;
  3 using system.threading;
  4 using system.threading.tasks;
  5 
  6 namespace autotester.utilities
  7 {
  8     public class comlistenservice
  9     {
 10         /// <summary>
 11         /// com监听服务类
 12         /// </summary>
 13         /// <param name="serialport">需要监听的端口</param>
 14         //public comlistenservice(string serialport)
 15         //{
 16         //    _serialport = serialport;
 17         //}
 18 
 19         /// <summary>
 20         /// 监听连接状态事件
 21         /// </summary>
 22         public event action<string, bool> connectionstatuschanged;
 23 
 24         /// <summary>
 25         /// 连接状态
 26         /// </summary>
 27         private bool _connectionstatus;
 28 
 29         /// <summary>
 30         /// 连接状态
 31         /// </summary>
 32         private bool connectionstatus
 33         {
 34             get { return _connectionstatus; }
 35             set
 36             {
 37                 if (_connectionstatus != value)
 38                 {
 39                     _connectionstatus = value;
 40                     connectionstatuschanged(_serialport, value);
 41                 }
 42             }
 43         }
 44 
 45 
 46         /// <summary>
 47         /// 开始监听
 48         /// </summary>
 49         public void startlisten()
 50         {
 51             _tokensource = new cancellationtokensource();
 52 
 53             task.factory.startnew(() =>
 54             {
 55                 listenning();
 56             });
 57         }
 58 
 59         /// <summary>
 60         /// 停止监听
 61         /// </summary>
 62         public void stoplisten()
 63         {
 64             _tokensource.cancel();
 65         }
 66 
 67         /// <summary>
 68         /// 监听端口
 69         /// </summary>
 70         public void listenning()
 71         {
 72             while (true)
 73             {
 74                 thread.sleep(listenfrequency);
 75 
 76                 if (_tokensource.iscancellationrequested)
 77                 {
 78                     break;
 79                 }
 80 
 81                 lock (_locker)
 82                 {
 83                     bool isexist = false;
 84                     registrykey keycom = registry.localmachine.opensubkey(@"hardware\devicemap\serialcomm");
 85                     if (keycom != null)
 86                     {
 87                         string[] ssubkeys = keycom.getvaluenames();
 88 
 89                         foreach (string sname in ssubkeys)
 90                         {
 91                             string svalue = string.empty;
 92 
 93                             //if (svalue == _serialport)
 94                             //{
 95                             //    isexist = true;
 96                             //    break;
 97                             //}
 98 
 99                             if (sname.contains("prolificserial") || sname.toupper().contains("vcp"))                           
100                             { 
101                                 _serialport = (string)keycom.getvalue(sname);
102                                 isexist = true;
103                                 break;
104                             }
105                         }
106                     }
107 
108                     connectionstatus = isexist;
109                 }
110             }
111         }
112 
113 
114         private string _serialport;
115         private cancellationtokensource _tokensource;
116         private const int listenfrequency = 1000; //监听频率(毫秒)
117         private static readonly object _locker = new object();
118     }
119 }

(注:prolificserial和vcp和你的硬件设备有关,插上你的硬件后观察注册表变化)

调用非常简单,直接上代码。

1  comlistenservice cls = new comlistenservice();
2  cls.connectionstatuschanged += cls_connectionstatuschanged;
3  cls.startlisten();
 1         /// <summary>
 2         /// 
 3         /// </summary>
 4         /// <param name="comport"></param>
 5         /// <param name="status"></param>
 6         private static void cls_connectionstatuschanged(string comport, bool status)
 7         {
 8             if (status)
 9             {
10                 //comport已插入
11             }
12             else
13             {
14                 //comport已拔出
15             }
16         }

测试后,完美一切正常。