标签:grid its property text .com tab center epo 没有
前文
由于经常用到串口调试, 尽管有现成的软件, 因为前端时间涉及一个二次开发, 就因为一个RtsEnable设置, 折腾半天, 网上各种版本的也很多, 功能扩展的很开也多。所以现在自己做了一个够用版,基于自己的需求,简单的实现发送接收功能, 至于那些扩展功能可以自己根据需求添加。
正文
先上个运行效果图:
项目架构
该实例用的GalaSoft.Mvvm, 该插件可以直接在NuGet中并且添加。
1.串口参数 , 为了方便, 端口号并没有用动态加载的方式, 如下枚举结构:
///
/// 端口号
///
public enum Port
{
COM1,
COM2,
COM3,
COM4,
COM5,
COM6,
COM7,
COM8,
COM9,
COM10,
COM11,
COM12,
COM13,
COM14,
COM15,
COM16,
COM17,
COM18,
COM19,
COM20,
COM21,
COM22,
COM23,
COM24,
COM25,
COM26,
COM27,
COM28,
COM29,
COM30
}
///
/// 奇偶校验
///
public enum CheckMode
{
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4
}
///
/// 停止位
///
public enum StopBit
{
One=1,
Two=2,
OnePointFive=3,
}
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 Listint>() { 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, };
DataBit = new Listint>() { 6, 7, 8 };
}
private Array port;
private Array checkMode;
private Array stopBit;
private Listint> dataBit;
private Listint> 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 Listint> BaudRate
{
get { return baudRate; }
set { baudRate = value; RaisePropertyChanged(); }
}
///
/// 数据位
///
public Listint> DataBit
{
get { return dataBit; }
set { dataBit = value; RaisePropertyChanged(); }
}
}
3.当前配置参数类
作用: 用于保存当前的串口参数、串口功能开关接收数据等业务。
///
/// 当前配置参数
///
public class CurrentParameter : ViewModelBase
{
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;
#region UI绑定参数
///
/// 接收区数据
///
public string DataReceiveInfo
{
get { return dataReceiveInfo; }
set { dataReceiveInfo = value; RaisePropertyChanged(); }
}
///
/// 发送数据
///
public string SendData
{
get
{
return sendData;
}
set { sendData = 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()
{
}
#endregion
///
/// 返回事件
///
///
///
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
string ReadText = serialPort.ReadExisting();
DataReceiveInfo += ReadText + "\r\n";
}
}
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();
}
#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 )
{
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 )
{
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.引用字体
"" Margin="20 5 0 5" FontFamily="pack://application:,,,/Font/#iconfont"
Foreground="White" FontSize="30" VerticalAlignment="Center"/>
4.绑定命令和元素
"端 口:" Style="{DynamicResource TxtComStyle}"/>
"0" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" SelectedItem="{Binding CurrentParameter.Port}"
ItemsSource="{Binding ComParameterConfig.Port}"
/>
"波 特 率:" Style="{DynamicResource TxtComStyle}"/>
"0" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" SelectedItem="{Binding CurrentParameter.BaudRdate}"
ItemsSource="{Binding ComParameterConfig.BaudRate}"
/>
"数 据 位:" Style="{DynamicResource TxtComStyle}"/>
"0" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" SelectedItem="{Binding CurrentParameter.DataBit}"
ItemsSource="{Binding ComParameterConfig.DataBit}"
/>
"校 验 位:" Style="{DynamicResource TxtComStyle}"/>
"0" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" SelectedItem="{Binding CurrentParameter.CheckMode}"
ItemsSource="{Binding ComParameterConfig.CheckMode}"
/>
"停 止 位:" Style="{DynamicResource TxtComStyle}"/>
"0" Grid.Column="2" Style="{StaticResource ComboBoxStyle}" SelectedItem="{Binding CurrentParameter.StopBit}"
ItemsSource="{Binding ComParameterConfig.StopBit}"
/>
"状 态:" Style="{DynamicResource TxtComStyle}"/>
"" Style="{DynamicResource TxtComStyle1}"
Foreground="{Binding CurrentParameter.IsOpen,Converter={StaticResource ColorConverters}}" />
写在最后
主项目的结构图 , 如下:
如有疑问或需要, 请添加如下微信:
C#串口调试工具 (基于WPF史无前例/MVVM结构完整示例版)
标签:grid its property text .com tab center epo 没有
原文地址:https://www.cnblogs.com/zh7791/p/9317042.html