Rasberry-pi中的串行通信(串行UART),带有Windows 10 iot核心和sim 900a

时间:2017-04-08 12:21:57

标签: raspberry-pi windows-10-iot-core sim900

我们正在构建一个可以发送和接收来自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!";
        }

1 个答案:

答案 0 :(得分: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
    }
}

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