当前位置: 代码迷 >> C# >> 另类,用串口实现普普通通电脑的开关量输入
  详细解决方案

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

热度:594   发布时间:2016-04-28 08:22:33.0
另类,用串口实现普通电脑的开关量输入

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

  

  相关解决方案