Windows 10 IOT 串行 - 在 RP2 上工作但读取串行数据不完整 [英] Windows 10 IOT serial - Working on RP2 but read serial data incomplete

查看:19
本文介绍了Windows 10 IOT 串行 - 在 RP2 上工作但读取串行数据不完整的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,自从 10 月版本开放串行引脚以来,我一直在试验 IOT 串行示例和 RP2.我使用的是 windows iot 串行示例.有几个问题我想不通.

So I have been experimenting with the IOT serial sample and RP2 since the october release opened up the serial pins. Im using the windows iot serial sample. Have a few issues i cant figure out.

  1. 读取的数据似乎不完整.我有一个 arduino 以 9600 波特率通过串口输出模拟输入读数.在 windows 通用应用程序上,我读了一个完整的行,然后读了一个不完整的行.例如:如果 arduiono 输出值2.25",应用程序将读取一行 2.25 然后下一行.25"(句点前面没有任何内容).我试过应用方面的延迟和 arduino 没有成功.

  1. The read data seems incomplete. I have an arduino outputting an analog input reading through the serial at 9600 baud. On the windows universial app, ill read one complete line then one incomplete line. For example: if the arduiono is outputting a value of "2.25", the app will read one line 2.25 then the next ".25"(without anything in front the period). Ive tried delays on the app side and arduino with no success.

有时尝试连接时,它会抛出格式异常.有时可以断开连接并重新连接,它会正常工作.其他我必须重新启动arduino.

At times when trying to connect, it will throw a formatting exception. Sometimes can hit disconnect and reconnect and it will work fine. Others i have to reboot the arduino.

我在考虑代码示例中的一些内容,因为如果我从笔记本电脑或树莓派运行,我也会遇到同样的问题.

Im thinking its something in the code sample because i have the same issues if i run from laptop or raspberry pi.

这里是程序的c#.我修改了一点.

Here is the c# for the program. i modified a little bit.

// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;

namespace SerialSample
{    
public sealed partial class MainPage : Page
{
    /// <summary>
    /// Private variables
    /// </summary>
    private SerialDevice serialPort = null;
    DataWriter dataWriteObject = null;
    DataReader dataReaderObject = null;

    private ObservableCollection<DeviceInformation> listOfDevices;
    private CancellationTokenSource ReadCancellationTokenSource;

    public MainPage()
    {
        this.InitializeComponent();            
        comPortInput.IsEnabled = false;
        sendTextButton.IsEnabled = false;
        listOfDevices = new ObservableCollection<DeviceInformation>();
        ListAvailablePorts();
    }

    /// <summary>
    /// ListAvailablePorts
    /// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
    /// - Attaches the DeviceInformation to the ListBox source so that       DeviceIds are displayed
    /// </summary>
    private async void ListAvailablePorts()
    {
        try
        {
            string aqs = SerialDevice.GetDeviceSelector();
            var dis = await DeviceInformation.FindAllAsync(aqs);

            status.Text = "Select a device and connect";

            for (int i = 0; i < dis.Count; i++)
            {
                listOfDevices.Add(dis[i]);
            }

            DeviceListSource.Source = listOfDevices;
            comPortInput.IsEnabled = true;
            ConnectDevices.SelectedIndex = -1;
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
        }
    }

    /// <summary>
    /// comPortInput_Click: Action to take when 'Connect' button is clicked
    /// - Get the selected device index and use Id to create the SerialDevice object
    /// - Configure default settings for the serial port
    /// - Create the ReadCancellationTokenSource token
    /// - Add text to rcvdText textbox to invoke rcvdText_TextChanged event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void comPortInput_Click(object sender, RoutedEventArgs e)
    {
        var selection = ConnectDevices.SelectedItems;

        if (selection.Count <= 0)
        {
            status.Text = "Select a device and connect";
            return;
        }

        DeviceInformation entry = (DeviceInformation)selection[0];         

        try
        {                
            serialPort = await SerialDevice.FromIdAsync(entry.Id);

            // Disable the 'Connect' button 
            comPortInput.IsEnabled = false;

            // Configure serial settings
            serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
            serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);                
            serialPort.BaudRate = 9600;
            serialPort.Parity = SerialParity.None;
            serialPort.StopBits = SerialStopBitCount.One;
            serialPort.DataBits = 8;

            // Display configured settings
            status.Text = "Serial port configured successfully!\n ----- Properties ----- \n";
            status.Text += "BaudRate: " + serialPort.BaudRate.ToString() + "\n";
            status.Text += "DataBits: " + serialPort.DataBits.ToString() + "\n";
            status.Text += "Handshake: " + serialPort.Handshake.ToString() + "\n";
            status.Text += "Parity: " + serialPort.Parity.ToString() + "\n";
            status.Text += "StopBits: " + serialPort.StopBits.ToString() + "\n";                            

            // Set the RcvdText field to invoke the TextChanged callback
            // The callback launches an async Read task to wait for data
            rcvdText.Text = "Waiting for data...";

            // Create cancellation token object to close I/O operations when closing the device
            ReadCancellationTokenSource = new CancellationTokenSource();

            // Enable 'WRITE' button to allow sending data
            sendTextButton.IsEnabled = true;
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
            comPortInput.IsEnabled = true;
            sendTextButton.IsEnabled = false;
        }
    }

    /// <summary>
    /// sendTextButton_Click: Action to take when 'WRITE' button is clicked
    /// - Create a DataWriter object with the OutputStream of the SerialDevice
    /// - Create an async task that performs the write operation
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void sendTextButton_Click(object sender, RoutedEventArgs e)
    {
        try
        {                
            if (serialPort != null)
            {
                // Create the DataWriter object and attach to OutputStream
                dataWriteObject = new DataWriter(serialPort.OutputStream);

                //Launch the WriteAsync task to perform the write
                await WriteAsync();
            }
            else
            {
                status.Text = "Select a device and connect";                
            }
        }
        catch (Exception ex)
        {
            status.Text = "sendTextButton_Click: " + ex.Message;
        }
        finally
        {
            // Cleanup once complete
            if (dataWriteObject != null)
            {
                dataWriteObject.DetachStream();
                dataWriteObject = null;
            }
        }
    }

    /// <summary>
    /// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream 
    /// </summary>
    /// <returns></returns>
    private async Task WriteAsync()
    {
        Task<UInt32> storeAsyncTask;

        if (sendText.Text.Length != 0)
        {
            // Load the text from the sendText input text box to the dataWriter object
            dataWriteObject.WriteString(sendText.Text);                

            // Launch an async task to complete the write operation
            storeAsyncTask = dataWriteObject.StoreAsync().AsTask();

            UInt32 bytesWritten = await storeAsyncTask;
            if (bytesWritten > 0)
            {                    
                status.Text = sendText.Text + '\n';
                status.Text += "Bytes written successfully!";
            }
            sendText.Text = "";
        }
        else
        {
            status.Text = "Enter the text you want to write and then click on 'WRITE'";
        }
    }

    /// <summary>
    /// rcvdText_TextChanged: Action to take when text is entered in the 'Read Data' textbox
    /// - Create a DataReader object
    /// - Create an async task to read from the SerialDevice InputStream
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void rcvdText_TextChanged(object sender, TextChangedEventArgs e)
    {
        try
        {
            if (serialPort != null)
            {
                dataReaderObject = new DataReader(serialPort.InputStream);
                await ReadAsync(ReadCancellationTokenSource.Token);
            }
        }
        catch (Exception ex)
        {
            if (ex.GetType().Name == "TaskCanceledException")
            {
                status.Text = "Reading task was cancelled, closing device and cleaning up";
                CloseDevice();
            }
            else
            {
                status.Text = ex.Message;
            }
        }
        finally
        {
            // Cleanup once complete
            if (dataReaderObject != null)
            {
                dataReaderObject.DetachStream();
                dataReaderObject = null;
            }
        }
    }

    /// <summary>
    /// ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task ReadAsync(CancellationToken cancellationToken)
    {
        Task<UInt32> loadAsyncTask;

        uint ReadBufferLength = 128;

        // If task cancellation was requested, comply
        cancellationToken.ThrowIfCancellationRequested();

        // Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
        dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;

        // Create a task object to wait for data on the serialPort.InputStream
        loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);

        // Launch the task and wait
        UInt32 bytesRead = await loadAsyncTask;

        if (bytesRead > 0)
        {

            rcvdText.Text = dataReaderObject.ReadString(bytesRead);
            status.Text = bytesRead.ToString();
            //status.Text = "\nBytes read successfully!";
        }            
    }

    /// <summary>
    /// CancelReadTask:
    /// - Uses the ReadCancellationTokenSource to cancel read operations
    /// </summary>
    private void CancelReadTask()
    {         
        if (ReadCancellationTokenSource != null)
        {
            if (!ReadCancellationTokenSource.IsCancellationRequested)
            {
                ReadCancellationTokenSource.Cancel();
            }
        }         
    }

    /// <summary>
    /// CloseDevice:
    /// - Disposes SerialDevice object
    /// - Clears the enumerated device Id list
    /// </summary>
    private void CloseDevice()
    {            
        if (serialPort != null)
        {
            serialPort.Dispose();
        }
        serialPort = null;

        comPortInput.IsEnabled = true;
        sendTextButton.IsEnabled = false;            
        rcvdText.Text = "";
        listOfDevices.Clear();               
    }

    /// <summary>
    /// closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
    /// - Cancel all read operations
    /// - Close and dispose the SerialDevice object
    /// - Enumerate connected devices
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void closeDevice_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            status.Text = "";
            CancelReadTask();
            CloseDevice();
            ListAvailablePorts();
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
        }          
    }        
}
}

这是 Arduino 草图:

Here is the Arduino Sketch:

void setup() 
{
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

}

// the loop routine runs over and over again forever:
void loop() 
{
// read the input on analog pin 0:  
float sensorValue = analogRead(A3);
sensorValue = (sensorValue / 1023) * 4.30;

// print out the value you read:
Serial.print(sensorValue);
Serial.println("");  
delay(1);        // delay in between reads for stability

}

还有这里是显示问题的快速视频的链接.而且你会知道它第一次连接视频哈哈哈.

And Here is a link to a quick video showing the issue. And you would know that it connected the first time for the video hahaha.

预先感谢所有帮助和建议.

Thanks in advance for all help and suggestions.

推荐答案

我简化了代码.我相信原始代码中的取消令牌可能是问题的一部分.现在它每次都连接并读取:) 如果有人想尝试,这里是代码.

I streamlined the code a good bit. I believe the cancellation tokens in the original code may have been part of the issue. Now it connects and reads every time:) Here is the code if anyone wants to try it out.

using System;
using System.Collections.Generic;
using System.IO;
using Windows.UI.Popups;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Collections.ObjectModel;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;



namespace Serial_Data_Read
{

public sealed partial class MainPage : Page
{

    private SerialDevice serialPort = null;

    DataReader dataReaderObject = null;

    public uint BytesReceived { get; }

    public MainPage()
    {
        this.InitializeComponent();
        ListAvailablePorts();

    }

    private async void ListAvailablePorts()
    {
        try
        {
            string aqs = SerialDevice.GetDeviceSelector();
            var dis = await DeviceInformation.FindAllAsync(aqs);

            var selectedPort = dis.First();
            serialPort = await SerialDevice.FromIdAsync(selectedPort.Id);


            serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
            serialPort.BaudRate = 9600;
            serialPort.Parity = SerialParity.None;
            serialPort.StopBits = SerialStopBitCount.One;
            serialPort.DataBits = 8;

            infoBox.Text = "Serial port configured successfully!\n ----- Properties ----- \n";
            infoBox.Text += "BaudRate: " + serialPort.BaudRate.ToString() + "\n";
            infoBox.Text += "DataBits: " + serialPort.DataBits.ToString() + "\n";
            infoBox.Text += "Handshake: " + serialPort.Handshake.ToString() + "\n";
            infoBox.Text += "Parity: " + serialPort.Parity.ToString() + "\n";
            infoBox.Text += "StopBits: " + serialPort.StopBits.ToString() + "\n";

            data.Text = "configuring port";

        }

        catch (Exception ex)
        {
            infoBox.Text = "OOps, Something went wrong! \n" + ex.Message ;
        }
    }

    private async void data_TextChanged(object sender, TextChangedEventArgs e)
    {
        dataReaderObject = new DataReader(serialPort.InputStream);
        try
        {
            var bytesRecieved = await dataReaderObject.LoadAsync(128);

            if (bytesRecieved > 0)
            {

                data.Text = dataReaderObject.ReadString(bytesRecieved).Trim();
            }

        }
        catch (Exception ex)
        {
            data.Text = ex.Message;
            ListAvailablePorts();
        }
        finally
        {
            if (dataReaderObject != null)
            {
                dataReaderObject.DetachStream();
                dataReaderObject = null;
            }
        }
    }    
}
}

和 xaml...

<Page
x:Class="Serial_Data_Read.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Serial_Data_Read"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
   Width="800" Height="480">

<Grid Background="{ThemeResource AppBarItemDisabledForegroundThemeBrush}">
    <TextBox x:Name="infoBox" HorizontalAlignment="Left" Margin="10,288,0,0" TextWrapping="Wrap" Text="Waiting to establish a connection" VerticalAlignment="Top" Height="182" Width="382"/>
    <TextBox x:Name="data" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Waiting for data" VerticalAlignment="Top" Height="154" Width="780"  TextChanged="data_TextChanged" />
</Grid>

这篇关于Windows 10 IOT 串行 - 在 RP2 上工作但读取串行数据不完整的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆