千家信息网

C#如何实现串口调试工具

发表于:2024-09-25 作者:千家信息网编辑
千家信息网最后更新 2024年09月25日,C#如何实现串口调试工具,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。前文由于经常用到串口调试, 尽管有现成的软件, 因
千家信息网最后更新 2024年09月25日C#如何实现串口调试工具

C#如何实现串口调试工具,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

前文

由于经常用到串口调试, 尽管有现成的软件, 因为前端时间涉及一个二次开发, 就因为一个RtsEnable设置, 折腾半天, 网上各种版本的也很多, 功能扩展的很开也多。所以现在自己做了一个够用版,基于自己的需求,简单的实现发送接收功能, 至于那些扩展功能可以自己根据需求添加。

正文

先上个运行效果图:

项目架构

该实例用的GalaSoft.Mvvm, 该插件可以直接在NuGet中并且添加。

1.串口参数 , 为了方便, 端口号并没有用动态加载的方式, 如下枚举结构:

namespace System.Windows.Data{    //    // 摘要:    //     提供将自定义逻辑应用于绑定的方法。    public interface IValueConverter    {        //        // 摘要:        //     转换值。        //        // 参数:        //   value:        //     绑定源生成的值。        //        //   targetType:        //     绑定目标属性的类型。        //        //   parameter:        //     要使用的转换器参数。        //        //   culture:        //     要用在转换器中的区域性。        //        // 返回结果:        //     转换后的值。 如果该方法返回 null,则使用有效的 null 值。        object Convert(object value, Type targetType, object parameter, CultureInfo culture);        //        // 摘要:        //     转换值。        //        // 参数:        //   value:        //     绑定目标生成的值。        //        //   targetType:        //     要转换为的类型。        //        //   parameter:        //     要使用的转换器参数。        //        //   culture:        //     要用在转换器中的区域性。        //        // 返回结果:        //     转换后的值。 如果该方法返回 null,则使用有效的 null 值。        object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);    }}

2.串口参数配置类 ,

作用: 主要用于绑定界面的参数选项。

///     /// 串口参数设置类    ///     public class ComParameterConfig : ViewModelBase    {        public ComParameterConfig()        {            Port = System.Enum.GetValues(typeof(Port));            CheckMode = System.Enum.GetValues(typeof(CheckMode));            StopBit = System.Enum.GetValues(typeof(StopBit));            BaudRate = new List() { 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, };            DataBit = new List() { 6, 7, 8 };        }        private Array port;        private Array checkMode;        private Array stopBit;        private List dataBit;        private List baudRate;        ///         /// 端口        ///         public Array Port        {            get { return port; }            set { port = value; RaisePropertyChanged(); }        }        ///         /// 校验模式        ///         public Array CheckMode        {            get { return checkMode; }            set { checkMode = value; RaisePropertyChanged(); }        }        ///         /// 停止位        ///         public Array StopBit        {            get { return stopBit; }            set { stopBit = value; RaisePropertyChanged(); }        }        ///         /// 波特率        ///         public List BaudRate        {            get { return baudRate; }            set { baudRate = value; RaisePropertyChanged(); }        }        ///         /// 数据位        ///         public List DataBit        {            get { return dataBit; }            set { dataBit = value; RaisePropertyChanged(); }        }    }

3.当前配置参数类

作用: 用于保存当前的串口参数、串口功能开关接收数据等业务。

核心代码:

///     /// 当前配置参数    ///     public class CurrentParameter : ViewModelBase    {        #region Private        private int baudRdate = 9600;        private int dataBit = 8;        private Port port;        private CheckMode checkMode;        private StopBit stopBit = StopBit.One;        private SerialPort serialPort;        private string dataReceiveInfo;        private string sendData;        private bool isOpen;        private bool receiveFormat16 = true;        private bool sendFormat16 = true;        private int sendCount;        private int receiveCount;        #endregion        #region UI绑定参数        ///         /// 发送数量        ///         public int SendCount        {            get { return sendCount; }            set { sendCount = value; RaisePropertyChanged(); }        }        ///         /// 接收数量        ///         public int ReceiveCount        {            get { return receiveCount; }            set { receiveCount = value; RaisePropertyChanged(); }        }        ///         /// 接收区16进制        ///         public bool ReceiveFormat16        {            get { return receiveFormat16; }            set { receiveFormat16 = value; RaisePropertyChanged(); }        }        ///         /// 接收区数据        ///         public string DataReceiveInfo        {            get { return dataReceiveInfo; }            set { dataReceiveInfo = value; RaisePropertyChanged(); }        }        ///         /// 发送数据        ///         public string SendData        {            get            {                return sendData;            }            set { sendData = value; RaisePropertyChanged(); }        }        ///         /// 发送区16进制        ///         public bool SendFormat16        {            get { return sendFormat16; }            set { sendFormat16 = value; RaisePropertyChanged(); }        }        #endregion        #region 串口参数信息        ///         /// 开关        ///         public bool IsOpen        {            get { return isOpen; }            set { isOpen = value; RaisePropertyChanged(); }        }        ///         /// 数据位        ///         public int DataBit        {            get { return dataBit; }            set { dataBit = value; RaisePropertyChanged(); }        }        ///         /// 波特率        ///         public int BaudRdate        {            get { return baudRdate; }            set { baudRdate = value; RaisePropertyChanged(); }        }        ///         /// 端口        ///         public Port Port        {            get { return port; }            set { port = value; RaisePropertyChanged(); }        }        ///         /// 校验        ///         public CheckMode CheckMode        {            get { return checkMode; }            set { checkMode = value; RaisePropertyChanged(); }        }        ///         /// 停止位        ///         public StopBit StopBit        {            get { return stopBit; }            set { stopBit = value; RaisePropertyChanged(); }        }        ///         /// COM        ///         public SerialPort SerialPort        {            get { return serialPort; }            set { serialPort = value; RaisePropertyChanged(); }        }        #endregion        #region 串口操作方法        ///         /// 开启串口        ///         ///         public bool Open()        {            if (serialPort != null && serialPort.IsOpen)            {                return Close();            }            try            {                serialPort = new SerialPort();                serialPort.DataBits = this.DataBit;                serialPort.StopBits = ComHelper.GetStopBits(this.StopBit.ToString());                serialPort.Parity = ComHelper.GetParity(this.CheckMode.ToString());                serialPort.PortName = this.Port.ToString();                serialPort.RtsEnable = true;                serialPort.DataReceived += SerialPort_DataReceived;                serialPort.Open();                if (serialPort.IsOpen)                    return IsOpen = true;                else                    return IsOpen = false;            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }            return IsOpen = false;        }        ///         /// 关闭串口        ///         ///         public bool Close()        {            try            {                if (serialPort.IsOpen)                {                    serialPort.Close();                    return IsOpen = serialPort.IsOpen;                }                else                {                    return IsOpen = serialPort.IsOpen;                }            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);                return IsOpen = false;            }        }        ///         /// 发送数据        ///         public void Send()        {            if (SendFormat16)            {                byte[] bytes = CRC.StringToHexByte(SendData);                this.SerialPort.Write(bytes, 0, bytes.Length);                SendCount = bytes.Length; //不做增量            }            else            {                this.SerialPort.Write(SendData);                SendCount = SendData.Length;            }            Messenger.Default.Send("", "PlaySendFlashing");        }        ///         /// 清空接收区        ///         public void Clear()        {            this.DataReceiveInfo = string.Empty;        }        ///         /// 清空发送区和缓存区        ///         public void ClearText()        {            this.SendData = string.Empty;            this.SendCount = 0;            this.ReceiveCount = 0;        }        #endregion        ///         /// 返回事件        ///         ///         ///         private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            Messenger.Default.Send("", "PlayReciveFlashing");            byte[] readBuffer = new byte[SerialPort.ReadBufferSize];            SerialPort.Read(readBuffer, 0, readBuffer.Length);            ReceiveCount = SerialPort.ReceivedBytesThreshold; //不做增量            if (ReceiveFormat16)            {                //不做增量                DataReceiveInfo = CRC.ByteToString(readBuffer, true);            }            else            {                DataReceiveInfo = Encoding.ASCII.GetString(readBuffer);            }        }    }

4.核心MainViewModel类

作用: 关联首页的上下文, 通过DataContext绑定, 关联界面元素、命令等作用。

public class MainViewModel : ViewModelBase    {        ///         /// Initializes a new instance of the MainViewModel class.        ///         public MainViewModel()        {            ComParameterConfig = new ComParameterConfig();            CurrentParameter = new CurrentParameter();        }        private ComParameterConfig comParameter;        ///         /// 参数类        ///         public ComParameterConfig ComParameterConfig        {            get { return comParameter; }            set { comParameter = value; RaisePropertyChanged(); }        }        private CurrentParameter currentParameter;        ///         /// 当前配置参数        ///         public CurrentParameter CurrentParameter        {            get { return currentParameter; }            set { currentParameter = value; RaisePropertyChanged(); }        }        #region Command        private RelayCommand _ToOpen;        public RelayCommand ToOpen        {            get            {                if (_ToOpen == null)                {                    _ToOpen = new RelayCommand(Open);                }                return _ToOpen;            }            set            {                _ToOpen = value;            }        }        ///         /// 根据配置打开端口        ///         public void Open()        {            this.CurrentParameter.Open();        }        private RelayCommand _ToClick;        public RelayCommand ToClick        {            get            {                if (_ToClick == null)                {                    _ToClick = new RelayCommand(Click);                }                return _ToClick;            }            set            {                _ToClick = value;            }        }        ///         /// 发送数据        ///         public void Click()        {            this.CurrentParameter.Send();        }        private RelayCommand _ToClear;        public RelayCommand ToClear        {            get            {                if (_ToClear == null)                {                    _ToClear = new RelayCommand(Clear);                }                return _ToClear;            }            set            {                _ToClear = value;            }        }        ///         /// 清空接收区        ///         public void Clear()        {            this.CurrentParameter.Clear();        }        private RelayCommand _ToClearText;        public RelayCommand ToClearText        {            get            {                if (_ToClearText == null)                {                    _ToClearText = new RelayCommand(ClearText);                }                return _ToClearText;            }            set            {                _ToClearText = value;            }        }        ///         /// 清空界面值        ///         public void ClearText()        {            this.CurrentParameter.ClearText();        }        #endregion    }

5.CRC校验核心类

作用:主要实现数据校验, 含ModbusCR标准校验

///     /// CRC校验    ///     public class CRC    {        #region  CRC16        public static byte[] CRC16(byte[] data)        {            int len = data.Length;            if (len > 0)            {                ushort crc = 0xFFFF;                for (int i = 0; i < len; i++)                {                    crc = (ushort)(crc ^ (data[i]));                    for (int j = 0; j < 8; j++)                    {                        crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);                    }                }                byte hi = (byte)((crc & 0xFF00) >> 8);  //高位置                byte lo = (byte)(crc & 0x00FF);         //低位置                return new byte[] { hi, lo };            }            return new byte[] { 0, 0 };        }        #endregion        #region  ToCRC16        public static string ToCRC16(string content)        {            return ToCRC16(content, Encoding.UTF8);        }        public static string ToCRC16(string content, bool isReverse)        {            return ToCRC16(content, Encoding.UTF8, isReverse);        }        public static string ToCRC16(string content, Encoding encoding)        {            return ByteToString(CRC16(encoding.GetBytes(content)), true);        }        public static string ToCRC16(string content, Encoding encoding, bool isReverse)        {            return ByteToString(CRC16(encoding.GetBytes(content)), isReverse);        }        public static string ToCRC16(byte[] data)        {            return ByteToString(CRC16(data), true);        }        public static string ToCRC16(byte[] data, bool isReverse)        {            return ByteToString(CRC16(data), isReverse);        }        #endregion        #region  ToModbusCRC16        public static string ToModbusCRC16(string s)        {            return ToModbusCRC16(s, true);        }        public static string ToModbusCRC16(string s, bool isReverse)        {            return ByteToString(CRC16(StringToHexByte(s)), isReverse);        }        public static string ToModbusCRC16(byte[] data)        {            return ToModbusCRC16(data, true);        }        public static string ToModbusCRC16(byte[] data, bool isReverse)        {            return ByteToString(CRC16(data), isReverse);        }        #endregion        #region  ByteToString        public static string ByteToString(byte[] arr, bool isReverse)        {            try            {                byte hi = arr[0], lo = arr[1];                return Convert.ToString(isReverse ? hi + lo * 0x100 : hi * 0x100 + lo, 16).ToUpper().PadLeft(4, '0');            }            catch (Exception ex) { throw (ex); }        }        public static string ByteToString(byte[] arr)        {            try            {                return ByteToString(arr, true);            }            catch (Exception ex) { throw (ex); }        }        #endregion        #region  StringToHexString        public static string StringToHexString(string str)        {            StringBuilder s = new StringBuilder();            foreach (short c in str.ToCharArray())            {                s.Append(c.ToString("X4"));            }            return s.ToString();        }        #endregion        #region  StringToHexByte        private static string ConvertChinese(string str)        {            StringBuilder s = new StringBuilder();            foreach (short c in str.ToCharArray())            {                if (c <= 0 || c >= 127)                {                    s.Append(c.ToString("X4"));                }                else                {                    s.Append((char)c);                }            }            return s.ToString();        }        private static string FilterChinese(string str)        {            StringBuilder s = new StringBuilder();            foreach (short c in str.ToCharArray())            {                if (c > 0 && c < 127)                {                    s.Append((char)c);                }            }            return s.ToString();        }        ///         /// 字符串转16进制字符数组        ///         ///         ///         public static byte[] StringToHexByte(string str)        {            return StringToHexByte(str, false);        }        ///         /// 字符串转16进制字符数组        ///         ///         /// 是否过滤掉中文字符        ///         public static byte[] StringToHexByte(string str, bool isFilterChinese)        {            string hex = isFilterChinese ? FilterChinese(str) : ConvertChinese(str);            //清除所有空格            hex = hex.Replace(" ", "");            //若字符个数为奇数,补一个0            hex += hex.Length % 2 != 0 ? "0" : "";            byte[] result = new byte[hex.Length / 2];            for (int i = 0, c = result.Length; i < c; i++)            {                result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);            }            return result;        }        #endregion    }

WPF技术点:

1.自定义样式按钮

                    

2.转换器用于绑定按钮

public class FontConverters : IValueConverter    {        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)        {            if (value != null && bool.TryParse(value.ToString(), out bool result))            {                if (result)                {                    return "关闭串口";                }            }            return "打开串口";        }        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)        {            throw new NotImplementedException();        }    }
//用于绑定UI的颜色状态显示    public class ColorConverters : IValueConverter    {        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)        {            if (value != null && bool.TryParse(value.ToString(), out bool result))            {                if (result)                {                    return new SolidColorBrush((Color)System.Windows.Media.ColorConverter.ConvertFromString("#2E8B57"));                }            }            return new SolidColorBrush((Color)System.Windows.Media.ColorConverter.ConvertFromString("#FF6347"));        }        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)        {            throw new NotImplementedException();        }    }

3.引用字体

   

4.绑定命令和元素

                                                                                                                                                                                                                                                                        

写在最后

主项目的结构图 , 如下:

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

0