首页 > 解决方案 > IoT Core UWP 应用程序在写入以停止 UHF 阅读器后挂在 DataReader.LoadAsync 上

问题描述

我正在 VS2017 中编写一个解决方案,该解决方案由两个需要使用 UHF RFID 阅读器的 UWP 项目组成。一个是 x64 系统,另一个是 ARM(用于 Raspberry Pi 3 - Windows 10 IoT Core)。

我用于这两个项目的部分是:

我正在考虑在两个应用程序(都是 UWP)上使用相同的代码来读取和写入我的 UHF 阅读器的命令。

我的 UHF 阅读器(有一个 RS-232 母端口)直接连接到我笔记本电脑的一个 USB 端口(使用 RS-232 - USB 电缆)。同一个 UHF 阅读器首先连接到 CP2102 USB - TTL 控制器(Reader_GND <-> TTL_GND、Reader_Tx <-> TTL_Rx、Reader_Rx <-> TTL_Tx),该控制器连接到我的 Pi 3 的 USB 2.0 端口之一。

以下代码在两个应用程序上运行并识别各自的设备:

// ...
aqs = SerialDevice.GetDeviceSelector(); 
DeviceInformationCollection dis = await 
DeviceInformation.FindAllAsync(aqs);
// ...

UWP x64 应用程序(在我的笔记本电脑上运行)上的代码找到设备名称“USB-SERIAL CH340”,而 ARM 应用程序(在 Pi 3 上运行)上的相同代码找到“CP2102 USB 到 UART 桥接控制器”。到目前为止,一切都很好。

按照我的 UHF 读卡器的开发人员协议手册,我能够构建发送命令以获取读卡器固件版本、启动读卡器、停止读卡器、获取参数、设置参数和扫描卡(标签 ID)的方法。所有这些方法都适用于 UWP x64 应用程序(笔记本电脑);但是,当我在我的 UWP ARM 应用程序(Pi 3)上运行相同的 Stop Reader 方法时,它会执行 Write 命令,然后在代码 DataReader.LoadAsync() 行上挂起。

这些是它在挂起之前经过的代码行:

// ...
private SerialDevice _serialRFPort = null;
...

public RfidCardReader(SerialDevice device) //SerialDevice device
{
    //configures the serial settings for interfacing with the RFID-Reader board

    _serialRFPort = device;
    _serialRFPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
    _serialRFPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
    _serialRFPort.BaudRate = 9600;
    _serialRFPort.Parity = SerialParity.None;
    _serialRFPort.StopBits = SerialStopBitCount.One;
    _serialRFPort.DataBits = 8;
    _serialRFPort.Handshake = SerialHandshake.None;

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

private async Task<byte[]> SendCommand(byte[] command)
{
   var writeResult = await Write(command); 
   if (writeResult.IsSuccessful)
   {
      //get response from the RFID-Reader
      var readResult = await Read(ReadCancellationTokenSource.Token);
...

private async Task<RfidReaderResult> Write(byte[] writeBytes)
{
    var dataWriter = new DataWriter(_serialRFPort.OutputStream);
...

private async Task<RfidReaderResult> Read(CancellationToken cancellationToken)
{
   DataReader dataReader = new DataReader(_serialRFPort.InputStream);
   ...
        loadAsyncTask = dataReader.LoadAsync(1024).AsTask(childCancellationTokenSource.Token);
        uint numBytesRecvd = await loadAsyncTask;  // <-- HANGS HERE FOREVER! .... :'(
...
// ...

UWP x64 应用程序代码处理 loadAsyncTask,将一个 6 字节数组(值为“0”)返回到变量 numBytesRecvd,而 UWP ARM 应用程序将永远挂起等待 loadAsyncTask(实际上是在执行 DataReader.LoadAsync())。

我认为这个问题可能与 Pi 3 没有“CP2102 USB 到 UART 桥接控制器”的驱动程序有关,但我在 Pi 3 上运行了以下 PowerShell 脚本,我认为它列出了驱动程序(除非我错了):

// ---------------------------------
> devcon.exe driverfiles *
...
USB\VID_10C4&PID_EA60\0001
    Name: Silicon Labs CP210x USB to UART Bridge
...
// ---------------------------------

你们有没有人知道是什么原因导致 DataReader.LoadAsync() 挂在我的 UWP ARM 应用程序(Pi 3)上而不挂在我的 UWP x64 应用程序(笔记本电脑)上?有关如何解决此问题的任何建议?... :(

标签: uwpraspberry-pi3rfiddatareaderwindows-10-iot-core

解决方案


我在基于UWP ARM的项目中有一个用于管理串行总线的类,您可以在下面看到:

class SerialDataBus : IDisposable
{
    private DataReader dataReader;
    private DataWriter dataWriter;

    public SerialDataBus(SerialDevice serialDevice)
    {
        dataReader = new DataReader(serialDevice.InputStream);
        dataWriter = new DataWriter(serialDevice.OutputStream);
        dataReader.InputStreamOptions = InputStreamOptions.Partial;
    }

    public DataReaderLoadOperation LoadAsync(uint count)
    {
        return dataReader.LoadAsync(count);
    }

    public DataWriterStoreOperation StoreAsync()
    {
        return dataWriter.StoreAsync();
    }

    public void ReadBytes(byte[] value)
    {
        dataReader.ReadBytes(value);
    }

    public void Dispose()
    {
        if (dataReader != null)
        {
            dataReader.DetachStream();
            dataReader.Dispose();
        }

        if (dataWriter != null)
        {
            dataWriter.DetachStream();
            dataWriter.Dispose();
        }
    }

    public void WriteBytes(byte[] value)
    {
        dataWriter.WriteBytes(value);
    }
}

我使用SerialDataBus从模块读取并以这种方式写入模块:

  using (SerialDataBus dataBus = new SerialDataBus(serialDevice))
  {
       //If you want write command to module or reader
       dataBus.WriteBytes('Your Command in Byte[] format');
       await dataBus.StoreAsync().AsTask();

       //Read data from module
       uint readByteLenght = await dataBus.LoadAsync(1024).AsTask();
       byte[] buffer = new byte[readByteLenght];
       dataBus.ReadBytes(buffer);
  }

推荐阅读