我在c#中使用串行口组件,它工作得很好!但问题是如何更快地处理高速(例如2 Mbps)数据传输。
由于我已经对此进行了研究,我发现内存可以直接访问(使用DMA,如此链接 )。有人能告诉我如何在我的应用程序中定义和使用它吗?
发布于 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无关。他们不能,严格来说这是驱动程序实现的细节。
发布于 2015-06-07 12:55:37
我相信您不需要更快地进行串行访问,而是调优c#应用程序以更快地处理数据传输。运行您选择的分析器,并测量序列化组件的方法所花费的时间百分比。我预测这将非常低,这意味着任何使串行口更快的努力都将白费。
发布于 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,则设备必须以完全相同的速度运行串行接口。
下面是我所描述的接收部分的一个例子:
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();
}
}https://stackoverflow.com/questions/30499210
复制相似问题