Serial port transmission missing one byte

I am responsible for creating an HMI that will use a USB port to communicate with the device.

I am new to C # and WPF, so I started to understand a bit and found a few questions and topics on this site that helped me reach the starting point I wanted: I can read and write in the SerialPort class.

To test the device, I have a UART that drives off any received message. I have a simple form with a text box, button and shortcut. After clicking the button, it sends the text typed into the field to the device (if the text is not entered, I have a predefined array of bytes for testing). The label is updated at any time when the port receives bytes.

The code works fine for the first message (no matter which one), but any message sent after that almost always returns with missing bytes. I have no idea why this happens, every time I tried to drop the buffers, but to no avail.

Here is my code:

using System.IO.Ports; namespace LearningSteps { /// <summary> /// Interaction logic for Comm.xaml /// </summary> /// public partial class Comm : Window { SerialPort port; BackgroundWorker backgroundWorker1 = new BackgroundWorker(); public delegate void AtualizaCallBack(string message); public Comm() { InitializeComponent(); //InitializeBackgroundWorker(); port = new SerialPort("COM4",115200,Parity.None,8,StopBits.One); port.RtsEnable = true; port.DataReceived += new SerialDataReceivedEventHandler(Recebido); port.Open(); } private void Recebido(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; String indata = sp.ReadExisting(); sp.DiscardOutBuffer(); sp.DiscardInBuffer(); my_label.Dispatcher.Invoke(new AtualizaCallBack(this.atualiza),new object[]{indata}); } private void bt_Click(object sender, RoutedEventArgs e) { if (txt1.Text.Length == 0) { byte[] vetor = new byte[] { 0x40, 0x45, 0x2B, 0x5C, 0x10 }; port.DiscardOutBuffer(); port.Write(vetor, 0, 5); } else { port.DiscardOutBuffer(); port.Write(txt1.Text); } } private void atualiza(string s) { my_label.Content = s; } } } 

And here is XAML:

 <Window x:Class="LearningSteps.Comm" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Comm" Height="346" Width="404"> <Grid Background="#FF9E9E9E"> <Label x:Name="my_label" HorizontalAlignment="Left" Height="40" Margin="80,200,0,0" VerticalAlignment="Top" Width="240" Background="#FFD1D18D" FontSize="14" FontWeight="Bold" Foreground="#FF1D83BD" HorizontalContentAlignment="Center" Content="Lalala"/> <TextBox x:Name="txt1" HorizontalAlignment="Left" Height="40" Margin="80,80,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="240" TextAlignment="Center" FontSize="14" FontWeight="Bold"/> <Button x:Name="bt" Content="Enviar" HorizontalAlignment="Left" Height="40" Margin="140,140,0,0" VerticalAlignment="Top" Width="120" FontWeight="Bold" Foreground="#FF4084BD" Click="bt_Click"> <Button.Background> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFF3F3F3" Offset="0"/> <GradientStop Color="#FFE6C041"/> <GradientStop Color="#FFE8C382" Offset="1"/> </LinearGradientBrush> </Button.Background> </Button> </Grid> </Window> 

Any ideas on what might be the issue here?

+4
source share
3 answers
  String indata = sp.ReadExisting(); sp.DiscardOutBuffer(); sp.DiscardInBuffer(); 

This is very unreasonable, the port will continue to receive data at the time of calling sp.ReadExisting (). At the high transfer rate that you use, there are non-zero coefficients when another byte was received, when ReadExisting () returns. Your call to DiscardInBuffer () will destroy it.

Delete all calls to DiscardOutBuffer and DiscardInBuffer. They are not cleared; they can lead to accidental data loss. They should only be used for the reset protocol to clear driver buffers; you do not have a protocol.

0
source

Serial port communications are subject to data transfer errors. You need to implement some kind of low-level protocol to ensure successful communication.

For example, you can include a checksum for each transmitted data frame. If this checksum does not match the checksum of the received data, then the receiving application may request the sending of the previous frame.

0
source

If someone had the same problem, here is the workaround I chose. This is disgusting and does not explain the causes of this byte loss (which I had in my project, although I used a different approach and did not flush the buffer), but it can work as a quick fix.

Just add a control character at the beginning of each message (in my case, I could use '0' , but 0x00 or another could be used as well). On the receiver side, if the message begins with this character, ignore the latter; otherwise, the control character has been discarded and the message actually received is a “payload”.

So, in the pseudo code (sorry if my pseudo code is Python), with '0' as the control character:

 // Sender message = "hello" send("0" + message) // Receiver message = read_port() if message[0] == '0': message = message[1:] 

Please note that this is not a viable solution, but only a fix.

0
source

Source: https://habr.com/ru/post/1499446/


All Articles