2009-07-22 4 views

Antwort

12

Ich habe ein paar Wege gefunden, dies zu tun. Die folgenden beiden Dokumente waren ein Ausgangspunkt

Der Schlüssel ist im folgenden Abschnitt aus dem ersten Dokument

Die einfachste Art und Weise, welche Baudraten zu bestimmen Sind an einer bestimmten seriellen Schnittstelle verfügbar, rufen Sie die GetCommProperties() - Anwendungsprogrammierschnittstelle (API) auf und untersuchen Sie die COMMPROP.dwSettableBau d Bitmaske, um zu bestimmen, welche Baudraten an diesem seriellen Port unterstützt werden.

In diesem Stadium gibt es zwei Möglichkeiten, diese in C# zu tun:

1,0 Verwenden interop (P/Invoke) wie folgt:

definieren folgende Datenstruktur

[StructLayout(LayoutKind.Sequential)] 
struct COMMPROP 
{ 
    short wPacketLength; 
    short wPacketVersion; 
    int dwServiceMask; 
    int dwReserved1; 
    int dwMaxTxQueue; 
    int dwMaxRxQueue; 
    int dwMaxBaud; 
    int dwProvSubType; 
    int dwProvCapabilities; 
    int dwSettableParams; 
    int dwSettableBaud; 
    short wSettableData; 
    short wSettableStopParity; 
    int dwCurrentTxQueue; 
    int dwCurrentRxQueue; 
    int dwProvSpec1; 
    int dwProvSpec2; 
    string wcProvChar; 
} 

Dann definieren Sie die folgenden Signaturen

[DllImport("kernel32.dll")] 
static extern bool GetCommProperties(IntPtr hFile, ref COMMPROP lpCommProp); 
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, 
      int dwShareMode, IntPtr securityAttrs, int dwCreationDisposition, 
      int dwFlagsAndAttributes, IntPtr hTemplateFile); 

Jetzt machen die folgenden Anrufe (siehe http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx)

COMMPROP _commProp = new COMMPROP(); 
    IntPtr hFile = CreateFile(@"\\.\" + portName, 0, 0, IntPtr.Zero, 3, 0x80, IntPtr.Zero); 
    GetCommProperties(hFile, ref commProp); 

Wo portname ist so etwas wie COM ?? (COM1, COM2 usw.). commProp.dwSettableBaud sollte jetzt die gewünschten Informationen enthalten.

2.0 Verwenden C# Reflexion

Reflexion verwendet werden, können die Serialport Base zuzugreifen und von dort die erforderlichen Daten wie folgt:

_port = new SerialPort(portName); 
    _port.Open(); 
    object p = _port.BaseStream.GetType().GetField("commProp", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_port.BaseStream); 
    Int32 bv = (Int32)p.GetType().GetField("dwSettableBaud", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p); 

anzumerken, dass sowohl bei den Verfahren über dem Port (s) muss mindestens einmal geöffnet werden, um diese Daten zu erhalten.


+0

Ich denke, Sie müssen den Griff schließen, wenn Sie fertig sind, indem Sie CloseHandle (hFile) aufrufen –

+0

@ HiteshP: An jeden, der Windows CE verwendet, nehmen Sie die folgenden zwei Änderungen: (1) ändern "Zeichenfolge wcProvChar" auf "Char wcProvChar "in der COMMPROP-Struktur und (2)" coredll.dll "statt" kernel32.dll "für beide P/Invokes verwenden. Beachten Sie, dass Sie das Dateihandle anschließend auch an den COM-Port anschließen sollten, wie Jakub darauf hinweist. – AlainD

0

Ich glaube nicht, dass Sie können.

Ich hatte dieses Problem vor kurzem und endete hart codieren die Baudraten, die ich verwenden wollte.

MSDN sagt einfach, "Die Baudrate muss vom seriellen Treiber des Benutzers unterstützt werden".

+0

Ich lese auch das Gleiche. Ich vermute jedoch, dass es eine Möglichkeit gibt, dies zu tun, da der Gerätemanager diese anzeigt. – HiteshP

+0

Ich vermute, dass dies auch hart codiert sein kann Ich habe ein paar verschiedene serielle Karten in diesem Computer, beide verschiedene Chipsätze, und die Liste der Baudraten ist identisch. Natürlich könnte es der Fall sein, dass beide zufällig genau die gleichen Baudraten unterstützen. Schauen Sie sich diese Win32-Struktur an, sie hat auch fest codierte Werte. – Bryan

+0

Entschuldigung, ich vermasselt den Link http://msdn.microsoft.com/en-us/library/aa363214(VS.85).aspx – Bryan

0
dwSettableBaud gives 268894207 int (0x1006ffff) 
while dwMaxBaud gives 268435456 int (0x10000000) 

Offensichtlich ist dies hilft mir nicht. So ist es das, was ich gerade unter Berufung auf:

using System; 
using System.Collections.Generic; 
using System.IO.Ports; 
using System.Linq; 


    public static readonly List<string> SupportedBaudRates = new List<string> 
{ 
    "300", 
    "600", 
    "1200", 
    "2400", 
    "4800", 
    "9600", 
    "19200", 
    "38400", 
    "57600", 
    "115200", 
    "230400", 
    "460800", 
    "921600" 
}; 

    public static int MaxBaudRate(string portName) 
    { 
     var maxBaudRate = 0; 
     try 
     { 
      //SupportedBaudRates has the commonly used baudRate rates in it 
      //flavor to taste 
      foreach (var baudRate in ConstantsType.SupportedBaudRates) 
      { 
       var intBaud = Convert.ToInt32(baudRate); 
       using (var port = new SerialPort(portName)) 
       { 
        port.BaudRate = intBaud; 
        port.Open(); 
       } 
       maxBaudRate = intBaud; 
      } 
     } 
     catch 
     { 
      //ignored - traps exception generated by 
      //baudRate rate not supported 
     } 

     return maxBaudRate; 
    } 

Die Baudraten in Strings sind, weil sie für ein Kombinationsfeld bestimmt sind.

private void CommPorts_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     var combo = sender as ComboBox; 
     if (combo != null) 
     { 
      var port = combo.Items[combo.SelectedIndex].ToString(); 
      var maxBaud = AsyncSerialPortType.MaxBaudRate(port); 
      var baudRates = ConstantsType.SupportedBaudRates; 
      var f = (SerialPortOpenFormType)(combo.Parent); 
      f.Baud.Items.Clear(); 
      f.Baud.Items.AddRange(baudRates.Where(baud => Convert.ToInt32(baud) <= maxBaud).ToArray()); 
     } 
    } 

Sie können sich auf die Leistung verbessern, wenn Sie die minimale Baudrate von allen seriellen Ports, die Sie öffnen wollen unterstützt wissen. Zum Beispiel scheint mit 115.200 anzufangen, eine sichere untere Grenze für in diesem Jahrhundert hergestellte serielle Häfen zu sein.