C#:如何确定串口设备的可设置波特率?

时间:2016-07-07 10:29:43

标签: c# winforms serial-port

我刚刚遇到串口问题,但到目前为止找不到答案。如果我做错了,请告诉我或给我一些线索,谢谢。我将尽可能详细地解释整个情况并最终提出我的问题。到此为止。

我使用FTDI FT232RL芯片购买了一个USB转TTL转换器,并对串行网络如何工作以及如何用C#编写自己的程序而不是使用超级终端感到好奇。我开始编写程序,阅读一些教程,让自己快速入门。在完成教程之后,我注意到我所阅读的所有教程在波特率设置方面都使用了类似的方法。他们将典型的波特率硬编码到代码中,而不是询问设备是否支持它。我总是尽量把程序写成通用的,因此,我开始研究如何从设备中获取检索信息。搜索之后,我发现this post answered by HiteshP非常有用,并继续使用帖子中建议的反射方法。所以这就是我的代码:

private void UpdateBaudRateCollection()
{
    mySerialPort.PortName = cboAllPortNames.SelectedItem.ToString();
    mySerialPort.Open();
    object p = mySerialPort.BaseStream.GetType().GetField("commProp", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(mySerialPort.BaseStream);
    int dwSettableBaud = (int)p.GetType().GetField("dwSettableBaud", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p);
    mySerialPort.Close();
    MessageBox.Show(dwSettableBaud.ToString("X"));
}

我从MessageBox获得的结果是10066B70,我不知道它代表什么,因为它是not shown in Microsoft's COMMPROP structure

我做了更多的搜索,试图找出10066B70的意思,但在我遇到AmundGjersøeBasic serial port listening application之前找不到任何答案。也许我必须使用10066B70执行AND操作以及Microsoft的COMMPROP结构给出的所有值。所以我把值扔进了函数。

private void SettableBaudRateOfDevice(int settableBaudRate)
{
    const int BAUD_075 = 0x00000001;
    const int BAUD_110 = 0x00000002;
    const int BAUD_150 = 0x00000008;
    const int BAUD_300 = 0x00000010;
    const int BAUD_600 = 0x00000020;
    const int BAUD_1200 = 0x00000040;
    const int BAUD_1800 = 0x00000080;
    const int BAUD_2400 = 0x00000100;
    const int BAUD_4800 = 0x00000200;
    const int BAUD_7200 = 0x00000400;
    const int BAUD_9600 = 0x00000800;
    const int BAUD_14400 = 0x00001000;
    const int BAUD_19200 = 0x00002000;
    const int BAUD_38400 = 0x00004000;
    const int BAUD_56K = 0x00008000;
    const int BAUD_57600 = 0x00040000;
    const int BAUD_115200 = 0x00020000;
    const int BAUD_128K = 0x00010000;
    const int BAUD_USER = 0x10000000;

    cboBaudRate.Items.Clear();

    if ((settableBaudRate & BAUD_075) > 0)
        cboBaudRate.Items.Add(75);
    if ((settableBaudRate & BAUD_110) > 0)
        cboBaudRate.Items.Add(110);
    if ((settableBaudRate & BAUD_150) > 0)
        cboBaudRate.Items.Add(150);
    if ((settableBaudRate & BAUD_300) > 0)
        cboBaudRate.Items.Add(300);
    if ((settableBaudRate & BAUD_600) > 0)
        cboBaudRate.Items.Add(600);
    if ((settableBaudRate & BAUD_1200) > 0)
        cboBaudRate.Items.Add(1200);
    if ((settableBaudRate & BAUD_1800) > 0)
        cboBaudRate.Items.Add(1800);
    if ((settableBaudRate & BAUD_2400) > 0)
        cboBaudRate.Items.Add(2400);
    if ((settableBaudRate & BAUD_4800) > 0)
        cboBaudRate.Items.Add(4800);
    if ((settableBaudRate & BAUD_7200) > 0)
        cboBaudRate.Items.Add(7200);
    if ((settableBaudRate & BAUD_9600) > 0)
        cboBaudRate.Items.Add(9600);
    if ((settableBaudRate & BAUD_14400) > 0)
        cboBaudRate.Items.Add(14400);
    if ((settableBaudRate & BAUD_19200) > 0)
        cboBaudRate.Items.Add(19200);
    if ((settableBaudRate & BAUD_38400) > 0)
        cboBaudRate.Items.Add(38400);
    if ((settableBaudRate & BAUD_56K) > 0)
        cboBaudRate.Items.Add(56000);
    if ((settableBaudRate & BAUD_57600) > 0)
        cboBaudRate.Items.Add(57600);
    if ((settableBaudRate & BAUD_115200) > 0)
        cboBaudRate.Items.Add(115200);
    if ((settableBaudRate & BAUD_128K) > 0)
        cboBaudRate.Items.Add(128000);
    if ((settableBaudRate & BAUD_USER) > 0)
        cboBaudRate.Items.Add(3000000);
}

运行程序后,我得到以下波特率:

300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 3000000

在我将其与Windows设备管理器中显示的值进行比较之前,它确实很有用。设备管理器的波特率为:

300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600

我能理解波特率:3000000没有显示,因为我自己定义了它,但其余的值是从哪里来的?我开始想知道它可能是在驱动程序中定义的。我开始深入挖掘并找到了FTDI的文件 AN232B-05 Configuring FT232R, FT2232 and FT232B Baud Rates。在文档中,它说明了FTDI的驱动程序配置文件(ftdiport.inf)。我搜索它,并在Windows系统文件夹下找到它。条目如下所示:

[FtdiPort.NT.HW.AddReg]
HKR,,"ConfigData",1,11,00,3F,3F,10,27,00,00,88,13,00,00,C4,09,00,00,E2,04,00,00,71,02,00,00,38,41,00,00,9C,80,00,00,4E,C0,00,00,34,00,00,00,1A,00,00,00,0D,00,00,00,06,40,00,00,03,80,00,00,00,00,00,00,D0,80,00,00

与FTDI文档第2.3节“使用附加FT232B子整数除数进行别名”中显示的内容相同。按照2.3节中的说明并从ftdiport.inf翻译ConfigData,我得到以下波特率:

300, 600, 1200, 2400, 4800, 9600, 19230, 38461, 57692, 115384, 230769, 461538, 923076, 14406

同样,它与设备管理器显示的内容不同。让我想知道设备管理器中的波特率是否也是硬编码的。

我还试过计算一​​下来自设备管理器的波特率:1800在ftdiport.inf文件中的样子:

Required divisor = 3000000/1800 = 1666.666
Divisor = 1666
Sub-integer divisors = 0.6666
Closest Sub-integer divisors = 0.625
Closest achievable baud rate = 3000000/1666.625 = 1800.045  
Error = (1800.045-1800)/1800*100 = 0.0025%

错误完全在文档中所述的允许的+/- 3%误差范围内,因此ftdiport.inf中的数据条目应该具有如下内容:

1666.625 Dec = 00014682 Hex
Data entry after re-order: 00014682 Hex => 82,46,01,00

相反,[82,46,01,00]在ftdiport.inf文件中找不到。我还从COMMPROP执行了dwMaxBaud并获得了结果10000000,其中引用了:

BAUD_USER (0x10000000): Programmable baud rate.

这意味着用户可以使用他们喜欢的任何波特率,只要它满足发送器和接收器的波特率并且在误差范围内,对吧? (只是确保我没有弄错,因为我的大脑开始有点模糊)

所以到现在为止,我很困惑,因为我脑中有三种不同的结果:

  1. 我的程序中的10066B70是什么意思?
  2. 与10066B70执行AND操作的设备管理器的波特率值相比,结果不同。这是它的意图吗?
  3. 设备管理器的波特率值和FTDI文档的结果不同。我不知道哪一个值得信任,因为两者都是正式的?
  4. 再次感谢您阅读我刚写的所有内容,我知道它很长。希望有人能够为我的问题提供一些答案。

    *注意:我没有达到10个声誉,因此我不能发布超过2个链接,因此我将链接放在评论中。再次感谢您的理解。

1 个答案:

答案 0 :(得分:1)

Fernhill制作的软件可以自动快速地尝试大量的串口设置组合,看看哪些会产生某种有意义的响应。

Modbus Serial Autodetect Wizard