2013-02-14 2 views
18

ОКОНЧАТЕЛЬНОЕ ОБНОВЛЕНИЕ Это была наша прошивка на все время. Смущаю до некоторой степени, но я счастлив, что мы можем двигаться вперед, и я могу учить изучение Java еще на один день. Мой ответ ниже.Ошибка исключения IO при использовании serialport.open()

ОБНОВЛЕНИЕ Так что я более или менее отказался от этого. Я думаю, что это ошибка, которая сводится к API, но у меня нет ни времени, ни ресурсов, ни навыков, чтобы добраться до сути. Я думаю, что существует некоторое аппаратное обеспечение, которому Windows просто дает средний палец. Я загрузил Eclipse, переключился на Java и попытаюсь посмотреть, работает ли это. Если нет, ты увидишь меня здесь. Тем не менее, я был бы очень рад решить эту проблему, и если у кого есть время или желание углубиться в это, я бы с удовольствием посмотрел, что вы придумали. Очевидно, я буду периодически проверять это время. Пожалуйста, убедитесь, что вы «@» меня в своих комментариях, поэтому меня предупреждают.


ОРИГИНАЛЬНЫЙ ПОСТ

Я знаю, что есть несколько других людей, занимающихся этим вопросом, но я надеялся, что кто-то может мне помочь. Я пытаюсь подключиться к COM-порту, но я получаю исключение ввода-вывода при попытке использовать serialport.Open() команду:

System.IO.IOException: The parameter is incorrect. 

    at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str) 
    at System.IO.Ports.InternalResources.WinIOError() 
    at System.IO.Ports.SerialStream.InitializeDCB(Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Boolean discardNull) 
    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 *programtitlehere.cs*:line 90 

Я использую Stellaris LM4F232 для эмуляции COM-порта. Я могу открыть, получить доступ и получить хорошие результаты с помощью Termite (терминальной программы), но всякий раз, когда я пытаюсь работать с Visual Studio, он даже не подключается, и я получаю эту ошибку. Теперь я даже не знаю, что означает эта ошибка, и я, несмотря на попытки читать в другом месте, все еще чувствую себя потерянным.

Может ли кто-нибудь объяснить мне, что здесь происходит, и, может быть, я начну пытаться понять это? Я могу добавить больше кода, но, честно говоря, там не так много; все свойства устройства serialport являются нормальными, и это происходит только с этим устройством (я могу использовать MSP430 без проблем с теми же деталями).

Мой код показан ниже для людей, которые хотели бы видеть, что это (обратите внимание, что это просто «песочница», а не фактическая программа, но симптомы идентичны):

try 
     { 
      serialPort1.PortName = "COM5"; 
      serialPort1.Open(); 
      if (serialPort1.IsOpen == true) 
      { 
       textBox1.Text = "CONNECTED"; 
      } 
      else 
      { 
       textBox1.Text = "NOT CONNECTED"; 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Error: " + ex.ToString(), "ERROR"); 
     } 

и другие параметры сделанный с менеджером свойств (разница только в baud установлена ​​на 230400, все остальные по умолчанию). Я могу открыть COM4 с этим (MSP430), который для всех целей и задач является идентичным устройством. Я могу открыть COM5 с Termite, поэтому я знаю, что соединение хорошее). И нет, я не пытаюсь открыть их одновременно. Если вам нужна дополнительная информация, дайте мне знать, и я могу разместить больше.

Спасибо!

EDIT: Я нахожусь на третий день, пытаясь понять это и до сих пор не повезло. Я не понимаю, почему я могу получить доступ к этому COM через терминальную программу, а не по своему усмотрению, когда, насколько я вижу, нет никакой разницы. Кто-нибудь знает о программе, которая может «исследовать» COM-порт, чтобы увидеть его свойства (помимо диспетчера Windows, я имею в виду)? Я становлюсь довольно расстроенным и вроде как стоять в своем проекте до тех пор, пока не узнаю об этом ...

EDIT2: Я нашел очевидное обходное решение, но мне еще нужно его заставить here , Теперь я получаю несколько разных ошибок ввода-вывода, но по крайней мере это движение (не уверен, что это прогресс). Я также узнал, что это ошибка .NET, которая существует с 2.0. Я все равно буду любить любую помощь, но если я это выясню, я отчитаю.Код Зака ​​(обходной путь связан выше) показано ниже:

using System; 
using System.IO; 
using System.IO.Ports; 
using System.Runtime.InteropServices; 
using System.Text; 
using Microsoft.Win32.SafeHandles; 

namespace SerialPortTester 
{ 
public class SerialPortFixer : IDisposable 
{ 
    public static void Execute(string portName) 
    { 
     using (new SerialPortFixer(portName)) 
     { 
     } 
    } 
    #region IDisposable Members 

    public void Dispose() 
    { 
     if (m_Handle != null) 
     { 
      m_Handle.Close(); 
      m_Handle = null; 
     } 
    } 

    #endregion 

    #region Implementation 

    private const int DcbFlagAbortOnError = 14; 
    private const int CommStateRetries = 10; 
    private SafeFileHandle m_Handle; 

    private SerialPortFixer(string portName) 
    { 
     const int dwFlagsAndAttributes = 0x40000000; 
     const int dwAccess = unchecked((int) 0xC0000000); 

     if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase)) 
     { 
      throw new ArgumentException("Invalid Serial Port", "portName"); 
     } 
     SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes, 
              IntPtr.Zero); 
     if (hFile.IsInvalid) 
     { 
      WinIoError(); 
     } 
     try 
     { 
      int fileType = GetFileType(hFile); 
      if ((fileType != 2) && (fileType != 0)) 
      { 
       throw new ArgumentException("Invalid Serial Port", "portName"); 
      } 
      m_Handle = hFile; 
      InitializeDcb(); 
     } 
     catch 
     { 
      hFile.Close(); 
      m_Handle = null; 
      throw; 
     } 
    } 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId, 
              StringBuilder lpBuffer, int nSize, IntPtr arguments); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, 
                IntPtr securityAttrs, int dwCreationDisposition, 
                int dwFlagsAndAttributes, IntPtr hTemplateFile); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern int GetFileType(SafeFileHandle hFile); 

    private void InitializeDcb() 
    { 
     Dcb dcb = new Dcb(); 
     GetCommStateNative(ref dcb); 
     dcb.Flags &= ~(1u << DcbFlagAbortOnError); 
     SetCommStateNative(ref dcb); 
    } 

    private static string GetMessage(int errorCode) 
    { 
     StringBuilder lpBuffer = new StringBuilder(0x200); 
     if (
      FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity, 
          IntPtr.Zero) != 0) 
     { 
      return lpBuffer.ToString(); 
     } 
     return "Unknown Error"; 
    } 

    private static int MakeHrFromErrorCode(int errorCode) 
    { 
     return (int) (0x80070000 | (uint) errorCode); 
    } 

    private static void WinIoError() 
    { 
     int errorCode = Marshal.GetLastWin32Error(); 
     throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode)); 
    } 

    private void GetCommStateNative(ref Dcb lpDcb) 
    { 
     int commErrors = 0; 
     Comstat comStat = new Comstat(); 

     for (int i = 0; i < CommStateRetries; i++) 
     { 
      if (!ClearCommError(m_Handle, ref commErrors, ref comStat)) 
      { 
       WinIoError(); 
      } 
      if (GetCommState(m_Handle, ref lpDcb)) 
      { 
       break; 
      } 
      if (i == CommStateRetries - 1) 
      { 
       WinIoError(); 
      } 
     } 
    } 

    private void SetCommStateNative(ref Dcb lpDcb) 
    { 
     int commErrors = 0; 
     Comstat comStat = new Comstat(); 

     for (int i = 0; i < CommStateRetries; i++) 
     { 
      if (!ClearCommError(m_Handle, ref commErrors, ref comStat)) 
      { 
       WinIoError(); 
      } 
      if (SetCommState(m_Handle, ref lpDcb)) 
      { 
       break; 
      } 
      if (i == CommStateRetries - 1) 
      { 
       WinIoError(); 
      } 
     } 
    } 

    #region Nested type: COMSTAT 

    [StructLayout(LayoutKind.Sequential)] 
    private struct Comstat 
    { 
     public readonly uint Flags; 
     public readonly uint cbInQue; 
     public readonly uint cbOutQue; 
    } 

    #endregion 

    #region Nested type: DCB 

    [StructLayout(LayoutKind.Sequential)] 
    private struct Dcb 
    { 
     public readonly uint DCBlength; 
     public readonly uint BaudRate; 
     public uint Flags; 
     public readonly ushort wReserved; 
     public readonly ushort XonLim; 
     public readonly ushort XoffLim; 
     public readonly byte ByteSize; 
     public readonly byte Parity; 
     public readonly byte StopBits; 
     public readonly byte XonChar; 
     public readonly byte XoffChar; 
     public readonly byte ErrorChar; 
     public readonly byte EofChar; 
     public readonly byte EvtChar; 
     public readonly ushort wReserved1; 
    } 

    #endregion 

    #endregion 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     SerialPortFixer.Execute("COM1"); 
     using (SerialPort port = new SerialPort("COM1")) 
     { 
      port.Write("test"); 
     } 
    } 
} 
} 

EDIT3: День 6: Я все еще корпеть в этом. Мой водный рацион низкий, но я все еще боюсь. Я чувствую, что помощь должна быть на горизонте. Тот, кто находит этот журнал, возвращает мои останки в Канаду и находит Николь. Скажи ей, что я люблю ее.

Но если серьезно, я понятия не имею, что вызывает эту проблему. Мне интересно, чисто ли это на встроенной стороне; возможно, потому что это USB-to-go, или потому, что устройство также может быть хостом. Кто-нибудь сталкивался с этой проблемой? Это не объясняет, почему я могу использовать Termite (терминальная программа, для тех, кто просто присоединяется к нам). Я пытался найти терминальную программу с открытым исходным кодом, которая: а) работает и б) видит а). Как обычно, я отчитаю, если я открою для себя эту проблему, так как теперь я нашел бесчисленные форумы, на которых, похоже, у людей появилась эта проблема, относящаяся к 2006 году.

EDIT4: Так, в соответствии с приведенным советом, я загрузил порт приложение мониторинга программного обеспечения (я получил Eltima Serial Port Monitor) и это выглядит как вопрос бода:

Screen capture from Eltima

, но странно, независимо от того, что бода я установил, что до сих пор не удается. А также может кто-нибудь объяснить, что означает «вверх-вниз»? Я пробовал искать его, но ключевые слова слишком общие. Как обычно, я буду сообщать о любых изменениях.

Кроме того, для записи я могу подключиться с помощью Eltima на боде 115200 (то же, что и Termite). К сожалению, это не работает в Visual Studio.

EDIT5: Наш сюжет захватывает сюрприз. Я отслеживал, что происходит, когда Termite подключается к рассматриваемому COM-порту и BLAM! Термиты бросают ту же самую ошибку, что и моя программа, но она игнорирует. Гений, да? Sloppy, но он работает. Теперь мне нужно научиться игнорировать IOExceptions. Я отчитаю, когда узнаю.

EDIT6: Как оказалось, это проблема с бодью, но она идет глубже. Я использую программное обеспечение Eltima Serial Port Monitoring, и он очень интуитивно понятен и прост в использовании. Я бы рекомендовал его. После some research Я узнал, что вы не можете игнорировать это исключение и по-прежнему подключаться к последовательному порту с использованием библиотеки .NET. Поэтому я должен углубиться в API Win32 и написать свой собственный. Я нашел несколько страниц, которые касаются этого, но, честно говоря, я никогда не делал ничего подобного раньше, так что может быть какое-то время, пока я не отчитаюсь, но я обязательно это рассмотрю и вернусь к каждому. Есть слишком много людей, которые страдают от этой проблемы. Я нашел довольно много форумов и веб-сайтов, где я могу видеть те же самые симптомы, но никто на самом деле ничего не сделал, кроме того, сказал: «Да, .NET сосет». Я планирую писать полный статический класс библиотеки, а затем публиковать либо на своем веб-сайте, и здесь, и где бы я мог. Надеемся, что .NET заметит (эта ошибка существует с версии 2.0). Я отчитаю, когда это будет сделано!

EDIT7: Это намного сложнее, чем я думал.

EDIT8: Я не знаю, если кто-то следит за этим или нет, но я хотел сказать, что я все еще нахожусь на нем, но выезжаю из города на неделю в командировке. Я все еще счастлив услышать предложения и альтернативные идеи, хотя!

+0

Какие настройки вы используете для подключения? Можем ли мы увидеть код? –

+0

Я только что добавил свой код к исходному сообщению. Я не знаю, как добавить код в комментарии ... – tmwoods

+1

Мое единственное догадаться, что ваши свойства как-то не так. Возможно, попробуйте снизить скорость передачи до 9600. –

ответ

1

Итак, наша захватывающая история подходит к концу. Это была прошивка все время (т. Е. Код на встроенном устройстве). Мы изменили несколько функций и, по существу, ткнулись, нарезали, добавили и полностью очистили код и вуаля, код работает. This pic подводит итог довольно хорошо. Проклятие прошивки!

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

6

Это происходит от драйвера последовательного порта, он недоволен одним из параметров. Поскольку скорость передачи данных является хорошим кандидатом, драйверы имеют тенденцию допускать только до 115200. Хотя это не должно быть ограничением, когда это выделенный продукт шины CAN.

Лучший способ справиться с этим - с помощью утилиты SysInternals PortMon, вы можете видеть, что отправляется драйверу. Соблюдайте его сначала для завершения, это ваш базовый уровень, основанный на работе. Затем перебирайте свойства SerialPort до тех пор, пока команды инициализации, как вы видите их в PortMon, не отправили вашей программой, не соответствуют термитам. Просто значения, а не порядок. Если это не закончится, то перейдите на автостоянку и вернитесь на нее с автомобилем несколько раз и купите другой бренд.


Обновление: это, безусловно, выглядит как проблема с бодрой. Это проблема в .NET, она не будет игнорировать код возврата ошибки драйвера, как это делают программы эмулятора терминала. Фактическое значение не должно иметь значения, так как вы разговариваете с серийным портом , эмулированным последовательным портом. Тем не менее, существует проблема с частотой шины CAN, ставки меняются, и мне не ясно, как они обсуждаются. Это, как правило, с DIP-переключателями в прежние дни, вполне возможно, что драйвер хочет, чтобы вы указали скорость через настройку скорости передачи. Там должно быть что-то об этом на коробке или в руководстве. Типичные скорости - 40, 250 или 500 Кбит/с. Производитель, конечно же, знал бы, позвоните им.

+0

Я нахожусь вне офиса на вечер, но когда я получу завтра, я отдам его :) – tmwoods

+0

Можете ли вы порекомендовать более современный пакет программного обеспечения для мониторинга портов? Единственная версия, которую я могу найти, несовместима с Windows 7 (она появлялась в последний раз, когда они обновляли это программное обеспечение для Win98). В нем говорится, что он защищен авторским правом на 2012 год, но я не могу его подключить, и все файлы справки либо отсутствуют, либо объясняются для среды Win98. – tmwoods

+0

Я пробовал монитор Elitima Serial Port Monitor, см. Основную часть вопроса выше. – tmwoods

3

Я столкнулся с аналогичной проблемой, о которой сообщалось в этой теме, но мне удалось решить проблему!

Я использую STM32F2xx для VCP!

И действительно, это моя проблема с прошивкой, я забыл включить настройки последовательного порта в свой обратный вызов USB!

Процесс подключения последовательного порта с ПК и прошивки:

  1. Когда ПК открывает последовательный порт связи, компьютер будет посылать какую-либо команду в «конфигурации конечной точки»
  2. В прошивке, это будет иметь обратный вызов, а прошивка предоставит всю информацию USB (они называют его дескриптором USB)
  3. Информация о USB - это конфигурация каждой конечной точки (например: латентность, передача данных по размеру, тип USB - высокая скорость или низкая скорость)
  4. После того, как фирма ware завершает отправку всей информации, ПК подтвердит и USB-связь успешно откроется
  5. Затем ПК отправит команду для получения настроек последовательного порта из прошивки
  6. Настройки последовательного порта - скорость передачи данных, четность данных, длина бита
  7. в прошивке, она должна отвечать настройки последовательного порта назад к ПК (Моя ошибка происходит здесь, я вмятина не отвечать любые настройки последовательного порта назад к ПК)
  8. в случае успеха, PC начнет серийный порт связи!
  9. Если не удалось, PC даст открытый серийный ошибку порта (но, не отметить, что эта ошибка иногда обходится)

В STM32 код прошивки:

static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length) 
{ 
    switch (cmd) { 
     case CDC_GET_LINE_CODING:  
     { 
      //I was missing this part 
      uint32_t baudrate = 9600; 
      pbuf[0] = (uint8_t)(baudrate); 
      pbuf[1] = (uint8_t)(baudrate >> 8); 
      pbuf[2] = (uint8_t)(baudrate >> 16); 
      pbuf[3] = (uint8_t)(baudrate >> 24); 
      pbuf[4] = 0; 
      pbuf[5] = 0; 
      pbuf[6] = 8; 
      break; 
     }: 
.... 
0

Я столкнулся с той же ситуации, , Я пытаюсь подключить последовательную связь к моему 3G USB Dongle (Huawei E303F) на/dev/ttyUSB0. Я использую моно в Raspbian (малина-pi2). В моей разработке ПК и macOS моя программа работает нормально. Но когда я развертываю его в Raspbian, я получил ошибку IOException Broken Pipe на Serial.Open().

Я потратил три дня на отладку и попробовал все возможные решения. Наконец, я обнаружил, что мне нужно установить ...

serialPort.DtrEnable = true; 
serialPort.RtsEnable = true; 

Перед вызовами .Открыть(). Надеюсь, это поможет другим людям, которые сталкиваются с такими же проблемами, как и мои.

Смежные вопросы