希望有人能够帮助我。我正在创建一个在Raspberry Pi2 / Windows IOT核心上运行的c#UWP应用程序。我需要读取2个串行设备的输入(由外部按钮/ PLC触发)以计算某些值。我能够一次读取其中一个设备,但到目前为止还无法获得两者的价值。我根据示例编写了序列代码,并且我试图从主页面调用它。无论到目前为止我改变了什么,第一个设备返回一个值,第二个设备没有返回值(串行处理程序中等待的任务立即返回null,而不是等待一个值通过串口)。
编辑:在做了一些额外的故障排除后,我发现了以下内容 - 当我尝试停止调试时,Visual Studio冻结(无法进行UI交互,但调试监控仍在更新),并且停止此操作的唯一方法是拔出我的笔记本电脑(和串口到USB电缆)对接,此时VS再次正常运行。此外,我似乎得到错误"请求的资源正在使用中。 (HRESULT的例外情况:0x800700AA)"在串口上的while(true)循环的第二次迭代中不起作用。调用串口的代码是:
private async Task listenForDeviceInput()
{
string weight;
string area;
//var areaTask = cognosCamera.Listen();
//var weightTask = weighTable.Listen();
Task <string> areaTask = cognosCamera.Listen();
Task <string> weightTask = weighTable.Listen();
await Task.WhenAll(areaTask, weightTask);
weight = await weightTask;
area = await areaTask;
weight = weight.TrimEnds("\r");
area = area.TrimEnds("\r");
AddNewHide(weight, area);
saveHide();
listenForDeviceInput(); //removed the await here to see what happens
}
串行处理在这里:
// 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 SerialDeviceHandler
{
public sealed partial class SerialPort
{
/// <summary>
/// Private variables
/// </summary>
private SerialDevice serialPort = null;
DataWriter dataWriteObject = null;
DataReader dataReaderObject = null;
private ObservableCollection<DeviceInformation> listOfDevices;
private CancellationTokenSource ReadCancellationTokenSource;
/// <summary>
/// ListAvailablePorts
/// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
/// - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed
/// </summary>
/// <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
/// - Start listening on the serial port input
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public async Task OpenSerialPort(string entry)
{
try
{
serialPort = await SerialDevice.FromIdAsync(entry);
if (serialPort == null) return;
// 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;
serialPort.Handshake = SerialHandshake.None;
// Create cancellation token object to close I/O operations when closing the device
ReadCancellationTokenSource = new CancellationTokenSource();
//Listen();
}
catch (Exception ex)
{
//status.Text = ex.Message;
//comPortInput.IsEnabled = true;
//sendTextButton.IsEnabled = false;
}
}
/// <summary>
/// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream
/// </summary>
/// <returns></returns>
/// <summary>
/// - Create a DataReader object
/// - Create an async task to read from the SerialDevice InputStream
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public async Task<String> Listen()
{
string result;
try
{
if (serialPort != null)
{
dataReaderObject = new DataReader(serialPort.InputStream);
// keep reading the serial input
while (true)
{
result = await ReadAsync(ReadCancellationTokenSource.Token);
if(result != "Nothing" || result == null)
{
return result;
}
}
}
return "Failed";
}
catch (TaskCanceledException tce)
{
//status.Text = "Reading task was cancelled, closing device and cleaning up";
CloseDevice();
return "Task Cancelled";
}
catch (Exception ex)
{
//status.Text = ex.Message;
return "Task Errored";
}
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<string> ReadAsync(CancellationToken cancellationToken)
{
Task<UInt32> loadAsyncTask;
uint ReadBufferLength = 1024;
// 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;
using (var childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
// Create a task object to wait for data on the serialPort.InputStream
loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(childCancellationTokenSource.Token);
// Launch the task and wait
UInt32 bytesRead = await loadAsyncTask;
if (bytesRead > 0)
{
return dataReaderObject.ReadString(bytesRead);
//status.Text = "bytes read successfully!";
}
return "Nothing";
}
}
/// <summary>
/// CancelReadTask:
/// - Uses the ReadCancellationTokenSource to cancel read operations
/// </summary>
public 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;
}
}
}
据我所知,2个串口对象似乎是正确创建的(基于这样一个事实,即如果我注释掉另一个的初始化,我可以从每个端口获取一个值)。我将2个串行对象初始化为:
private async System.Threading.Tasks.Task InitializeSerialDevicesAsync()
{
weighTable = new SerialPort();
cognosCamera = new SerialPort();
await weighTable.OpenSerialPort(scaleComPort);
await cognosCamera.OpenSerialPort(cameraComPort);
}
我知道我可能只是在做一些愚蠢的事情,但任何帮助都会非常感激。在这一点上,我只是想让它在普通PC上工作,然后才能开始处理Pi上的驱动程序问题等。
答案 0 :(得分:0)
好的 - 所以我已经解决了问题,但不明白为什么。我将USB转换为串行电缆到另一个品牌(从多产品到FTDI),现在应用程序在笔记本电脑和pi上正常运行。