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

普通电脑没有通用的输入输出口(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

 

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

 

 

你可能感兴趣的:(实现)