将FTDI TTL-232R读取到USB

时间:2016-04-19 08:12:00

标签: c# .net serial-port ftdi

我正在尝试使用FTDI RS232转USB 5V可编程电缆通过USB读取RS232输入。使用FTD2XX_NET库。连接到每10秒发送一次电报的智能电表。

一切似乎都很好。我可以设置波特率,数据位,停止位等。但是在读取数据时会停止。下面的代码片段只是没有数据传递。我没有电子方面的经验,所以它有点超出了我的安慰区。

我的问题。

  • 如果设备,FlowControl如何影响读取功能。
  • 如果设备,numBytesAvailable如何影响读取功能。
  • 如果设备,numBytesRead如何影响读取功能。

我不知道设置上述属性的变量。我根本不知道会收到多少数据。任何帮助都将受到高度赞赏。

在此处找到有线数据表: http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf

Smart Meter数据表在这里找到: http://files.domoticaforum.eu/uploads/Smartmetering/DSMR%20v4.0%20final%20P1.pdf

enter code here

namespace P1_reader
{
class Program
{

    static void Main(string[] args)
    {
       if (args.Count() > 0) 
         { 
             ExecuteOption(args[0]); 
         } 
         else 
         { 
             string option; 
             do 
             { 
                 var menu = new StringBuilder(); 
                 menu.AppendLine("(1) ListenForData");
                 menu.AppendLine("(x) Exit"); 

                 System.Console.WriteLine(menu); 
                 option = System.Console.ReadKey().KeyChar.ToString();                     
                 System.Console.WriteLine(); 
                 ExecuteOption(option); 
                 System.Console.WriteLine(); 
             } while (option.ToLower() != "x"); 
         }
    }

     private static void ExecuteOption(string option)
     { 
         switch (option.ToLower()) 
         { 
             case "1": 
                 ListenForData(); 
                 break;
             case "x": 
                 break; 
             default: 
                 System.Console.WriteLine("That's not an option!"); 
                 break; 
         } 
     }

    private static void ListenForData()
    {
        try
        {
            UInt32 ftdiDeviceCount = 0;
            FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OK;

            FTDI myFtdiDevice = new FTDI();

            ftStatus = myFtdiDevice.GetNumberOfDevices(ref ftdiDeviceCount);

            if (ftStatus == FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Number of FTDI devices: " + ftdiDeviceCount.ToString());
                Console.WriteLine("");
            }
            else
            {
                Console.WriteLine("Failed to get number of devices (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            if (ftdiDeviceCount == 0)
            {
                Console.WriteLine("Failed to get number of devices (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            FTDI.FT_DEVICE_INFO_NODE[] ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[ftdiDeviceCount];

            ftStatus = myFtdiDevice.GetDeviceList(ftdiDeviceList);

            if (ftStatus == FTDI.FT_STATUS.FT_OK)
            {
                for (UInt32 i = 0; i < ftdiDeviceCount; i++)
                {
                    Console.WriteLine("Device Index: " + i.ToString());
                    Console.WriteLine("Flags: " + String.Format("{0:x}", ftdiDeviceList[i].Flags));
                    Console.WriteLine("Type: " + ftdiDeviceList[i].Type.ToString());
                    Console.WriteLine("ID: " + String.Format("{0:x}", ftdiDeviceList[i].ID));
                    Console.WriteLine("Location ID: " + String.Format("{0:x}", ftdiDeviceList[i].LocId));
                    Console.WriteLine("Serial Number: " + ftdiDeviceList[i].SerialNumber.ToString());
                    Console.WriteLine("Description: " + ftdiDeviceList[i].Description.ToString());
                    Console.WriteLine("");
                }
            }

            ftStatus = myFtdiDevice.OpenBySerialNumber(ftdiDeviceList[0].SerialNumber);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to open device (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            ftStatus = myFtdiDevice.SetBaudRate(115200);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to set Baud rate (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            ftStatus = myFtdiDevice.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);

            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to set data characteristics (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            ftStatus = myFtdiDevice.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to set flow control (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            // Set read timeout to 12 seconds, write timeout to infinite
            ftStatus = myFtdiDevice.SetTimeouts(12000, 0);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to set timeouts (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }

            UInt32 numBytesAvailable = 0;

            ftStatus = myFtdiDevice.GetRxBytesAvailable(ref numBytesAvailable);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Console.WriteLine("Failed to get number of bytes available to read (error " + ftStatus.ToString() + ")");
                Console.ReadKey();
                return;
            }
            Thread.Sleep(10);

            string readData = "";
            UInt32 numBytesRead = 0;
            byte[] dataBuffer = new byte[1024];

            ftStatus = myFtdiDevice.Read(out readData, numBytesAvailable, ref numBytesRead);
            while (readData == "")
            {
                ftStatus = myFtdiDevice.Read(out readData, numBytesAvailable, ref numBytesRead);
            }

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

            ftStatus = myFtdiDevice.Close();

            Console.WriteLine("Press any key to continue.");
            Console.ReadKey();
            return;
        }
        catch
        {
            Console.WriteLine("Something realy bad happened..");
        }
    }

}
}

1 个答案:

答案 0 :(得分:0)

FTDI驱动程序具有内部缓冲区,并自动将从RX数据线读取的任何数据复制到此缓冲区中。对GetRxBytesAvailable()的调用将告诉您内部缓冲区内有多少数据,即芯片读取了多少数据。

Read()的调用是阻塞的,它将等到它返回前请求的字节数。如果我没记错的话,您可以使用API​​设置读取超时。

您希望在while循环中进行GetRxBytesAvailable()调用,例如

UInt32 numBytesAvailable = 0;

while (true)
{
    ftStatus = myFtdiDevice.GetRxBytesAvailable(ref numBytesAvailable);
    if (ftStatus != FTDI.FT_STATUS.FT_OK)
    {
        Console.WriteLine("Failed to get number of bytes available to read (error " + ftStatus.ToString() + ")");
        Console.ReadKey();
        break;
    }

    string readData = "";
    UInt32 numBytesRead = 0;
    byte[] dataBuffer = new byte[1024];    

    // TODO: check so you don't over your buffer.
    ftStatus = myFtdiDevice.Read(out readData, numBytesAvailable, ref numBytesRead);

    ProcessData(readData);

    Thread.Sleep(10000); // Sleep 10 seconds.
}