zoukankan      html  css  js  c++  java
  • 另类,用串口实现普通电脑的开关量输入

    普通电脑没有通用的输入输出口(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 + "	On");
    12             };
    13             portSwitch.SwitchOff += pin =>
    14             {
    15                 Console.WriteLine(pin + "	Off");
    16             };
    17 
    18             portSwitch.Start();
    19             Console.WriteLine("串口输入运行中,按任意键结束...");
    20             Console.ReadKey();
    21             portSwitch.Stop();
    22         }
    23     }
    View Code

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

  • 相关阅读:
    蓝桥杯2016初赛
    蓝桥杯2016初赛
    蓝桥杯2016初赛
    蓝桥杯2015初赛
    关于VS本身遇到的一些相关问题
    VS的一些常用快捷键
    蓝桥杯2015初赛
    Luogu P1704 寻找最优美做题曲线
    POI2009 LYZ-Ice Skates
    Luogu P4313 文理分科
  • 原文地址:https://www.cnblogs.com/djian/p/3584435.html
Copyright © 2011-2022 走看看