你的位置:首页 > ASP.net教程

[ASP.net教程]另类,用串口实现普通电脑的开关量输入


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