Pregunta

I'm currently working on a project with a FTDI chip.

I'm programming in C# and I tried one of the examples (the 3rd one with the data loopback) on the FTDI website.

The code is working, I'm able to write "Hello world" and read it back. In this case, we know how much data we're expecting to get back from the buffer :

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

But what if I want to read all the data and I don't how much data I can expect to get back from the buffer ?

Thanks

¿Fue útil?

Solución

Use event driven methodology;

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; }
        }
    }
}

Otros consejos

Another option to use event-driven methodology is to use the actual event notification mechanism from the FTDI library, which is particularly well-suited for streaming:

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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top