Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serial Port Communication missing one byte

Tags:

c#

wpf

I'm responsible for creating a HMI which will use the USB port to communicate with the device.

I'm new to C# and WPF, so I started researching a bit and found several questions and topics in this site which helped me achieve the starting point I wanted: I'm able to read and write to the SerialPort class.

To test the device I have a UART that echoes back any message it receives. I have a simple form with a text box, a button and a label. Once the button is clicked it sends the text typed in the box to the device (if no text is entered I have a pre defined array of bytes to test). The label is update anytime the port receives bytes.

The code runs ok for the first message (doesn't matter which), but any message sent after that almost always comes back with missing bytes. I have no clue as to why this is happening, I tried discarding the buffers every time, but to no avail.

Here's 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's the 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 of what might be the problem here?

like image 820
Rafael Tarcha Avatar asked Nov 11 '22 22:11

Rafael Tarcha


1 Answers

        String indata = sp.ReadExisting();
        sp.DiscardOutBuffer();
        sp.DiscardInBuffer();

This is very unwise, the port will continue to receive data at the time you call sp.ReadExisting(). At the high baudrate you are using, there are non-zero odds that another byte was received when ReadExisting() returns. Your DiscardInBuffer() call will destroy it.

Remove all calls to DiscardOutBuffer and DiscardInBuffer. They do not flush, they'll only cause random data loss. They should only ever be used for a protocol reset to purge the driver buffers, you don't have a protocol.

like image 139
Hans Passant Avatar answered Nov 14 '22 23:11

Hans Passant