Windows Iot Core 上的 SerialDevice 读取任务

Reading Task on SerialDevice on Windows Iot Core

我正在尝试编写一个 Task,它将 运行 直到被取消,它将读取 UART 接收到的任何数据,并继续通过定义的 event。我希望读取循环读取 200 毫秒,然后返回它可能在该时间片中读取的任何数据(包括可能为零的数据),或者读取一个完整的缓冲区,以先发生者为准;绝大多数时间超时将首先发生。我已成功从 UART 发送数据,但我未能收到任何数据,即使已确认设备已通过线路接收到数据。

SerialDevice device;

// Instantiate the SerialDevice.

device.ReadTimeout = new TimeSpan( 0, 0, 0, 0, 200 );
ReadDataCancellationTokenSource = new CancellationTokenSource();

const uint BufferSize_bytes = 50;

ReadDataTask = Task.Factory.StartNew( async () =>
{
    using( DataReader reader = new DataReader( device.InputStream ) )
    {
       reader.InputStreamOptions = InputStreamOptions.Partial;

       while( !ReadDataCancellationTokenSource.IsCancellationRequested )
       {
          uint dataRead = await reader.LoadAsync( BufferSize_bytes ).AsTask();

          if( dataRead > 0 )
          {
             IBuffer buffer = reader.ReadBuffer( dataRead );
             if( buffer.Length > 0 )
                PropogateReceivedData( ReadBuffer( buffer ) );
          }
       }
    }
}, ReadDataCancellationTokenSource.Token );

PropogateReceivedData( ReadBuffer( buffer ) )调用读取缓冲区中的所有数据,然后调度数据;已知这可以正常工作。存储 ReadDataCancellationTokenSource 成员以在需要时关闭 Task

考虑到我在尝试采用这种方法时遇到的挑战,我想知道它是否应该起作用,如果不起作用,我需要做什么才能让它起作用。

I have successfully sent data out the UART but I have failed to receive any data even though it has been confirmed the device received the data on the wire.

我不知道你怎么样"confirmed the device received the data on the wire"。当你设置 InputStreamOptions.Partial 时,即使线路上只有一个字节,这条线 await reader.LoadAsync( BufferSize_bytes ).AsTask(); 也会 return 你会在缓冲区中得到这个字节。

另外我也不知道你们是怎么处理PropogateReceivedData( ReadBuffer( buffer ) )中接收到的数据的,这里我用下面几行将数据转换成字符串显示在UI中你可以参考:

                                var dataReader = DataReader.FromBuffer(buffer);
                                rcvdText.Text = dataReader.ReadString(buffer.Length);

我的建议是,如果要获取字符串数据,可以使用 reader.ReadString(dataRead);,如果要获取字节流,则可以使用 reader.ReadBytes(readData);。更多支持的API可以参考DataReader.

Given the challenges I have experienced trying to get this approach, I am wondering if it should work or if not, what I need to do to get it to work.

是的,您的逻辑应该有效,除了我从未发生过读取超时。您能否确认设置 device.ReadTimeout = new TimeSpan( 0, 0, 0, 0, 200 ); 时读取超时对您有效?有没有超时信息?

以下是我从你的问题中得到的完整代码行,它对我有用。

                device.ReadTimeout = new TimeSpan(0, 0, 0, 0, 200);
                var ReadDataCancellationTokenSource = new CancellationTokenSource();

                const uint BufferSize_bytes = 50;

                using (DataReader reader = new DataReader(device.InputStream))
                {
                    reader.InputStreamOptions = InputStreamOptions.Partial;

                    while (!ReadDataCancellationTokenSource.IsCancellationRequested)
                    {
                        uint dataRead = await reader.LoadAsync(BufferSize_bytes).AsTask();

                        if (dataRead > 0)
                        {
                            IBuffer buffer = reader.ReadBuffer(dataRead);
                            if (buffer.Length > 0)
                            {
                                //    rcvdText.Text = reader.ReadString(dataRead);

                                //    var readData = new Byte[dataRead];
                                //    reader.ReadBytes(readData);

                                var dataReader = DataReader.FromBuffer(buffer);
                                rcvdText.Text = dataReader.ReadString(buffer.Length);
                                status.Text = "bytes read successfully!";
                            }
                        }
                    }
                }

Official serial sample可以参考。