C#WinForm实操串口通讯使用GtkSharp库实现跨平台

 

Linux下运行.NET项目:

1、环境安装

2、cd 项目路径

3、dotnet 项目dll,即可运行

 

部分代码分享:

using Gtk;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using GLib;
using Application = Gtk.Application;
using Pango;

namespace GTKWinFormsApp
{
    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
        }

        private SerialPort comService; // 端口控件
        private StringBuilder tmpBuilder; // 可重复使用
        private bool isStart; // 该仪表是否已启动
        private double scaler; // 换算关系
        private double scalerAscii; // 使用Ascii时的scaler
        private string[] flagStrings; // string.Split需要


        private string flagString = "";

        /// <summary>
        /// 仪表数据段的标识位
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(""), Description("仪表数据段的标识位")]
        public string FlagString
        {
            get { return flagString; }
            set
            {
                flagString = value;
            }
        }

        #region Com

        private string portName = "COM1";

        /// <summary>
        /// 仪表的端口
        /// </summary>
        [Category("自定义-Com"), DefaultValue("COM1"), Description("仪表的端口")]
        public string PortName
        {
            get { return portName; }
            set
            {
                portName = value;
            }
        }

        private int baudRate = 9600;

        /// <summary>
        /// 仪表的波特率
        /// </summary>
        [Category("自定义-Com"), DefaultValue(9600), Description("仪表的波特率")]
        public int BaudRate
        {
            get { return baudRate; }
            set
            {
                baudRate = value;
            }
        }

        private Parity parity = Parity.None;

        /// <summary>
        /// 仪表的奇偶校验位
        /// </summary>
        [Category("自定义-Com"), DefaultValue(Parity.None), Description("仪表的奇偶校验位")]
        public Parity Parity
        {
            get { return parity; }
            set
            {
                parity = value;
            }
        }

        private int dataBits = 8;

        /// <summary>
        /// 仪表的数据长度
        /// </summary>
        [Category("自定义-Com"), DefaultValue(8), Description("仪表的数据长度")]
        public int DataBits
        {
            get { return dataBits; }
            set
            {
                dataBits = value;
            }
        }

        private StopBits stopBits = StopBits.One;

        /// <summary>
        /// 仪表的停止位
        /// </summary>
        [Category("自定义-Com"), DefaultValue(StopBits.One), Description("仪表的停止位")]
        public StopBits StopBits
        {
            get { return stopBits; }
            set
            {
                stopBits = value;
            }
        }

        #endregion Com



        public void StopCOM()
        {
            if (!isStart) { return; }

            try
            {
                if (comService != null && comService.IsOpen)
                {
                    comService.Close();
                    comService = null;
                }

                isStart = false;
            }
            catch (Exception e)
            {
                throw new Exception("关闭仪表出错:" + e.Message, e);
            }
        }

        public void StartCOM()
        {
            if (isStart) { return; }
            isStart = true;

            tmpBuilder = new StringBuilder();
            flagStrings = new[] { FlagString };

            comService = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
            comService.NewLine = "\r\n"; // 指定换行符
            comService.RtsEnable = true; // 启用RTS/CTS握手(解决隐藏设备的问题?)
            comService.DataReceived += ComService_DataReceived;
            scalerAscii = 0.001;
            try
            {
                comService.Open();
            }
            catch (Exception e)
            {
                isStart = false;
                throw new Exception("打开仪表出错:" + e.Message, e);
            }
        }

        //正在接收数据
        bool IsReceivingData = false;

        private void ComService_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                IsReceivingData = true;
                DataProgress();
            }
            catch
            {
                IsReceivingData = false;
            }
        }


        private void DataProgress()
        {
            byte[] buffer;
            try
            {
                int num = comService.BytesToRead; // 该次接收到的byte数
                if (num == 0) { return; }

                buffer = new byte[num]; // 可能会以十六进制展示,所以按byte[]接收而不是char[]
                comService.Read(buffer, 0, num);

                DataReceivedMethod(buffer);
                AscDataProgress(buffer);
            }
            catch (Exception)
            {
            }
        }
        private void DataReceivedMethod(byte[] buffer)
        {
            try
            {
                string readString = System.Text.Encoding.Default.GetString(buffer, 0, buffer.Length);
                string readStringHex = ByteToHex(buffer);

                TxtBoxMessage2(readStringHex);
            }
            catch (Exception ex)
            {
                TxtBoxMessage2(ex.Message);
            }
        }


        private int signStart = 1;

        /// <summary>
        /// 仪表数据段的正负号标记起始位
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(1), Description("仪表数据段的正负号标记起始位")]
        public int SignStart
        {
            get { return signStart; }
            set
            {
                signStart = value;
            }
        }


        private int signBits = 1;

        /// <summary>
        /// 仪表数据段的正负号标记长度
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(1), Description("仪表数据段的正负号标记长度")]
        public int SignBits
        {
            get { return signBits; }
            set
            {
                signBits = value;
            }
        }

        private int numberStart = 2;

        /// <summary>
        /// 仪表数据段的数据起始位
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(2), Description("仪表数据段的数据起始位")]
        public int NumberStart
        {
            get { return numberStart; }
            set
            {
                numberStart = value;
            }
        }

        private int numberBits = 6;

        /// <summary>
        /// 仪表数据段的数据长度
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(6), Description("仪表数据段的数据长度")]
        public int NumberBits
        {
            get { return numberBits; }
            set
            {
                numberBits = value;
            }
        }

        private bool isAntitone;

        /// <summary>
        /// 仪表数据段的数据是否反序
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue(false), Description("仪表数据段的数据是否反序")]
        public bool IsAntitone
        {
            get { return isAntitone; }
            set
            {
                isAntitone = value;
            }
        }
        private string signNegativeString = "-";

        /// <summary>
        /// 仪表数据段的正负号标记为负号时的字符串表示
        /// </summary>
        [Category("自定义-Ascii"), DefaultValue("-"), Description("仪表数据段的正负号标记为负号时的字符串表示")]
        public string SignNegativeString
        {
            get { return signNegativeString; }
            set
            {
                signNegativeString = value;
            }
        }

        private int precision = 2;
        private string precisionFormat1 = "#0.000"; // double.ToString会使用
        private string precisionFormat2 = "#0.";

        /// <summary>
        /// 仪表控件的精度(影响控件本身的展示)
        /// </summary>
        [Category("自定义-数据"), DefaultValue(3), Description("仪表控件的精度(影响控件本身的展示)")]
        public int Precision
        {
            get { return precision; }
            set
            {
                precision = value;
                precisionFormat1 = precisionFormat2 + "".PadRight(precision, '0');
            }
        }
        private void AscDataProgress(byte[] buffer)
        {
            try
            {
                byte[] tempbuffer = new byte[buffer.Length];
                tmpBuilder.Append(System.Text.Encoding.ASCII.GetString(buffer));
                string completeData = tmpBuilder.ToString();
                if (completeData.LastIndexOf(FlagString) != -1)
                {
                    string[] tmps = completeData.Split(flagStrings, StringSplitOptions.None);
                    if (tmps.Length > 2) // 即至少有两个FlagString
                    {
                        tmpBuilder.Remove(0, tmpBuilder.Length).Append(FlagString).Append(tmps[tmps.Length - 1]);
                        string data = tmps[tmps.Length - 2];

                        if (SignStart < 1)
                        {
                            SignStart = 1;
                        }
                        if (data.Length < SignStart - 1 + SignBits)
                        {
                            SignBits = data.Length - (SignStart - 1);
                        }
                        string signPart = data.Substring(SignStart - 1, SignBits); // 符号段
                        if (data.Length < NumberStart - 1 + NumberBits)
                        {
                            NumberBits = data.Length - (NumberStart - 1);
                        }
                        string dataPart = data.Substring(NumberStart - 1, NumberBits); // 数据段

                        if (IsAntitone)
                        {
                            char[] arr = dataPart.ToCharArray();
                            Array.Reverse(arr);
                            dataPart = new string(arr);
                        }
                        double result = Math.Round((Convert.ToDouble(dataPart) * scalerAscii) * (signPart == SignNegativeString ? -1 : 1), Precision, MidpointRounding.AwayFromZero);

                        TxtBoxMessage(result.ToString());
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }



        /// <summary>
        /// 转换字节数组到十六进制字符串
        /// </summary>
        /// <param name="comByte">待转换字节数组</param>
        /// <returns>十六进制字符串</returns>
        public string ByteToHex(byte[] comByte)
        {
            StringBuilder builder = new StringBuilder(comByte.Length * 3);
            foreach (byte data in comByte)
            {
                builder.Append(Convert.ToString(data, 16).PadLeft(2, '0').PadRight(3, ' '));
            }
            return builder.ToString().ToUpper();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            PortName = textBox1.Text.Trim();
            //BaudRate = 9600;
            BaudRate = 115200;
            Parity = Parity.None;
            DataBits = 8;
            StopBits = StopBits.One;

            StartCOM();
            TxtBoxMessage2("COM打开");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            StopCOM();
            TxtBoxMessage2("COM关闭");
        }

        public void TxtBoxMessage(string message)
        {
            Application.Invoke(delegate
            {
                textBox3.Text = message;
            });
        }

        string lastTxtBoxMessage = "";
        public void TxtBoxMessage2(string message)
        {
            Application.Invoke((EventHandler)(delegate
            {
                if (lastTxtBoxMessage == message) { return; }
                lastTxtBoxMessage = message;

                message = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "  " + message + Environment.NewLine;

                richTextBox1.AppendText(message);
            }));
        }
    }
}

 

posted @ 2024-12-05 15:50  上位机李工  阅读(325)  评论(0)    收藏  举报