ОКОНЧАТЕЛЬНОЕ ОБНОВЛЕНИЕ
Все время это была наша прошивка. До некоторой степени смущает, но я рад, что мы можем двигаться вперед, и я могу отложить изучение Java на другой день. Мой ответ ниже.
ОБНОВЛЕНИЕ
Так что я более или менее отказался от этого. Я думаю, что это ошибка API, но у меня нет ни времени, ни ресурсов, ни навыков, чтобы разобраться в ней. Я думаю, что существует какое-то оборудование, которому Windows просто показывает средний палец. Я загрузил Eclipse, переключился на Java и попробую проверить, работает ли это. Если нет, ты снова увидишь меня здесь. Тем не менее, я бы очень хотел решить эту проблему, и поэтому, если у кого-то есть время или желание углубиться в это, я хотел бы увидеть, что вы придумали. Очевидно, я буду возвращаться сюда время от времени. Пожалуйста, убедитесь, что вы отметили меня @ в своих комментариях, чтобы я был предупрежден.
ОРИГИНАЛЬНАЯ ЗАПИСЬ
Я знаю, что этой проблемой занимаются еще несколько человек, но я надеялся, что кто-нибудь сможет мне помочь. Я пытаюсь подключиться к COM-порту, но получаю сообщение / O исключение, когда я пытаюсь использовать команду 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, она даже не подключается, и я получаю эту ошибку. Сейчас я даже толком не знаю, что означает эта ошибка, и, несмотря на попытки прочитать где-нибудь еще, я все еще чувствую себя потерянным.
Может ли кто-нибудь объяснить мне, что здесь происходит, и, может быть, я смогу попытаться понять это? Я могу включить больше кода, но, честно говоря, там немного; все свойства устройства последовательного порта в норме, и это происходит только с этим устройством (я могу использовать 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 с помощью Termite, поэтому знаю, что соединение хорошее). И нет, я не пытаюсь открывать их одновременно. Если вам нужна дополнительная информация, дайте мне знать, и я могу опубликовать больше.
РЕДАКТИРОВАТЬ: Я нахожусь на третьем дне, пытаясь понять это, и все еще не повезло. Я действительно не понимаю, почему я могу получить доступ к этому COM-порту через терминальную программу, а не через свою собственную, когда, насколько я могу судить, нет абсолютно никакой разницы. Есть ли программа, которая может «исследовать» COM-порт, чтобы увидеть его свойства (кроме менеджера Windows, я имею в виду)? Я очень расстраиваюсь и как бы замираю в своем проекте, пока не разберусь в этом ...
РЕДАКТИРОВАТЬ2: Я нашел очевидное обходное решение, но мне еще предстоит заставить его работать здесь. Теперь я получаю несколько разных ошибок ввода-вывода, но, по крайней мере, это движение (не уверен, что это прогресс). Я также узнал, что это ошибка .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");
}
}
}
}
РЕДАКТИРОВАТЬ 3: День 6: Я все еще занимаюсь этим. У меня мало воды, но я все еще борюсь. Я чувствую, что помощь обязательно должна быть на горизонте. Кто бы ни нашел этот журнал, верните мои останки в Канаду и найдите Николь. Скажи ей, что я люблю ее.
А если серьезно, я понятия не имею, что вызывает эту проблему. Мне интересно, чисто ли это на встроенной стороне; возможно, потому что это USB On-The-Go (OTG), или потому что устройство также может быть хостом. Кто-нибудь сталкивался с этой проблемой? Это не объясняет, почему я могу использовать Termite (программу-терминал для тех, кто просто присоединяется к нам). Я пытался найти программу терминала с открытым исходным кодом, которая а) работает и б) см. А). Как обычно, я сообщу, если обнаружу здесь проблему, поскольку теперь я нашел бесчисленное количество форумов, где, похоже, у людей была эта проблема, относящаяся к 2006 году.
EDIT4: согласно данному совету я загрузил программное обеспечение для мониторинга портов (у меня есть Eltima Serial Port Monitor), и это действительно похоже на проблему с бодами:
Но, как ни странно, какую бы скорость я ни установил, он все равно не работает. А также может кто-нибудь объяснить, что означает «вверх / вниз»? Я пробовал погуглить, но ключевые слова слишком общие. Как обычно, я буду сообщать обо всех изменениях.
Кроме того, для записи, я могу подключиться с помощью Eltima на скорости 115200 бод (такой же, как Termite). К сожалению, в Visual Studio это не работает.
EDIT5: наш сюжет неожиданно изменился. Я отслеживал, что происходит, когда Termite подключается к рассматриваемому COM-порту и BLAM! Termite выдает ту же ошибку, что и моя программа, но игнорирует ее. Гений, правда? Коряво, но работает. Теперь мне нужно научиться игнорировать исключения IOExceptions. Я сообщу, когда выясню.
EDIT6: Как оказалось, это проблема скорости передачи данных, но она идет глубже. Я использовал программное обеспечение Eltima Serial Port Monitoring, оно очень интуитивно понятное и простое в использовании. Я бы рекомендовал это. После некоторых исследований я узнал, что нельзя игнорировать это исключение и по-прежнему подключается к последовательному порту с помощью библиотеки .NET.
Поэтому мне нужно глубже изучить Win32 API и написать свой собственный. Я нашел несколько страниц, которые касаются этого, но, честно говоря, я никогда раньше не делал ничего подобного, так что может пройти некоторое время, прежде чем я отчитаюсь, но я обязательно разберусь с этим и свяжусь со всеми. Слишком много людей страдают от этой проблемы.
Я нашел довольно много форумов и веб-сайтов, на которых я вижу те же самые симптомы, но на самом деле никто ничего не сделал, кроме как сказать: «Да, .NET - отстой». Я планирую написать полный класс статической библиотеки, а затем опубликовать его на своем веб-сайте, здесь и везде, где я могу. Надеюсь, .NET заметит (эта ошибка существует с 2.0).
GC.Collect()
до получения информации с порта? - person jmvtrinidad   schedule 08.03.2017