1

我们正在构建一个可以从 sim900a 模块发送和接收短信的应用程序,该模块与带有 windows 10 iot 核心的 raspberry-pi 接口。

在 windows 窗体应用程序中:- 我们将通过调用 SerialPort 实例的 ReadExisting 方法来读取串行数据;它返回部分响应,因此我们必须循环并附加数据,直到我们收到的串行数据包含子字符串“OK”或“\r\n>”,这意味着我们已经完全读取了 AT 命令响应。

do
{
  if (receiveNow.WaitOne(timeout, false)) 
  {   
     string data = port.ReadExisting();
     serialPortData += data;  
  }
}while (!serialPortData.EndsWith("\r\nOK\r\n") &&
    !serialPortData.EndsWith("\r\n> ") && 
    !serialPortData.EndsWith("\r\nERROR\r\n"));

如何在通用 Windows 平台(uwp)中做同样的事情

我已经使用了这些命令,但它部分读取(直到 \r \n),其余部分未被读取。

Task<UInt32> loadAsyncTask;
uint ReadBufferLength = 1024;

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

// Launch the task and wait
UInt32 bytesRead = await loadAsyncTask;
if (bytesRead > 0)
        {
            rcvdText.Text = dataReaderObject.ReadString(bytesRead);
            status.Text = "bytes read successfully!";
        }
4

1 回答 1

0

看看SerialDevice类。它可以从 USB vendorID/productID 或名称(例如 COM1)创建。它提供对串行端口的基于流的访问。

我对它没有经验(正在进行中),但它似乎是 UWP 的必经之路。

这是我目前在 UWP 中进行串行通信的尝试(尚未测试!):

using SerialCommunication.Contracts.DataTypes;
using SerialCommunication.Contracts.Interfaces;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;

namespace SerialCommunication
{
    public class SerialPort : ISerialPort, IDisposable
    {
        public SerialPort(string portName)
        {
            PortName = portName;
            AdvancedQuery = SerialDevice.GetDeviceSelector(portName);
        }
        public SerialPort(ushort vendorId, ushort productId)
        {
            PortName = $"{nameof(vendorId)}={vendorId} {nameof(productId)}={productId}";
            AdvancedQuery = SerialDevice.GetDeviceSelectorFromUsbVidPid(vendorId, productId);
        }

        public void Dispose() => Disconnect();

        public string PortName { get; }
        public string AdvancedQuery { get; }
        public bool IsConnected => serialPort != null;
        public int WriteTimeoutMilliseconds { get; set; }
        public int ReadTimeoutMilliseconds { get; set; }
        public uint BaudRate { get; set; }
        public SerialParity Parity { get; set; } = SerialParity.None;
        public SerialStopBitCount StopBits { get; set; } = SerialStopBitCount.One;
        public ushort DataBits { get; set; } = 8;
        public SerialHandshake Handshake { get; set; } = SerialHandshake.None;
        public InputStreamOptions InputStreamOptions { get; set; } = InputStreamOptions.ReadAhead;
        public UnicodeEncoding Encoding { get; set; } = UnicodeEncoding.Utf8;
        public ByteOrder ByteOrder { get; set; } = ByteOrder.LittleEndian;

        public bool Connect()
        {
            lock (serialPortLock)
            {
                CreateSerialDevice().Wait();

                // serial port
                serialPort.WriteTimeout = TimeSpan.FromMilliseconds(WriteTimeoutMilliseconds);
                serialPort.ReadTimeout = TimeSpan.FromMilliseconds(ReadTimeoutMilliseconds);
                serialPort.BaudRate = BaudRate;
                serialPort.Parity = Parity;
                serialPort.StopBits = StopBits;
                serialPort.DataBits = DataBits;
                serialPort.Handshake = Handshake;

                // output stream
                dataWriter = new DataWriter(serialPort.OutputStream);
                dataWriter.UnicodeEncoding = Encoding;
                dataWriter.ByteOrder = ByteOrder;

                // input stream
                dataReader = new DataReader(serialPort.InputStream);
                dataReader.InputStreamOptions = InputStreamOptions;
                dataReader.UnicodeEncoding = Encoding;
                dataReader.ByteOrder = ByteOrder;

                // start reader
                ReadWorker();

                return IsConnected;
            }
        }

        public void Disconnect()
        {
            lock (serialPortLock)
            {
                if (serialPort == null) return;

                continuousReadData = false;


                serialPort?.Dispose();
                serialPort = null;
            }
        }

        private async Task CreateSerialDevice()
        {
            var foundDevices = await DeviceInformation.FindAllAsync(AdvancedQuery);
            if (foundDevices.Count == 0) throw new SerialPortException($"No device found: {nameof(PortName)}={PortName} {nameof(AdvancedQuery)}={AdvancedQuery}");

            var deviceId = foundDevices[0].Id;
            serialPort = await SerialDevice.FromIdAsync(deviceId);
            if (serialPort == null) throw new SerialPortException($"Error creating device: {nameof(PortName)}={PortName} {nameof(AdvancedQuery)}={AdvancedQuery} {nameof(deviceId)}={deviceId}");
        }

        public void Write(byte[] bytes, int index = 0, int count = -1)
        {
            if (count < 0) count = bytes.Length - index;

            byte[] tmp = new byte[count];
            Array.Copy(bytes, index, tmp, 0, count);
            WriteBytes(tmp);
        }

        public void InjectAndDispatch(byte[] receivedBytes)
        {
            lock (listeners)
            {
                foreach (var listener in listeners)
                    if (listener.IsActive)
                        listener.AddBytes(receivedBytes);
            }
        }

        private async void ReadWorker()
        {
            continuousReadData = true;

            while (continuousReadData)
            {
                await dataReader.LoadAsync(1);

                byte[] receivedBytes = new byte[dataReader.UnconsumedBufferLength];
                dataReader.ReadBytes(receivedBytes);

                lock (listeners)
                    foreach (var listener in listeners)
                        if (listener.IsActive)
                            listener.AddBytes(receivedBytes);
            }

            dataReader.Dispose();
        }

        private async void WriteBytes(params byte[] bytes)
        {
            dataWriter.WriteBytes(bytes);

            await dataWriter.StoreAsync();
            await dataWriter.FlushAsync();
        }

        private readonly object serialPortLock = new object();
        private SerialDevice serialPort;
        private DataWriter dataWriter;
        private DataReader dataReader;
        private volatile bool continuousReadData = true;

        #region listeners
        public IListener AddListener()
        {
            lock (listenersLock)
            {
                var listener = new Listener();
                listeners.Add(listener);
                return listener;
            }
        }
        public void RemoveListener(IListener listener)
        {
            lock (listenersLock)
                listeners.Remove(listener as IListenerInternal);
        }

        private readonly object listenersLock = new object();
        private readonly List<IListenerInternal> listeners = new List<IListenerInternal>();

        class Listener : IListenerInternal
        {
            private bool _IsActive;
            public bool IsActive
            {
                get { return _IsActive; }
                set
                {
                    if (_IsActive != value)
                    {
                        _IsActive = value;
                        Clear();
                    }
                }
            }

            public void AddBytes(byte[] bytes)
            {
                lock (receivedBytesLock)
                    receivedBytes.AddRange(bytes);

                BytesReceived?.Invoke(this, EventArgs.Empty);
            }
            public event EventHandler BytesReceived;

            public byte[] GetReceivedBytesAndClear()
            {
                lock (receivedBytesLock)
                {
                    var bytes = receivedBytes.ToArray();
                    receivedBytes.Clear();
                    return bytes;
                }
            }

            public byte[] GetReceivedBytes()
            {
                lock (receivedBytesLock)
                    return receivedBytes.ToArray();
            }

            public void Clear()
            {
                lock (receivedBytesLock)
                    receivedBytes.Clear();
            }

            public void Trim(int length)
            {
                lock (receivedBytesLock)
                {
                    var count = receivedBytes.Count;
                    if (count > length)
                        receivedBytes.RemoveRange(0, count - length);
                }
            }

            private readonly object receivedBytesLock = new object();
            private readonly List<byte> receivedBytes = new List<byte>();
        }
        #endregion
    }
}

此外,我在使用带有字符串(ReadExisting 等)的 System.IO.SerialPort(.NET Framework 的)时遇到了麻烦。有时编码似乎很难创造出好的结果。我总是将它与字节数组一起使用 - 更少的麻烦,更多的乐趣!

于 2017-09-05T08:30:35.093 回答