Ошибка исключения ввода-вывода при использовании serialport.открыть()
ОКОНЧАТЕЛЬНОЕ ОБНОВЛЕНИЕ Это была наша прошивка все время. До некоторой степени неловко, но я рад, что мы можем двигаться вперед, и я могу отложить изучение Java на другой день. Мой ответ ниже.
обновление Так что я более или менее отказался от этого. Я думаю, что это ошибка, которая спускается к API, но у меня нет ни времени, ни ресурсов, ни навыков, чтобы добраться до сути. Я думаю, что существует некоторое оборудование, которому Windows просто дает средний палец. Я загрузили Eclipse, переключились на Java и попытаются посмотреть, работает ли это. Если нет,увидимся здесь. Тем не менее, я бы очень хотел решить эту проблему, и если у кого-то есть время или желание углубиться в это, я хотел бы посмотреть, что вы придумаете. Очевидно, я буду время от времени заглядывать сюда. Пожалуйста, убедитесь, что вы " @ " меня в ваших комментариях, так что я предупрежден.
ОРИГИНАЛЬНЫЙ ПОСТ
Я знаю, что есть несколько других людей занимаюсь этим вопросом, но я надеялся, что кто-то может мне помочь. Я пытаюсь подключиться к COM-порту, но при попытке использовать :
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");
}
и другие настройки выполняются с помощью диспетчера свойств (разница только в том, что БОД установлен в 230400, все остальные по умолчанию). Я могу открыть COM4 с этим (MSP430), который для всех целей и задач является идентичным устройством. Я могу открыть COM5 с термитом, поэтому я знаю, что соединение хорошее). И нет, я не пытаюсь открыть их одновременно. Если вам нужна дополнительная информация, дайте мне знать, и я могу больше.
спасибо!
EDIT: я на третий день пытаюсь понять это и до сих пор не повезло. Я действительно не понимаю, почему я могу получить доступ к этому COM через терминальную программу, а не свою собственную, когда, насколько я вижу, нет абсолютно никакой разницы. Кто-нибудь знает о программе, которая может "изучить" COM-порт, чтобы увидеть его свойства (кроме диспетчера windows, я имею в виду)? Я становлюсь довольно расстроенным и вроде как стою на месте в своем проекте, пока не пойму это...
EDIT2: я нашел очевидный обходной путь, но мне еще предстоит заставить его работать здесь. Теперь я получаю несколько разных ошибок ввода-вывода, но, по крайней мере, это движение (не уверен, что это прогресс). Я также узнал, что это ошибка .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 (терминальную программу, для тех зрителей, которые только что присоединились к нам). Я пытался найти программу с открытым исходным кодом, которая a) работает и b) см. a). Как обычно, я сообщу, если я обнаружу проблему здесь, как я нашел бесчисленные форумы, где звучит, что у людей была эта проблема, начиная с 2006 года.
EDIT4: Итак, согласно данному совету, я загрузил программное обеспечение для мониторинга портов (я получил монитор последовательного порта Eltima), и это похоже на проблему с БОДом:
но странно, независимо от того, какой БОД я установить его не удается. А также может кто-нибудь объяснить, что означает вверх/вниз? Я попробовал погуглить его, но ключевые слова слишком общие. Как обычно, я буду сообщать о любых изменениях.
кроме того, для записи я могу подключиться с помощью Eltima в Боде 115200 (так же, как термит). К сожалению, это не работает в Visual Studio.
EDIT5: наш сюжет принимает неожиданный поворот. Я отслеживал, что происходит, когда Термит подключается к рассматриваемому COM-порту и BLAM! Термит выдает ту же ошибку, что и моя программа, но это игнорировать его. Гениально, правда? Коряво, но работает. Теперь мне нужно научиться игнорировать IOExceptions. Я доложу, когда разберусь.
EDIT6: так как оказывается, это проблема скорости передачи, но она идет глубже. Я использую Мониторинг Последовательного Порта Eltima программное обеспечение, и это очень интуитивно понятный и простой в использовании. Я бы порекомендовал. После исследования я узнал, что вы нельзя игнорировать это исключение и по-прежнему подключаться к последовательному порту с помощью .Библиотека NETs. Поэтому я должен углубиться в Win32 API и написать свой собственный. Я нашел несколько страниц, которые касаются этого, но, честно говоря, я никогда не делал ничего подобного раньше, поэтому может пройти некоторое время, прежде чем я отчитаюсь, но я обязательно выясню это и вернусь ко всем. Слишком многие страдают от этой проблемы. Я нашел довольно много форумов и веб-сайтов, где я могу видеть точно такие же симптомы но никто не сделал ничего, кроме как сказать: "Да, .NET отстой". Я планирую написать полный статический класс библиотеки, а затем опубликовать его на своем веб-сайте, здесь и везде, где смогу. Надеюсь, .NET заметит (эта ошибка существует с 2.0). Я доложу, когда все будет сделано!
EDIT7: это намного сложнее, чем я думал.
EDIT8: я не знаю, следит ли кто-нибудь за этим или нет, но я хотел сказать, что я все еще на нем, но меня нет в городе на неделю командировка. Я все еще рад услышать предложения и альтернативные идеи, хотя!
5 ответов
Это происходит от драйвера последовательного порта, он недоволен одной из настроек. С baudrate быть хорошим кандидатом, водители, как правило, позволяют только до 115200. Хотя это не должно быть ограничением, когда это выделенный продукт шины CAN.
лучший способ решить эту проблему-использовать утилиту PortMon SysInternals, вы можете увидеть, что отправляется водителю. Соблюдайте его для завершения первого, это ваша известная для работы базовая линия. Затем поработайте с SerialPort свойства до тех пор, пока команды инициализации, как вы видите их в PortMon, отправленные вашей программой, не совпадут с термитами. Только ценности, не порядок. Если это не сработает, то возьмите его на стоянку и обратно с вашим автомобилем несколько раз и купите другую марку.
обновление: это, конечно, похоже на проблему скорости. Это проблема в .NET, она не будет игнорировать код возврата ошибки драйвера, как это делают ваши программы эмулятора терминала. Фактическое значение не должно иметь значения, так как вы говорите с эмулируется последовательный порт. Однако существует возможная проблема со скоростью CAN-bus, ставки являются переменными, и мне не ясно, как они обсуждаются. Это, как правило, делается с помощью DIP-переключателей в старые времена, вполне может быть, что водитель хочет, чтобы вы указали скорость через настройку baudrate. Там должно быть что-то об этом на коробке или в инструкции. Типичные скорости 40, 250 или 500 Kbps. Производитель конечно, узнаю, позвоню им.
я сталкиваюсь с аналогичной проблемой, как сообщается в этом потоке, но мне удалось решить проблему!
Я использую STM32F2xx для VCP!
и действительно, это моя проблема прошивки, я забыл включить настройки последовательного порта в мой обратный вызов USB!
процесс подключения последовательного порта от ПК и прошивки:
- когда ПК раскроет сообщение серийного порта, ПК пошлет некоторую команду в " конфигурацию конечная точка"
- в прошивке он будет иметь обратный вызов, и прошивка предоставит всю информацию USB (они называют это дескриптором USB)
- данные по УСБ конфигурация каждой конечной точки, (например: латентность, передача размера данных, тип УСБ - быстрый ход или низкоскоростной)
- как только прошивка завершит отправку всей информации, ПК подтвердит и USB-связь будет успешно открыта
- затем ПК отправит команду, чтобы получить настройки последовательного порта из прошивки
- настройки последовательного порта - baudrate, четность данных, длина бита
- в прошивке он должен ответить на настройки последовательного порта обратно на ПК (моя ошибка происходит здесь, я не отвечаю на настройки последовательного порта обратно на ПК)
- если успешно, ПК начнет сообщение серийного порта!
- если не удалось, ПК даст ошибку открытого последовательного порта (но, обратите внимание, что эта ошибка иногда обошел)
в коде прошивки 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;
}:
....
и так наша захватывающая история подходит к концу. Это была прошивка все время (т. е. код на встроенном устройстве). Мы изменили несколько функций и, по сути, ковырялись, рубили, добавляли и вообще очищали код и вуаля, код работает. фото подводит итог довольно хорошо. Проклинаю тебя прошивка!!
однако ошибка, описанная в моем (длинном) вопросе, все еще сохраняется для многих людей, и я знаю, что есть много людей, у которых все еще есть он. Все, что я могу сказать, это удача и четверная проверка прошивки (по-видимому, тройная проверка в эти дни недостаточно).
я столкнулся с такой же ситуацией. Я пытаюсь подключить последовательную связь к моему 3G USB-ключу (Huawei E303F) at /dev/ttyUSB0. Я использую mono в Raspbian (raspberry-pi2). В моем компьютере разработки и macOS моя программа работает нормально. Но когда я развертываю его в Raspbian, я получил ошибку сломанной трубы IOException на последовательном.Открытый.)(
Я взял три дня отладки и попробовал все возможные решения. Наконец-то я понял, что должен сесть...
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
перед вызовом .Открытый.)( Я надеюсь, что это может помочь другим людям, которые сталкиваются с той же проблемой, как моя.