我几周来一直遇到问题,现在从串口读取数据并根据收到的消息更新canvas元素。要更新的画布元素是一个小图像,应根据接收到的消息的第三部分旋转到某个角度。我不确定出了什么问题,似乎并不总是收到完整的信息。我将详细介绍端口和数据。 结构 - 8个数据位,1个起始位,1个停止位,无奇偶校验。消息频率为15 Hz(每秒写入的行数)。默认波特率为9,600。
共有五个部分: 1.第1节 - 小数点后两位。 2.第2节 - 小数点后两位。 角度 - 乘以10 - 即256.0度显示为2560。 4. Section4乘以-100 - 即6.66度是-666。 5. Section5乘以100 - 即55.5度是555。 消息以冒号(:)开头,以<结尾。 CR>< LF> 。包含星号“***”的字段表示没有为该字段定义任何值。
举例说明:
Column
1 15 22 29 36 43
1.00 *** 0 0 0
: 1.00 20.20 2460 0 0
: 2.40 20.45 2460 10000 -10000
: 3.00 20.45 2355 1000 554
我收到的最新消息显示在窗口顶部,以确保用户正在接收数据,但我注意到该消息只显示应该是什么的一些部分,从而弄乱了旋转画布元素。因此,例如,消息可能是:首先是20 500,然后获得完整的消息。
以下是发送数据的屏幕截图:
这是我的MainWindow.cs中的相关代码:
private Port port = new Port();
private double rovHeading;
Point rotate_Origin = new Point(0.5, 0.5);
public string LastCOMMessage
{
get { return (string)this.GetValue(LastCoMMessageProperty); }
set { this.SetValue(LastCoMMessageProperty, value); }
}
private void Connect_Port(object sender, RoutedEventArgs e)
{
if (port.Status == Port.PortStatus.Disconnected)
{
try
{
port.Connect("COM1", 9600, false, 250); //When set to false, test data is used on Connect. Last parameter is how often the UI is updated. Closer to 0, the faster it updates.
//Sets button State and Creates function call on data recieved
Connect_btn.Content = "Disconnect";
port.OnMessageReceived += new Port.MessageReceivedHandler(port_OnMessageReceived);
}
catch (Exception)
{
System.Windows.MessageBox.Show("Port is not available.");
}
}
else
{
try // just in case serial port is not open, could also be achieved using if(serial.IsOpen)
{
port.Disconnect();
Connect_btn.Content = "Connect";
}
catch
{
}
}
}
/// <summary>
/// Reads in the data streaming from the port, taking out the third value which is the ROV's heading and assigning it to rovHeading.
/// It then calls orientRovImage.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void port_OnMessageReceived(object sender, Port.MessageEventArgs e)
{
LastCOMMessage = e.Message;
if (rovImage != null && e.Message.EndsWith("\r\n")) //messages end in <CR><LF>. Was having issues where only half a message would be received and updated the heading to wrong number.
{
string[] messageComponents = LastCOMMessage.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (messageComponents.Length >= 3)
{
double.TryParse(messageComponents[3], out rovHeading);
if (rovHeading > 0)
{
rovHeading /= 10;
orientRovImage();
}
}
}
}
/// <summary>
/// Rotates the ROV icon based on the heading being streamed in.
/// </summary>
private void orientRovImage()
{
RotateTransform rotateRov = new RotateTransform(rovHeading + angle_Offset);
rovImage.RenderTransformOrigin = rotate_Origin;
rovImage.RenderTransform = rotateRov;
}
这是我的Port.cs:
class Port
{
private SerialPort serial = null;
private DispatcherTimer testTimer;
private string[] testData = new string[] { ": 3.00 20.45 2355 1000 554\r\n", ": 5.00 78.09 1725 3200 121\r\n", ": 9.20 10.12 1492 8820 197\r\n" }; //test data to be sent when liveData is set to false.
private int testDataIndex = -1;
private DateTime dateOflastMessageHandled;
public enum PortStatus
{
Connected,
Disconnected
}
public PortStatus Status { get; private set; }
public bool LiveData { get; private set; }
public int MillisecondsDelayBetweenMessages { get; private set; }
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
Message = message;
}
}
public delegate void MessageReceivedHandler(object sender, MessageEventArgs e);
public event MessageReceivedHandler OnMessageReceived;
private void MessageReceived(string message)
{
if (OnMessageReceived == null)
{
return;
}
OnMessageReceived(this, new MessageEventArgs(message));
}
public Port()
{
Status = PortStatus.Disconnected;
}
public void Connect(string portName, int baudRate, bool liveData, int millisecondsDelayBetweenMessages)
{
LiveData = liveData;
MillisecondsDelayBetweenMessages = millisecondsDelayBetweenMessages;
Disconnect();
if (liveData)
{
serial = new SerialPort();
serial.PortName = portName;
serial.BaudRate = baudRate;
serial.Handshake = Handshake.None;
serial.Parity = Parity.None;
serial.DataBits = 8;
serial.StopBits = StopBits.One;
serial.ReadTimeout = 200;
serial.WriteTimeout = 50;
serial.Open();
serial.DataReceived += new SerialDataReceivedEventHandler(Receive);
}
else
{
testTimer = new DispatcherTimer();
testTimer.Interval = new TimeSpan(0, 0, 0, 0, 3);
testTimer.Tick += new EventHandler(testTimer_Tick);
testTimer.Start();
}
Status = PortStatus.Connected;
}
private void testTimer_Tick(object sender, EventArgs e)
{
if (dateOflastMessageHandled == null || DateTime.Now.Subtract(dateOflastMessageHandled).TotalMilliseconds >= MillisecondsDelayBetweenMessages)
{
dateOflastMessageHandled = DateTime.Now;
MessageReceived(testData[testDataIndex]);
testDataIndex++;
if (testDataIndex >= testData.Length)
{
testDataIndex = 0;
}
}
}
private void Receive(object sender, SerialDataReceivedEventArgs e)
{
if (dateOflastMessageHandled == null || DateTime.Now.Subtract(dateOflastMessageHandled).TotalMilliseconds >= MillisecondsDelayBetweenMessages)
{
dateOflastMessageHandled = DateTime.Now;
Application.Current.Dispatcher.BeginInvoke(new Action(
delegate()
{
//MessageReceived(serial.ReadLine());
MessageReceived(serial.ReadExisting());
}));
}
}
public void Disconnect()
{
if (testTimer != null)
{
testTimer.Stop();
}
testDataIndex = 0;
Status = PortStatus.Disconnected;
if (serial != null)
{
serial.Close();
}
}
}
最后在我的MainWindow.xaml中,这只显示收到的最后一条消息:
<Button Content="Connect" Click="Connect_Port" Name="Connect_btn" />
<TextBlock Text="{Binding LastCOMMessage, ElementName=this}" />
任何提示或帮助都会非常感激,因为这是我第一次使用w / ports。谢谢!