gpt4 book ai didi

c# - Windows 通用应用程序串行端口无法打开,SerialDevice.FromIdAsync 始终为空

转载 作者:可可西里 更新时间:2023-11-01 12:59:26 27 4
gpt4 key购买 nike

我正在尝试在 Windows 通用应用程序中使用串行端口。我一直在使用 Microsoft 的 Serial Sample 应用程序作为模板,但是我遇到了一个相当奇怪的问题。

var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
var sp = await SerialDevice.FromIdAsync(dis[0].Id);

这是一个失败的片段。它与原始样本略有不同,因为它连接到具有特定供应商的第一台设备。现在,如果我将此代码段放入 Microsoft 生成的示例应用程序中,串行端口将打开,一切正常。但是,当我将这段代码移到我自​​己的项目中时,它总是从该方法返回 null

这是来自 Microsoft 示例的完整 MainPage.xaml.cs 以及我的提醒:这有效!!

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

using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
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(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
serialPort = await SerialDevice.FromIdAsync(dis[0].Id);

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;

try
{


// 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;
serialPort.Handshake = SerialHandshake.None;

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

// 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;

Listen();
}
catch (Exception ex)
{
status.Text = ex.Message;
comPortInput.IsEnabled = true;
sendTextButton.IsEnabled = false;
}
}
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
/// - Start listening on the serial port input
/// </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;
serialPort.Handshake = SerialHandshake.None;

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

// 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;

Listen();
}
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 + ", ";
status.Text += "bytes written successfully!";
}
sendText.Text = "";
}
else
{
status.Text = "Enter the text you want to write and then click on 'WRITE'";
}
}

/// <summary>
/// - 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 Listen()
{
try
{
if (serialPort != null)
{
dataReaderObject = new DataReader(serialPort.InputStream);

// keep reading the serial input
while (true)
{
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 = 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;

// 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 = "bytes 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;
}
}
}
}

下一个 block 如果来 self 的代码。 ConnectToSerialPort() 中的前两行与之前的测试相同,但是 SerialDevice.FromIdAsync(dis[0].id); 始终为空。 这行不通!!

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;

namespace OpenLab.Kitchen.Receiver
{
public sealed partial class MainPage : Page
{
private List<byte> Bytes { get; set; }

public MainPage()
{
this.InitializeComponent();
Bytes = new List<byte>();
ConnectToSerialPort();
}

private async void ConnectToSerialPort()
{
var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
var sp = await SerialDevice.FromIdAsync(dis[0].Id);

Debug.WriteLine(sp.UsbVendorId);

DeviceInformationCollection serialDevices;

while ((serialDevices = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A))).Count < 1)
{
Debug.WriteLine("Unable to locate...");
}

SerialDevice serialPort;

while ((serialPort = await SerialDevice.FromIdAsync(serialDevices[0].Id)) == null)
{
Debug.WriteLine("Failed to open serial port...");
}

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;

var dataReader = new DataReader(serialPort.InputStream);
var buffer = new byte[1024];

while (true)
{
var bytesRead = await dataReader.LoadAsync((uint)buffer.Length);
dataReader.ReadBytes(buffer);
Bytes.AddRange(buffer.Take((int)bytesRead));

byte[] slipPacket;
while ((slipPacket = Slip.ExtractSlipPacket(Bytes)) != null)
{
var waxPacket = WaxPacketConverter.FromBinary(slipPacket, DateTime.Now);
if (waxPacket != null)
{
Debug.WriteLine(waxPacket);
}
}
}
}
}
}

我已经检查了所有 list 权限以匹配它们并检查了诸如引用的 DLL 版本之类的东西,一切看起来都一样。还检查了像以管理员身份运行 VS 之类的事情,我没有同时打开两个应用程序,所以它不是应该保持端口打开或任何东西......

有没有人有什么想法?

最佳答案

因此,Microsoft 没有提到您需要向应用程序 list 中添加一些内容以进行串行通信,也没有在应用程序 list GUI 中为串行通信勾选复选框。

需要将以下内容添加到您的应用程序 list (如果不存在,请创建 <Capabilities> 部分):

<Capabilities>
<DeviceCapability Name="serialcommunication">
<Device Id="any">
<Function Type="name:serialPort" />
</Device>
</DeviceCapability>
</Capabilities>

更新 10/2016

Microsoft 已更新其文档以反射(reflect)此要求。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx

关于c# - Windows 通用应用程序串行端口无法打开,SerialDevice.FromIdAsync 始终为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34160376/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com