C#使用WPF框架实现 使用System.IO.Ports.SerialPort读取串口数据

由C#编程语言+WPF框架实现。由于需要实现应用程序的个体使用,也需要满足现有的维宏系统实现插件部分集成到总系统中,所以功能实现部分都在WaterAnalysisControl类库。

功能为上位机为RS232接口或USB接口,下位机为TTL电平协议,进行通讯

代码部分都以分块注释,有利于新手学习并理解

前端xaml部分

<Window x:Class="WaterAnalysis.WaterAnalysisDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WaterAnalysis" d:DataContext="{d:DesignInstance Type=local:WaterAnalysisControl}"
        mc:Ignorable="d"
        Height="200" Width="250" FontSize="18"
        Closing="Window_Closing">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50*"/>
            <RowDefinition Height="50*"/>
            <RowDefinition Height="30*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="125*"/>
            <ColumnDefinition Width="125*"/>
        </Grid.ColumnDefinitions>

        <Button x:Name="btConnect" Content="启动连接" Margin="5" Click="btConnect_Click" Grid.Row="0" Grid.Column="0"/>
        <Button x:Name="btGetData" Content="是否连接" Margin="5" Click="btGetData_Click" Grid.Row="0" Grid.Column="1"/>

        <TextBlock Text="TDS值:" Grid.Row="1" Grid.Column="0" />
        <TextBlock x:Name="tbTDS"  Grid.Row="1" Grid.Column="1" Text="{Binding TDS, Mode=TwoWay}"/>


        <TextBlock Text="串口连接状态:" Grid.Row="2" Grid.Column="0"/>
        <TextBlock x:Name="tbConnectStatus" Text="未连接" Grid.Row="2" Grid.Column="1"/>
    </Grid>
</Window>

后端

using Microsoft.SqlServer.Server;
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WaterAnalysis
{
    /// <summary>
    /// WaterAnalysisDialog.xaml 的交互逻辑
    /// </summary>
    public partial class WaterAnalysisDialog : Window
    {
        public static WaterAnalysisDialog mainWindow;

        WaterAnalysisControl waterAnalysisControl=new WaterAnalysisControl();
 
        public WaterAnalysisDialog()
        {
            InitializeComponent();
            mainWindow = this;
            this.DataContext = waterAnalysisControl;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            waterAnalysisControl.ClosePort();
        }

        private void btConnect_Click(object sender, RoutedEventArgs e)
        {
            waterAnalysisControl.Connect();
        }

        private void btGetData_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(waterAnalysisControl.IsOpen().ToString());
            //tbTDS.Text=waterAnalysisControl.Threshold.ToString();
        }

    }
}

创建WaterAnalysisControl类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Weihong.Phoenix.Framework;
using LuaNet;
using Weihong.Phoenix.UI.Interactions;
using System.Threading;

namespace WaterAnalysis
{
    public class WaterAnalysisControl: INotifyPropertyChanged, ISerializableObject
    {
        public WaterAnalysisControl() 
        { }

        #region 定义全局变量
        //串口实例
        SerialPort serialPort = new SerialPort();
        //监控串口任务
        Task monitorPortTask;
        int screen = 0;
        //实例化lua日志文件
        Lua_Log lua_Log = new Lua_Log(Scripts.Lua);
        #endregion

        #region demo中属性绑定UI通知方法
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        #region demo中进行创建 串口连接
        public void Connect()
        {
            //启动连接
            if (serialPort.IsOpen)
            {
                serialPort.Close();
            }
            else
            {
                try
                {
                    //创建Rtu主站
                    serialPort.PortName = "COM3"; //Phoenix.G.WaterAnalysis.Port;
                    serialPort.BaudRate = 9600;
                    serialPort.DataBits = 8;
                    serialPort.Parity = Parity.None;
                    serialPort.StopBits = StopBits.One;
                    serialPort.Open();
                    serialPort.ReadTimeout = 1000;
                    serialPort.RtsEnable = true;

                    //定义DataReceived事件,当串口收到数据后触发事件
                    serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }

                monitorPortTask = new Task(MonitorPort);
                monitorPortTask.Start();
            }
        }
        #endregion

        #region demo中串口关闭,当系统退出时执行
        public void ClosePort()
        {
            try
            {
                if (serialPort.PortName != null)
                {
                    serialPort.Close();
                }
            }
            catch (Exception ex)
            {
                if (ex.Source != null)
                {

                }
            }
        }
        #endregion

        #region 串口号
        private string port="COM3";
        [Param("Control")]
        [Attr("Name", "${LS:Param.NameWaterAnalysisPort, 串口序号}")]
        [Attr("Desc", "${LS:Param.DescWaterAnalysisPort, 设备通讯使用串口序号,需在设备启用前修改。}")]
        [Attr("Tag", "Manufacturer,MC")]
        public string Port
        {
            get { return port; }
            set { port = value; }
        }
        #endregion

        #region 是否启用
        private bool enabled = false;
        [Param("Control")]
        [Attr("Name", "${LS:Param.NameWaterAnalysisEnabled, 启用水质检测}")]
        [Attr("Desc", "${LS:Param.DescWaterAnalysisEnabled, 是否启用水质检测设备。是:启用;否:不启用。}")]
        [Attr("Tag", "Manufacturer,MC")]
        [Attr("Check", "{LE = 0, GE = 1}")]
        public bool Enabled
        {
            get { return enabled; }
            set 
            {
                enabled = value; 

                if (value) 
                {
                    //打开串口连接
                    ConnectStatus = true;
                }
                else
                {
                    //关闭串口连接
                    ConnectStatus = false;
                }
            }
        }
        #endregion

        #region 警告阈值
        private int threshold=300;
        [Param("Control")]
        [Attr("Name", "${LS:Param.NameWaterAnalysisThreshold, 警报阈值}")]
        [Attr("Desc", "${LS:Param.DescWaterAnalysisThreshold, 超过此值系统会产生报警,设置范围0-999,建议设置300。}")]
        [Attr("Tag", "Manufacturer,MC")]
        [Attr("Check", "{LE = 0, GE = 999}")]
        public int Threshold
        {
            get { return threshold; }
            set 
            {
                if (value <= 0 || value >= 999)
                {
                    MessageBox.Show("报警阈值需设置范围在 0-999,推荐值为 300 ");
                    return;
                }
                else threshold = value;
            }
        }
        #endregion

        #region 水质报警状态
        private bool tdsWarnStatus = false;
        public bool TdsWarnStatus
        {
            get { return tdsWarnStatus; }
            set { tdsWarnStatus = value; }
        }
        #endregion

        #region 水质检测 线路连接 报警状态
        private bool lineWarnStatus = false;
        public bool LineWarnStatus
        {
            get { return lineWarnStatus; }
            set { lineWarnStatus = value; }
        }
        #endregion

        #region 水质TDS值
        private int tds;
        public int TDS
        {
            get
            {
                return tds;
            }
            set
            {
                tds = value;

                //在使用类库时不能使用,在使用应用程序时取消注释
                OnPropertyChanged(nameof(tds));

                if(value > threshold)
                {
                    if(!TdsWarnStatus)
                    {
                        //使用维宏系统中的警报,报警:LogError,警报:LogWarning
                        lua_Log.LogWarning("水质质地较差,请检查水质!");
                        TdsWarnStatus = true;
                    }
                }
                else
                    TdsWarnStatus= false;
            }
        }
        #endregion

        #region 维宏中进行 串口连接
        private bool connectStatus;
        public bool ConnectStatus
        {
            get
            {
                return connectStatus;
            }
            set
            {
                //连接串口
                if (value == true)
                {
                    try
                    {
                        serialPort.PortName = Phoenix.G.WaterAnalysisDll.Port;
                        serialPort.BaudRate = 9600;
                        serialPort.DataBits = 8;
                        serialPort.Parity = Parity.None;
                        serialPort.StopBits = StopBits.One;
                        serialPort.Open();
                        serialPort.ReadTimeout = 1000;
                        serialPort.RtsEnable = true;

                        connectStatus = value;
                        //定义DataReceived事件,当串口收到数据后触发事件
                        serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);

                        
                    }
                    catch (Exception ex)
                    {
                        //MessageBox.Show("串口打开异常,异常信息:" + ex.Message);
                        connectStatus = false;
                    }

                    monitorPortTask = new Task(MonitorPort);
                    monitorPortTask.Start();
                }
                else if (value == false)
                {
                    //关闭
                    if (serialPort.IsOpen)
                    {
                        try
                        {
                            serialPort.Close();

                            //初始化阈值
                            tds = 0;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("串口关闭异常,异常信息:" + ex.Message);
                        }
                    }
                    connectStatus = value;
                }
            }
        }
        #endregion

        #region 获取串口连接状态
        public bool IsOpen()
        {
            if(serialPort.IsOpen)
                return true;
            else
                return false;
        }
        #endregion

        #region 继承自维宏的接口实现
        private string name = "WaterAnalysisControl";
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public bool Load
        {
            set
            {
                if (value == false)
                {
                    return;
                }
                var c = SerializationContext.GetContext(this);
                c.Deserialize(PresistenceService.Load(this));
            }
        }
        public bool Save
        {
            set
            {
                if (value == false)
                {
                    return;
                }
                var c = SerializationContext.GetContext(this);
                PresistenceService.Save(this, c.Serialize());
            }
        }
        #endregion

        #region 串口接收数据
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //延时100ms等待接收完数据
            System.Threading.Thread.Sleep(100);
            // this.Invoke就是跨线程访问ui的方法
            Dispatcher.CurrentDispatcher.Invoke(new System.Threading.ThreadStart(delegate   //使用new System.Threading.ThreadStart代替(EventHandler)
            {
                Byte[] ReceivedData = new Byte[serialPort.BytesToRead];
                serialPort.Read(ReceivedData, 0, ReceivedData.Length);
                //原始数据
                String RecvDataText = null;
                //16进制数据
                String Hexadecimal = null;
                //10进制数据
                String DecimalData = null;

                for (int i = screen; i < ReceivedData.Length - screen; i++)
                {
                    RecvDataText += ReceivedData[i].ToString("X2");
                    Hexadecimal += ReceivedData[i].ToString("X2");
                    DecimalData += GetHexadecimalValue(ReceivedData[i].ToString("X2")).ToString();

                    //TDS值计算方法:TDS=byte1*100+byte2
                    if (i == 1)
                    {
                        TDS = GetHexadecimalValue(ReceivedData[i].ToString("X2")) * 10;
                    }
                    else if (i == 2)
                    {
                        TDS += GetHexadecimalValue(ReceivedData[i].ToString("X2"));
                    }
                }
                //WaterAnalysisDialog.mainWindow.tbTDS.Text = TDS + "\r\n";
                //输出为16进制数据
                //tbTDS.Text += Hexadecimal + "\r\n" + "TDS值:" + TDS + "\r\n";

                serialPort.DiscardInBuffer();//丢弃接收缓冲区数据
            }));
        }
        #endregion

        #region 十六进制换算为十进制
        public static int GetHexadecimalValue(String strColorValue)
        {
            char[] nums = strColorValue.ToCharArray();
            int total = 0;
            try
            {
                for (int i = 0; i < nums.Length; i++)
                {
                    String strNum = nums[i].ToString().ToUpper();
                    switch (strNum)
                    {
                        case "A":
                            strNum = "10";
                            break;
                        case "B":
                            strNum = "11";
                            break;
                        case "C":
                            strNum = "12";
                            break;
                        case "D":
                            strNum = "13";
                            break;
                        case "E":
                            strNum = "14";
                            break;
                        case "F":
                            strNum = "15";
                            break;
                        default:
                            break;
                    }
                    double power = Math.Pow(16, Convert.ToDouble(nums.Length - i - 1));
                    total += Convert.ToInt32(strNum) * Convert.ToInt32(power);
                }
            }
            catch (System.Exception ex)
            {
                String strErorr = ex.ToString();
                return -1;
            }
            return total;
        }
        #endregion

        #region 监控串口方法
        private void MonitorPort()
        {
            bool isOpen = false;
            string[] gCOM = null;
            while (true)
            {
                gCOM = null;
                isOpen = false;
                // 获取设备的所有可用串口
                gCOM = System.IO.Ports.SerialPort.GetPortNames();
                int j = gCOM.Length; // 得到所有可用串口数目
                //判断是否找到串口,没有则直接报错
                if (j != 0)
                {
                    for (int i = 0; i < j; i++)
                    {
                        //找到目标串口
                        if (gCOM[i].ToUpper() == "COM3") //Phoenix.G.WaterAnalysisDll.Port;
                        {
                            //判断目标串口是否打开
                            if (serialPort.IsOpen)
                            {
                                isOpen = true;
                            }
                            else
                            {
                                try
                                {
                                    //尝试打开串口
                                    serialPort.Open();
                                    isOpen = true;
                                    //水质检测 线路连接 报警取消
                                    LineWarnStatus = false;
                                }
                                catch (Exception)
                                {
                                    //打开失败给false状态
                                    isOpen = false;
                                }

                            }
                            break;
                        }
                    }
                    //
                    if (!isOpen)
                    {
                        //使用维宏系统中的警报,报警:LogError,警报:LogWarning
                        if (!LineWarnStatus)
                        {
                            lua_Log.LogWarning("未能读取到水质数据,请检测水质检测线路。");
                            LineWarnStatus = true;
                        }
                    }
                }
                else
                {
                    //使用维宏系统中的警报,报警:LogError,警报:LogWarning
                    if (!LineWarnStatus)
                    {
                        lua_Log.LogWarning("未能读取到水质数据,请检测水质检测线路。");
                        LineWarnStatus = true;
                    }
                }

                Thread.Sleep(60000);
            }
        }
        #endregion
    }
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值