C#接收串口RS232的CD、CTS、DSR信号

通过串口RS232和工控机连接,工控机可以接收设备(光电传感器)的IO信号

SerialPortSwitch portSwitch = new SerialPortSwitch("COM3");
ToolData.WriteLog(lrtxtLog, "打开" + cbcomname3.Text + "成功", 0);
portSwitch.SwitchOn += pin =>
{
    //断开到闭合事件触发,CD、CTS、DSR之间任意一个触发都会进入该事件,可以在类中进行设置
};
portSwitch.SwitchOff += pin =>
{
    //从闭合到断开事件触发
};
portSwitch.Start();

原理是软件后台线程一直发信号检测port.CDHolding以及port.DsrHolding和port.CtsHolding这三个的状态,如果状态变化则进入到事件

SerialPortSwitch类

/********************************************
 * -------------
 * \ 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 TrainDemo
{
    /// <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 = 40;

        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;
            this.port.Handshake = Handshake.RequestToSend;

            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; }
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马儿不吃草

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值