Разрабатываю одну программулину (C# .Net CF)/
Есть КПК (ОС Win Mobile 6.5) и стороннее устройство, обмен данными между которыми осуществляется посредством com-порта.
В качестве реализации функций обмена я использовал класс SerialPort входящий в состав платформы .Net.
В процессе тестирования выяснилось, что на КПК невозможно открыть порт при значении BaudRate > 57600.
Т.е. на 57600 ещё открывает, а на 115200 и тем более 128000 уже нет (ArgumentOutOfRangeException при открытии гарантирован).
Запустив другую программку (разрабатывалась на С++), выяснилось, что порт прекрасно открывается на 115200 (128000 и выше — не пробовал).
Покопавшись на форумах нашел, что не я один столкнулся с подобной проблемой.
Как вариант решения проблемы советуют использовать класс OpenNETCF.IO.Serial.Port (
здесь).
Посмотрел я этот Port, честно говоря не впечатлен, но деваться-то некуда...
В общем переписал я часть кода, заменив стандартный класс SerialPort на OpenNETCF.IO.Serial.Port, вроде как работает ))
Уже после, решил глянуть рефлектором, что там в System.IO.Ports.SerialPort происходит...
Внутри метода Open() вижу сл. строку:
...
this.internalSerialStream = new SerialStream(this.portName, this.baudRate, this.parity, this.dataBits, this.stopBits, this.readTimeout, this.writeTimeout, this.handshake, this.dtrEnable, this.rtsEnable, this.discardNull, this.parityReplace);
...
Ну поток и поток, "захожу" в реализацию конструктора:
...
this.commProp = new UnsafeNativeMethods.COMMPROP();
int lpModemStat = 0;
if (!UnsafeNativeMethods.GetCommProperties(this._handle, ref this.commProp) || !UnsafeNativeMethods.GetCommModemStatus(this._handle, ref lpModemStat))
{
int errorCode = Marshal.GetLastWin32Error();
switch (errorCode)
{
case 0x57:
case 6:
throw new ArgumentException(SR.GetString("Arg_InvalidSerialPortExtended"), "portName");
}
InternalResources.WinIOError(errorCode, string.Empty);
}
if ((this.commProp.dwMaxBaud != 0) && (baudRate > this.commProp.dwMaxBaud))
{
throw new ArgumentOutOfRangeException("baudRate", SR.GetString("Max_Baud", new object[] { this.commProp.dwMaxBaud }));
}
...
Стоит проверка что указанное значение baudRate не должно превышать максимально возможное (commProp.dwMaxBaud).
Метод GetCommProperties(this._handle, ref this.commProp) инициализирует commProp.
Открываем GetCommProperties, там импорт стандартной функции:
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
internal static extern bool GetCommProperties(SafeFileHandle hFile, ref COMMPROP lpCommProp);
Ищу описание GetCommProperties, а за одно и COMMPROP (
здесь)
Что я вижу:
dwMaxBaud инициализируется не "прямым" значением скорости, а значением из перечисления:
BAUD_56K -> 0x00008000
BAUD_57600 -> 0x00040000
BAUD_115200 -> 0x00020000
BAUD_128K -> 0x00010000
и т.д.
Теперь самое интересное — в примерах которые я находил — значение BaudRate указывалось в виде необходимой скорости т.е. 9600, 115200 и т.д.
Т.е. получается , что необходимо указывать значение BaudRate например не 115200, а 131072 (0x00020000)?
Ну и в любом случае проверка "(baudRate > this.commProp.dwMaxBaud)" в таком случае выглядит немного странной, т.к. BAUD_128K будет считается меньшим чем BAUD_115200, или я чего-то не понял?
Здравствуйте, AlexKvs, Вы писали:
AK>Ну и в любом случае проверка "(baudRate > this.commProp.dwMaxBaud)" в таком случае выглядит немного странной, т.к. BAUD_128K будет считается меньшим чем BAUD_115200, или я чего-то не понял?
А что тут странного — обыкновенный баг