我目前正在开发一个使用FTDI芯片的项目。
我正在使用C#编程,我在FTDI网站上尝试了examples之一(带有数据环回的第3个)。
代码正常运行,我可以编写“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);
但是,如果我想读取所有数据并且我没有预期从缓冲区返回多少数据呢?
由于
答案 0 :(得分: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; }
}
}
}
答案 1 :(得分: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);
}