另类,用串口实现普通电脑的开关量输入

普通电脑没有通用的输入输出口(GPIO),但有时候我就想输入一个开关量。

比如让用户拉一下拉绳开关就启动某个应用,比如装一个触点开关判断门是打开的还是关闭的,比如....

需求是如此简单,你都不愿意花几十块钱去买一个单片机,更不用说PCI扩展卡、PLC之类的了。。怎么办呐?

有办法!最简单的用串口就能实现。

原理:

串口的pin4[DTR]和pin7[RTS] 可以输出+6V的电(好吧,你的电脑上不一定是+6V,但肯定大于+3V就可以了),将该输出分别接入到pin1[DCD]、pin6[DSR]、pin8[CTS],在PC上就能检测出来,从而实现开关量输入。

核心代码:

//往PIN口输出电压
SerialPort.DtrEnable = true;
SerialPort.RtsEnable = true;

//判断PIN是否有电压输入
bool cd = SerialPort.CDHolding;
bool dsr = SerialPort.DsrHolding;
bool cts = SerialPort.CtsHolding;

知道原理,剩下的就好办了。

 首先是接线:(你需要一个9针串口母头、若干个开关、导线、电烙铁)

如图,我接了3个开关,4作为公共引脚,1、6、8分别接一个开关用于输入信号。当然,你只接一个开关也可以的。

(电脑主板上的带针的是公头,接线要用母头否则插不到电脑上,如果没有可以到电子城去买一个很便宜的,上面的编号很小要仔细看

没有串口的笔记本可以淘宝上买一条USB转串口线也可以的)

 

然后写一段代码不停检测1、6、8口是否有输入:

  1 /********************************************
  2  * -------------
  3  * \ 1 2 3 4 5 /
  4  *  \ 6 7 8 9 /
  5  *   --------- 
  6  * 原理:
  7  * 4[DTR]作为+6V电源 也可以用[RTS]替代[DTR]
  8  * 软件中不停检测
  9  * 1[CD ]
 10  * 6[DSR]
 11  * 8[CTS]
 12  * 三个端口的电压变化
 13  *********************************************/
 14 
 15 using System;
 16 using System.IO.Ports;
 17 using System.Threading;
 18 
 19 namespace PortSignalReader
 20 {
 21     /// <summary>
 22     /// 
 23     /// </summary>
 24     public delegate void SwitchEventHandler(Pin pin);
 25 
 26     /// <summary>
 27     /// 用一个串口采集3路开关输入信号(也叫钢节点或继电器输入)
 28     /// </summary>
 29     public class SerialPortSwitch
 30     {
 31         private const int PRIORITY = 20;
 32 
 33         /// <summary>
 34         /// 瞬时信号过滤时间
 35         /// </summary>
 36         private const int FILTER = 100;
 37 
 38         private readonly SerialPort port = new SerialPort();
 39 
 40         private readonly PinState[] pins;
 41 
 42         public event SwitchEventHandler SwitchOn;
 43 
 44         public event SwitchEventHandler SwitchOff;
 45 
 46         public bool IsRunning { get; private set; }
 47 
 48         public bool StopPedding { get; private set; }
 49 
 50         public SerialPortSwitch(string portName)
 51         {
 52             this.port.PortName = portName;
 53             this.port.BaudRate = 9600;
 54             this.port.Parity = Parity.None;
 55             this.port.DataBits = 8;
 56             this.port.StopBits = StopBits.Two;
 57             this.port.ReadBufferSize = 8;
 58             this.port.WriteBufferSize = 8;
 59             this.port.DtrEnable = true;
 60             this.port.RtsEnable = true;
 61 
 62             pins = new[]
 63             {
 64                 new PinState {PinName = Pin.CD},
 65                 new PinState {PinName = Pin.CTS},
 66                 new PinState {PinName = Pin.DSR},
 67             };
 68         }
 69 
 70         public void Start()
 71         {
 72             if(IsRunning) return;
 73             IsRunning = true;
 74             StopPedding = false;
 75             try
 76             {
 77                 Thread thread = new Thread(OnRunning);
 78                 thread.Name = "SerialPortSwitch";
 79                 thread.Start();
 80             }
 81             catch
 82             {
 83                 IsRunning = false;
 84                 StopPedding = false;
 85                 throw;
 86             }
 87         }
 88 
 89         public void Stop(bool waitUntilStoped = true)
 90         {
 91             if (IsRunning) StopPedding = true;
 92 
 93             if (waitUntilStoped)
 94             {
 95                 int timeout = Environment.TickCount + 10 * 1000;
 96                 while (Environment.TickCount < timeout)
 97                 {
 98                     Thread.Sleep(100);
 99                     if (IsRunning == false) return;
100                 }
101                 throw new TimeoutException("Stop SerialPortSwitch failed");
102             }
103         }
104 
105         private void OnRunning()
106         {
107             try
108             {
109                 port.Open();
110                 while (StopPedding == false)
111                 {
112                     foreach (PinState pin in pins)
113                     {
114                         CheckState(pin);
115                     }
116                     Thread.Sleep(PRIORITY);
117                 }
118             }
119             catch (Exception ex)
120             {
121                 //TODO:log error.
122                 System.Diagnostics.Debug.WriteLine("SerialPortSwitch term:" + ex);
123             }
124             finally
125             {
126                 IsRunning = false;
127                 StopPedding = false;
128             }
129         }
130 
131         private void CheckState(PinState pin)
132         {
133             bool newHoding = GetPinHoding(pin.PinName);
134             if (pin.IsHoding == newHoding)
135             {
136                 pin.HodingStableTime = Environment.TickCount;
137             }
138             if (Environment.TickCount - pin.HodingStableTime > FILTER)
139             {
140                 pin.IsHoding = newHoding;
141                 if (pin.IsHoding)
142                 {
143                     if (SwitchOn != null) SwitchOn(pin.PinName);
144                 }
145                 else
146                 {
147                     if (SwitchOff != null) SwitchOff(pin.PinName);
148                 }
149             }
150         }
151 
152         private bool GetPinHoding(Pin pin)
153         {
154             switch (pin)
155             {
156                 case Pin.CD:
157                     return port.CDHolding;
158                 case Pin.DSR:
159                     return port.DsrHolding;
160                 case Pin.CTS:
161                     return port.CtsHolding;
162                 default:
163                     throw new ArgumentOutOfRangeException();
164             }
165         }
166     }
167 
168     /// <summary>
169     /// 串口中的3个信号针
170     /// </summary>
171     public enum Pin
172     {
173         CD = 1,
174         DSR = 6,
175         CTS = 8,
176     }
177 
178     public class PinState
179     {
180         public Pin PinName { get; set; }
181 
182         public bool IsHoding { get; set; }
183 
184         public int HodingStableTime { get; set; }
185     }
186 }
View Code

Man函数:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             const string PORT_NAME = "COM6";//设置成你自己的端口
 6 
 7             SerialPortSwitch portSwitch = new SerialPortSwitch(PORT_NAME);
 8 
 9             portSwitch.SwitchOn += pin =>
10             {
11                 Console.WriteLine(pin + "\tOn");
12             };
13             portSwitch.SwitchOff += pin =>
14             {
15                 Console.WriteLine(pin + "\tOff");
16             };
17 
18             portSwitch.Start();
19             Console.WriteLine("串口输入运行中,按任意键结束...");
20             Console.ReadKey();
21             portSwitch.Stop();
22         }
23     }
View Code

 

怎么样,是不是很简单。一起来动手做一个吧~~~

 

 

posted @ 2014-03-06 15:00  sweetjian  阅读(8239)  评论(8编辑  收藏  举报