4

我在 c# 中使用串行端口组件,它运行良好!但问题是如何才能更快地处理高速(例如 2 Mbps)数据传输。

正如我对此进行的研究一样,我发现可以直接访问内存(使用 DMA 像这个链接)。谁能告诉我如何在我的应用程序中定义和使用它?

4

3 回答 3

8

No, the [c#] tag puts this a million miles out of reach. The code snippet on that web page is not real, it is just a "pattern". It does things you cannot do in C#, like handling interrupts, obtaining the physical memory address of buffers, directly programming the device registers. On the kind of machines that can execute C# code, not counting the Micro Framework, this can only be done by device drivers.

It would be the kind of code that could run on a micro-controller, the kind of processor that doesn't run with a protected-mode operating system. Even then it is stretch, it invokes DMA by unstated magic, never actually starting the transfer on a transmit for example. No sign of a DMA controller either, required to arbitrate bus access between devices. It is fake code.

When you use real hardware you always get a device driver with it that takes care of talking to the device. If the device actually supports DMA, very unusual, then the device driver programmer would not avoid using it. The SerialPort class you use in a C# program uses the operating system api, one that's universal for any kind of serial port device. It passes your I/O requests to the device driver to get the job done.

The interface between the operating system api and the device driver is covered by IOCTLs. This MSDN page documents the ones for Windows. There's a pretty close match between the IOCTLs and the api, the api layer is pretty thin. When you take a closer look, it will be obvious that none of them have anything to do with DMA. They can't, it is strictly a driver implementation detail.

于 2015-06-06T15:54:26.820 回答
1

我相信您不需要更快地进行串行访问,而是调整您的 c# 应用程序以更快地处理数据传输。运行您选择的分析器并测量在串行端口组件的方法中花费的时间百分比。我预测这将是相当低的,这意味着任何使串行端口更快的努力都将徒劳无功。

于 2015-06-07T12:55:37.873 回答
1

你完全错了。

首先,您处于无法直接访问硬件(Windows)的环境中,因此如果不编写内核驱动程序,您所描述的事情基本上是不可能的(相信我,您不想这样做)。

其次,操作系统和它的驱动程序已经非常优化,如果它需要使用 DMA 传输,它应该已经这样做了。

第三,除非您的串行控制器支持,否则您将无法获得这些速度,而且它们通常不支持,PC 的 RS232 控制器通常高达 115200 波特,但有些控制器高达 1Mb。

但是还有另一种选择,不用 USB 去 USB :D

根据您的问题,我想您正在将某种类型的微控制器与 PC 连接,并且您不想为控制器编写 USB 驱动程序(或者它没有 USB 功能),所以一个很好的选择是使用 RS-232 转 USB 电缆,通常支持非常快的速度,我个人使用过 FTDI RS-232 3v3,它最高可达 3Mb(http://www.ftdichip.com/Support/Documents/DataSheets/Cables /DS_TTL-232R_CABLES.pdf)。

最后,您将编写一个普通的串行端口代码,但它将使用更扩展的 USB 接口(这是另一个优势,并非所有今天的 PC 都带有串行端口)。

之后,要真正从加速中受益,请记住为端口设置一个非常大的读/写缓冲区(至少 1Mb),执行非阻塞接收例程并发送大块数据(必须适合写入缓冲)。

请记住,您的设备必须与所选速度匹配,因此,如果您将其设置为 2-3Mbps,您的设备必须以完全相同的速度运行串行接口。

这是我所描述的接收部分的示例:

    SerialPort sp;
    Queue<byte[]> buffer = new Queue<byte[]>();
    AutoResetEvent dataAvailable = new AutoResetEvent(false);
    Thread processThread;

    public void Start()
    {
        //Start the processing thread
        processThread = new Thread(ProcessData);
        processThread.Start();

        //Open the serial port at 3Mbps and with buffers of 3Mb
        sp = new SerialPort("COM12", 3145728, Parity.None, 8, StopBits.One);
        sp.ReadBufferSize = 1024 * 1024 * 3;
        sp.WriteBufferSize = 1024 * 1024 * 3;
        sp.DataReceived += sp_DataReceived;
        sp.Open();
    }

    //This thread processes the stored chunks doing the less locking possible
    void ProcessData(object state)
    {

        while (true)
        {

            dataAvailable.WaitOne();

            while (buffer.Count > 0)
            {

                byte[] chunk;

                lock (buffer)
                    chunk = buffer.Dequeue();

                //Process the chunk here as you wish

            }

        }

    }

    //The receiving function only stores data in a list of chunks
    void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        while (sp.BytesToRead > 0)
        { 
            byte[] chunk = new byte[sp.BytesToRead];
            sp.Read(chunk, 0, chunk.Length);

            lock (buffer)
                buffer.Enqueue(chunk);

            dataAvailable.Set();
        }
    }
于 2015-06-11T12:58:41.317 回答