普通電腦沒有通用的輸入輸出口(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 4 5 /
* \ 6 7 8 9 /
* ---------
* 原理:
* 4[DTR]作為+6V電源 也可以用[RTS]替代[DTR]
* 軟件中不停檢測
* 1[CD ]
* 6[DSR]
* 8[CTS]
* 三個端口的電壓變化
*********************************************/
using System;
using System.IO.Ports;
using System.Threading;
namespace PortSignalReader
{
/// <summary>
///
/// </summary>
public delegate void SwitchEventHandler(Pin pin);
/// <summary>
/// 用一個串口采集3路開關輸入信號(也叫鋼節點或繼電器輸入)
/// </summary>
public class SerialPortSwitch
{
private const int PRIORITY = 20;
/// <summary>
/// 瞬時信號過濾時間
/// </summary>
private const int FILTER = 100;
private readonly SerialPort port = new SerialPort();
private readonly PinState[] pins;
public event SwitchEventHandler SwitchOn;
public event SwitchEventHandler SwitchOff;
public bool IsRunning { get; private set; }
public bool StopPedding { get; private set; }
public SerialPortSwitch(string portName)
{
this.port.PortName = portName;
this.port.BaudRate = 9600;
this.port.Parity = Parity.None;
this.port.DataBits = 8;
this.port.StopBits = StopBits.Two;
this.port.ReadBufferSize = 8;
this.port.WriteBufferSize = 8;
this.port.DtrEnable = true;
this.port.RtsEnable = true;
pins = new[]
{
new PinState {PinName = Pin.CD},
new PinState {PinName = Pin.CTS},
new PinState {PinName = Pin.DSR},
};
}
public void Start()
{
if(IsRunning) return;
IsRunning = true;
StopPedding = false;
try
{
Thread thread = new Thread(OnRunning);
thread.Name = "SerialPortSwitch";
thread.Start();
}
catch
{
IsRunning = false;
StopPedding = false;
throw;
}
}
public void Stop(bool waitUntilStoped = true)
{
if (IsRunning) StopPedding = true;
if (waitUntilStoped)
{
int timeout = Environment.TickCount + 10 * 1000;
while (Environment.TickCount < timeout)
{
Thread.Sleep(100);
if (IsRunning == false) return;
}
throw new TimeoutException("Stop SerialPortSwitch failed");
}
}
private void OnRunning()
{
try
{
port.Open();
while (StopPedding == false)
{
foreach (PinState pin in pins)
{
CheckState(pin);
}
Thread.Sleep(PRIORITY);
}
}
catch (Exception ex)
{
//TODO:log error.
System.Diagnostics.Debug.WriteLine("SerialPortSwitch term:" + ex);
}
finally
{
IsRunning = false;
StopPedding = false;
}
}
private void CheckState(PinState pin)
{
bool newHoding = GetPinHoding(pin.PinName);
if (pin.IsHoding == newHoding)
{
pin.HodingStableTime = Environment.TickCount;
}
if (Environment.TickCount - pin.HodingStableTime > FILTER)
{
pin.IsHoding = newHoding;
if (pin.IsHoding)
{
if (SwitchOn != null) SwitchOn(pin.PinName);
}
else
{
if (SwitchOff != null) SwitchOff(pin.PinName);
}
}
}
private bool GetPinHoding(Pin pin)
{
switch (pin)
{
case Pin.CD:
return port.CDHolding;
case Pin.DSR:
return port.DsrHolding;
case Pin.CTS:
return port.CtsHolding;
default:
throw new ArgumentOutOfRangeException();
}
}
}
/// <summary>
/// 串口中的3個信號針
/// </summary>
public enum Pin
{
CD = 1,
DSR = 6,
CTS = 8,
}
public class PinState
{
public Pin PinName { get; set; }
public bool IsHoding { get; set; }
public int HodingStableTime { get; set; }
}
}
Man函數:
class Program
{
static void Main(string[] args)
{
const string PORT_NAME = "COM6";//設置成你自己的端口
SerialPortSwitch portSwitch = new SerialPortSwitch(PORT_NAME);
portSwitch.SwitchOn += pin =>
{
Console.WriteLine(pin + "\tOn");
};
portSwitch.SwitchOff += pin =>
{
Console.WriteLine(pin + "\tOff");
};
portSwitch.Start();
Console.WriteLine("串口輸入運行中,按任意鍵結束...");
Console.ReadKey();
portSwitch.Stop();
}
}
怎麼樣,是不是很簡單。一起來動手做一個吧~~~
查看本欄目