首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用DMA访问高速串口

用DMA访问高速串口
EN

Stack Overflow用户
提问于 2015-05-28 06:53:35
回答 3查看 3.1K关注 0票数 4

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

由于我已经对此进行了研究,我发现内存可以直接访问(使用DMA,如此链接 )。有人能告诉我如何在我的应用程序中定义和使用它吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-06-06 15:54:26

不,c#标签把这个放远了一百万英里。该网页上的代码片段不是真实的,它只是一个“模式”。它可以完成在C#中不能做的事情,比如处理中断、获取缓冲区的物理内存地址、直接对设备寄存器进行编程。在可以执行C#代码的机器上,不包括,这只能由设备驱动程序来完成。

这将是一种可以在微控制器上运行的代码,一种不使用保护模式操作系统运行的处理器。即使这样,它也是拉伸的,它通过未声明的魔法调用DMA,从没有在传输时实际启动传输。也没有DMA控制器的迹象,需要对设备之间的总线访问进行仲裁。这是假密码。

当您使用真正的硬件时,您总是会得到一个设备驱动程序,它负责与设备对话。如果设备实际上支持DMA,这是非常不寻常的,那么设备驱动程序程序员将不会避免使用它。您在SerialPort程序中使用的C#类使用操作系统api,它对于任何类型的串口设备都是通用的。它将您的I/O请求传递给设备驱动程序以完成工作。

操作系统api和设备驱动程序之间的接口由IOCTL覆盖。此MSDN页面记录了Windows的文档。IOCTL和api之间有非常接近的匹配,api层非常薄。当您仔细观察时,很明显,它们都与DMA无关。他们不能,严格来说这是驱动程序实现的细节。

票数 8
EN

Stack Overflow用户

发布于 2015-06-07 12:55:37

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

票数 1
EN

Stack Overflow用户

发布于 2015-06-11 12:58:41

你完全错了。

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

其次,操作系统及其驱动程序已经非常优化,如果需要使用DMA传输,就应该已经使用了。

第三,除非你的串行控制器支持它,否则你不会获得这样的速度,通常情况下,一个PC的RS232控制器通常高达115200 but,但有些控制器高达1Mb。

但是还有另一种选择,不带USB的转USB :D

从您的问题中,我猜想您正在将某种类型的微控制器与PC进行接口,并且您不想为控制器编写USB驱动程序(或者它不具备USB的能力),所以一个非常好的选择是使用RS-232到USB电缆,这些通常支持非常快的速度,我个人使用过FTDI RS-232 3v3,它高达3Mb (CABLES.pdf)。

最后,您将编程一个正常的串口代码,但它将使用更扩展的USB接口(这是另一个优势,不是所有的PC配备了串行端口)。

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

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

下面是我所描述的接收部分的一个例子:

代码语言:javascript
复制
    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();
        }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30499210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档