普通电脑没有通用的输入输出口(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 try108 {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 finally125 {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 else146 {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 Pin172 {173 CD = 1,174 DSR = 6,175 CTS = 8,176 }177 178 public class PinState179 {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
怎么样,是不是很简单。一起来动手做一个吧~~~
新闻热点
疑难解答