Опять про SerialPort
От: AlexKvs Россия  
Дата: 14.11.10 00:47
Оценка:
Разрабатываю одну программулину (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, или я чего-то не понял?
Re: Опять про SerialPort
От: Jolly Roger  
Дата: 14.11.10 08:18
Оценка:
Здравствуйте, AlexKvs, Вы писали:

AK>Ну и в любом случае проверка "(baudRate > this.commProp.dwMaxBaud)" в таком случае выглядит немного странной, т.к. BAUD_128K будет считается меньшим чем BAUD_115200, или я чего-то не понял?


А что тут странного — обыкновенный баг
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.