我刚开始学习C#中的串行通信,所以这可能是一个很简单的问题,但我花了三天时间在谷歌上搜索,我的问题仍然没有解决,所以我希望你能帮助我。
我有一个设备(这是一种特殊的手风琴),上面有很多按钮。当我按下一个按钮时,获取数据是没有问题的。对于每个按钮,我会收到不同的ASCII代码。
我的问题是:我需要知道时间,我按下按钮多长时间。但我只有在按下按钮时才会获得数据(而不是在释放按钮时)。
有没有可能发现这一点?
下面你可以看到我写的程序,只是为了了解串行通信是如何工作的。
我的Commport类:
class MyCommPort : INotifyPropertyChanged
{
//Implementierung von "INotifyPropertyChanged"
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
//Felder
private SerialPort _serialPort = null;
private SolidColorBrush fillColor1 = Brushes.LightBlue;
private SolidColorBrush fillColor2 = Brushes.LightBlue;
private string text = null;
//Eigenschaften
public SerialPort SerialPort
{
get { return _serialPort; }
set { _serialPort = value; }
}
public SolidColorBrush FillColor1
{
get { return fillColor1; }
set
{
fillColor1 = value;
OnPropertyChanged("FillColor1");
}
}
public SolidColorBrush FillColor2
{
get { return fillColor2; }
set
{
fillColor2 = value;
OnPropertyChanged("FillColor2");
}
}
public string Text
{
get { return text; }
set
{
text = value;
OnPropertyChanged("Text");
}
}
//Konstruktor
public MyCommPort()
{
//Neuer Port wird angelegt
SerialPort = new SerialPort("COM3", 115200);
//Port wird geöffnet
SerialPort.Open();
//Wenn Daten am Port ankommen wird Event gefeuert
SerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}
//Destruktor
~MyCommPort()
{
//Port wird geschlossen
SerialPort.Close();
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(10);
//Neuer Port (Kopie von serialPort) wird angelegt ==> sender ist serialPort!
SerialPort sp = (SerialPort)sender;
//string DataIN = null;
string DataIN = sp.ReadExisting();
switch (DataIN)
{
case "(D07084)":
FillColor1 = Brushes.Red;
break;
case "(D04081)":
FillColor2 = Brushes.Red;
break;
default:
break;
}
Text = DataIN;
DataIN = null;
Thread.Sleep(200);
FillColor1 = Brushes.LightBlue;
FillColor2 = Brushes.LightBlue;
}
}
我的观点:
<Window x:Class="USB.MainWindow"
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:USB"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Ellipse Grid.Row="0" Fill="{Binding Path=FillColor1}" />
<Ellipse Grid.Row="1" Fill="{Binding Path=FillColor2}" />
</Grid>
<TextBox Grid.Column="1" Text="{Binding Text}" Height="50" Width="200"/>
</Grid>
视图背后的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyCommPort();
}
}
发布于 2018-07-25 09:31:56
我将要写的答案可能看起来很不可靠;然而,这是你得到的,直到有人想出一些聪明的想法。
由于您无法到达按钮释放的时刻,因此如果(且仅当)您的设备在按住按键的情况下一直发送相同的按键数据,那么就有一个技巧可以完成。
您需要定义一个时间间隔,该时间间隔对于人类按下两次键来说太小,对于机器不发送两次按键数据来说太大。在本例中,我假设您的关键代码是int
,我将预定义的时间间隔视为75
(毫秒)。
private delegate void SerialPortKeyUpHandler(int keyCode, TimeSpan timeHeld);
private event SerialPortKeyUpHandler SerialPortKeyUp;
CancellationTokenSource cancellationTokenSource;
private int keyCode;
private const int accuracy = 75; //the interval I'm talking about
private void StartCapturing(int keyCode)
{
this.keyCode = keyCode;
DateTime start = DateTime.UtcNow;
cancellationTokenSource.CancelAfter(accuracy);
ParameterizedThreadStart threadStart = new ParameterizedThreadStart((object cancellationTokenObj) =>
{
CancellationToken cancellationToken = (CancellationToken)cancellationTokenObj;
while (!cancellationToken.IsCancellationRequested) ; //wait until we make sure no more of the same key data is being sent
SerialPortKeyUp?.Invoke(keyCode, DateTime.UtcNow.Subtract(start));
});
Thread thread = new Thread(threadStart);
thread.Start(cancellationTokenSource.Token);
}
private void KeyDownCallback(object sender, KeyEventArgs e)
{
if (cancellationTokenSource == null || cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource = new CancellationTokenSource();
StartCapturing(e.KeyValue);
}
else
{
if (e.KeyValue == keyCode)
{
cancellationTokenSource.CancelAfter(accuracy);
}
else
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
cancellationTokenSource = new CancellationTokenSource();
StartCapturing(e.KeyValue);
}
}
}
private void KeyUpCallback(int keyCode, TimeSpan heldTime)
{
Debug.WriteLine($"Key {keyCode} is up. The key was held for {heldTime.TotalSeconds.ToString("#.00")} second(s).");
}
现在您有了一个要注册的SerialPortKeyUp
事件;为此,请在某个地方键入以下内容
SerialPortKeyUp += KeyUpCallback;
https://stackoverflow.com/questions/51508756
复制相似问题