Я пытаюсь открыть и прочитать из последовательного порта с помощью класса System.IO.Ports.SerialPort. Я перетащил последовательный порт из панели инструментов (Visual Studio 2008) в свое приложение Windows Forms.

У меня настроена сетка свойств, поэтому я могу легко изменять свойства последовательного порта во время выполнения. Когда я пытаюсь открыть порт, я получаю сообщение об ошибке, показанное ниже. Я не понимаю почему, потому что я могу открывать и читать из порта с помощью Hyperterminal.

Любые идеи?

System.IO.IOException Error connection: A device attached to the system is not functioning
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.InternalResources.WinIOError()
   at System.IO.Ports.SerialStream.set_DtrEnable(Boolean value)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at Test.CardReader.frmMain.Connect() in D:\Develop\2.0\Projects\Kiosk\EmbeddedBrowser\Windows Forms\Test.CardReader\Form1.cs:line 166

Обратите внимание, что это USB-соединение, поэтому на самом деле это виртуальный последовательный порт.

Мои настройки следующие:

BaudRate = 9600
DataBits = 8
DiscardNull = ложь
DtrEnable = false
Рукопожатие = Нет
Четность = Нет
ParityReplace = 63
PortName = COM3
ReadBufferSize = 4096
ReadTimeout = -1
ReceivedBytes = 1
TrsEnable = False
StopBits = один
WriteBufferSize = 2048
WriteTimeout = -1

Я загрузил PortMon из Sysinternals. Я сделал два журнала. Первый - это журнал того, что происходит, когда HyperTerminal открывает порт, а второй - что происходит когда класс .NET SerialPort пытается открыть порт:

Гипертерминал:

IRP_MJ_CREATE                  USBSER000  SUCCESS       Options: Open
IOCTL_SERIAL_SET_QUEUE_SIZE    USBSER000  SUCCESS       InSize: 8192 OutSize: 8192
IOCTL_SERIAL_CONFIG_SIZE       USBSER000  SUCCESS       Size: 0
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_SET_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_SET_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:f6 XOFF:6
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:80000001 Replace:80000040 XonLimit:80 XoffLimit:200
IOCTL_SERIAL_SET_TIMEOUTS      USBSER000  SUCCESS       RI:10 RM:0 RC:0 WM:0 WC:5000
IOCTL_SERIAL_SET_WAIT_MASK     USBSER000  SUCCESS       Mask: RLSD ERR
IOCTL_SERIAL_GET_MODEMSTATUS   USBSER000  SUCCESS
IOCTL_SERIAL_WAIT_ON_MASK      USBSER000
IRP_MJ_READ    USBSER000                                Length 80

.NET SerialPort:

IRP_MJ_CREATE                  USBSER000  SUCCESS       Options: Open
IOCTL_SERIAL_GET_PROPERTIES    USBSER000  SUCCESS
IOCTL_SERIAL_GET_MODEMSTATUS   USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_CLR_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_CLR_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IRP_MJ_CLEANUP                 USBSER000  SUCCESS
IRP_MJ_CLOSE                   USBSER000  SUCCESS
3
Jeremy 30 Янв 2009 в 20:29
Есть ли у InnerException IOException дополнительные сведения? Кроме того, можете ли вы открыть это в HyperTerminal (или другом терминале)?
 – 
Jon B
30 Янв 2009 в 21:07
B. В этой ошибке нет внутреннего исключения, и она работает в гипертерминале.
 – 
Jeremy
30 Янв 2009 в 21:58
В Win32 API DTR управляется одним из флагов в структуре DCB: msdn.microsoft.com/en-us/library/aa363436 (VS.85) .aspx
 – 
ChrisW
31 Янв 2009 в 01:51
Вы когда-нибудь решали эту проблему? Я знаю, что это было недавно, но я столкнулся с той же проблемой с небольшими отличиями.
 – 
tmwoods
12 Мар 2013 в 23:41
Я использовал сторонний компонент под названием OpenNETCF.IO.Serial.dll. Работает очень хорошо.
 – 
Jeremy
13 Мар 2013 в 02:35

4 ответа

Лучший ответ

Что касается различий между HyperTerminal и объектом последовательного порта .NET, HyperTerminal является коммерческим стабильным приложением. Если базовый объект последовательного порта умер или вызвал исключение, HyperTerminal скрыл его от вас. Объект последовательного порта .NET генерирует больше исключений, чем любой другой объект .NET, который я использовал.

Что нужно сделать:

  • Всякий раз, когда вы меняете настройку, сначала закройте ее, измените, а затем снова откройте. Некоторые порты действительно ненавидят, когда вы меняете его в открытом состоянии.
  • Ожидайте, что вы будете делать много попыток в отношении вашего объекта последовательного порта, во всем, что вы делаете.
  • Убедитесь, что у вас есть по одному для каждого из перечисленных возможных исключений, и убедитесь, что каждое из них проверяет сообщение (оно может отличаться в зависимости от обстоятельств). Многие можно восстановить, просто закрыв и снова открыв.
  • Попробуйте точно следить за тем, где возникают исключения. Посмотрите, исправляет ли это изменение порядка, который вы устанавливаете ... объект действительно привередлив.

Если вы пытались явно установить для DTR значение false перед открытием, вам, возможно, придется просто усмехнуться и терпеть это с этим устройством. Объект SerialPort - не один из ярких примеров хорошо реализованной библиотеки в .NET. Если вы заметили, HyperTerminal выдает ту же ошибку, но просто игнорирует ее.

По возможности попробуйте использовать обычный последовательный порт или USB-устройство другой марки. Если вы по-прежнему получаете ту же ошибку, это может быть что-то на стороне вашего приложения.

4
Peter Mortensen 19 Дек 2019 в 01:28
Я вызываю метод Open. исключение выбрасывается где-то там. Я использовал PortMonitor из sysinternals и обнаружил, что под капотом выдается IOCTL_SERIAL_CLR_DTR, который возвращает ошибку 0xC0000001 и приводит к тому, что класс SerialPort закрывает порт и генерирует исключение.
 – 
Jeremy
31 Янв 2009 в 02:25
Hyperterminal не вызывает выдачу IOCTL_SERIAL_CLR_DTR. Не уверен, как подавить это в рамках .net.
 – 
Jeremy
31 Янв 2009 в 02:25
К сожалению, вы можете не ничего с этим поделать. : /
 – 
Robert P
2 Фев 2009 в 19:50

В реальном UART DTREnable будет утверждать DTR вашего UART, чтобы указать, что вы готовы к приему данных.

В зависимости от реализации вашего драйвера вам может потребоваться установить для DTREnable значение true, чтобы открыть порт.

1
Peter Mortensen 19 Дек 2019 в 01:30
Да, я забыл упомянуть, это USB-соединение, так что это виртуальный последовательный порт. Если проблема в том, что вы предлагаете, как я могу ее обойти? Последовательный порт настроен на DtrEnable = false
 – 
Jeremy
30 Янв 2009 в 20:45
Это устранило мою проблему с использованием порта, просто _Port.DtrEnable = true;
 – 
Aaron
12 Авг 2010 в 06:39

См. Это сообщение на форуме. Я подозреваю, что это связано с неисправностью оборудования или драйвера. Однако это не объясняет, почему он работает с HyperTerminal. Следуйте совету Джозефа М. Новичка, чтобы увидеть, что HyperTerminal делает по-другому.

0
Peter Mortensen 19 Дек 2019 в 01:31
Hyperterminal не обязательно использует класс .NET: он использует Win32 API ... и он может использовать меньше Win32 API и / или иметь другую обработку ошибок, чем класс .Net. В частности, с помощью Win32 API вы можете открыть порт и впоследствии не установить некоторые его параметры.
 – 
ChrisW
31 Янв 2009 в 00:35
Я запустил программное обеспечение PortMon от sysinternals и добавил журналы к моему вопросу, я просто не знаю, какая команда win32 сейчас вызывает ошибку, как ее обойти. Доступен ли лучший класс последовательного порта?
 – 
Jeremy
31 Янв 2009 в 01:07
Я думаю, что развернутое резюме из этого сообщения на форуме было бы целесообразным (так что этот ответ является самодостаточным, а не только для ссылки).
 – 
Peter Mortensen
19 Дек 2019 в 01:32

Похоже, разница в рукопожатии.

У меня не было проблем с классом последовательного порта, и я написал приложения, которые работали со скоростью 800 000 бит / с.

0
Peter Mortensen 19 Дек 2019 в 01:33