1

我目前正在开发一个带有 FTDI 芯片的项目。

我正在使用 C# 进行编程,并在 FTDI 网站上尝试了其中一个示例(第三个带有数据环回的示例)。

该代码正在运行,我可以编写“Hello world”并将其读回。在这种情况下,我们知道我们期望从缓冲区返回多少数据:

// Perform loop back - make sure loop back connector is fitted to the device
// Write string data to the device
   string dataToWrite = "Hello world!";
   UInt32 numBytesWritten = 0;

// Note that the Write method is overloaded, so can write string or byte array data
   ftStatus = myFtdiDevice.Write(dataToWrite, dataToWrite.Length, ref numBytesWritten);

   if (ftStatus != FTDI.FT_STATUS.FT_OK)
   {
       // Wait for a key press
       Console.WriteLine("Failed to write to device (error " + ftStatus.ToString() + ")");
       Console.ReadKey();
       return;
   }

   // Check the amount of data available to read
   // In this case we know how much data we are expecting, 
   // so wait until we have all of the bytes we have sent.
   UInt32 numBytesAvailable = 0;
   do
   {
       ftStatus = myFtdiDevice.GetRxBytesAvailable(ref numBytesAvailable);

       if (ftStatus != FTDI.FT_STATUS.FT_OK)
       {
           // Wait for a key press
           Console.WriteLine("Failed to get number of bytes available to read (error " + ftStatus.ToString() + ")");
           Console.ReadKey();
           return;
       }
       Thread.Sleep(10);
    } while (numBytesAvailable < dataToWrite.Length);

    // Now that we have the amount of data we want available, read it
    string readData;
    UInt32 numBytesRead = 0;

    // Note that the Read method is overloaded, so can read string or byte array data
    ftStatus = myFtdiDevice.Read(out readData, numBytesAvailable, ref numBytesRead);

    if (ftStatus != FTDI.FT_STATUS.FT_OK)
    {
        // Wait for a key press
        Console.WriteLine("Failed to read data (error " + ftStatus.ToString() + ")");
        Console.ReadKey();
        return;
    }
    Console.WriteLine(readData);

但是,如果我想读取所有数据并且我不希望从缓冲区中返回多少数据怎么办?

谢谢

4

2 回答 2

3

使用事件驱动的方法;

using System;
using System.Timers;

namespace Example
{
    public class Program
    {
        private Timer m_timer;
        private event EventHandler<EventArgs<string>> ReadingAvailable;

        protected virtual void OnReadingAvailable(string value)
        {
            EventHandler<EventArgs<string>> handler = ReadingAvailable;
            if (handler != null)
            {
                handler(this, new EventArgs<string>(value));
            }
        }

        public static void Main(string[] args)
        {
            var foo = new Program();
            foo.Initialise();

            Console.ReadLine();
        }

        private void Initialise()
        {
            ReadingAvailable += Program_ReadingAvailable;

            m_timer = new Timer {Interval = 1000};
            m_timer.Elapsed +=timer_Elapsed;
            m_timer.Enabled = true;
            m_timer.Start();

        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
             string readData;
             UInt32 numBytesRead = 0;
             // Note that the Read method is overloaded, so can read string or byte array data
             ftStatus = myFtdiDevice.Read(out readData, numBytesAvailable, ref numBytesRead);

            // add the condition checking here to validate that the readData in not empty.
            OnReadingAvailable(readData);
        }

        private void Program_ReadingAvailable(object sender, EventArgs<string> e)
        {
            string readData= e.Value;
            Console.WriteLine(readData);
        }
    }

    ///
    /// Helper class to parse argument in the EventArg
    public class EventArgs<T> : EventArgs
    {
        private readonly T m_value;

        protected EventArgs()
            : base()
        {
            m_value = default(T);
        }

        public EventArgs(T value)
        {
            m_value = value;
        }

        public T Value
        {
            get { return m_value; }
        }
    }
}
于 2013-06-26T12:31:14.510 回答
1

使用事件驱动方法的另一个选择是使用 FTDI 库中的实际事件通知机制,它特别适合流式传输:

Task.Run(() => ReceiveLoop());

void ReceiveLoop()
{
    var receivedDataEvent = new AutoResetEvent(false);
    myFtdiDevice.SetEventNotification(FT_EVENTS.FT_EVENT_RXCHAR, receivedDataEvent);

    var cancellation = new CancellationTokenSource();  // should be declared in a broader scope
    while (!_cancellation.IsCancellationRequested)
    {
        receivedDataEvent.WaitOne();
        ReadAvailable();
    }
}

void ReadAvailable()
{
    uint rxBytesAvailable = 0;
    myFtdiDevice.GetRxBytesAvailable(ref rxBytesAvailable);
    if (rxBytesAvailable < 1)
        return;
    byte[] bytes = new byte[rxBytesAvailable];
    uint numBytesRead = 0;
    myFtdiDevice.Read(bytes, rxBytesAvailable, ref numBytesRead);
    if (rxBytesAvailable != numBytesRead)
        logger.Warn("something happened")
    DoSomething(bytes);
}
于 2018-03-27T13:59:55.390 回答