最终更新
问题出在我们的固件上。有点尴尬,但我很高兴我们能够继续前进,而且我可以把学习Java的事情再拖一天。我的答案在下面。
更新
所以我已经放弃了这个问题。我认为这是一个与API相关的错误,但我没有时间、资源和技能来解决它。我认为有些硬件会让Windows无法正常工作。我已经下载了Eclipse,切换到Java,看看是否有效。如果不行,我会回到这里。然而,我非常希望解决这个问题,如果有人有时间或意愿深入研究这个问题,我很想看看你们的成果。显然,我会时不时地回来查看。请确保在评论中使用 '@' 提醒我。
原始帖子
我知道还有其他人在处理这个问题,但我希望有人能帮助我。我正在尝试连接到COM端口,但当我尝试使用serialport.Open()
命令时,我遇到了一个I/O异常:
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;其他所有设置均为默认设置)。我可以用这个(MSP430)打开COM4,它在所有方面都与另一个设备相同。我可以用Termite打开COM5,所以我知道连接是好的)。不,我不想同时打开它们。如果您需要更多信息,请告诉我,我可以发布更多信息。
编辑:我已经尝试了三天,仍然没有成功。我真的不明白为什么我可以通过终端程序访问此COM端口,但不能通过自己的程序访问,因为我看不到任何区别。有没有可以“检查”COM端口以查看其属性的程序(除了Windows管理器)?我变得非常沮丧,并且在我的项目中陷入了停滞状态,直到我解决这个问题...
编辑2:我已经找到了一个明显的解决方法,但是我还没有让它在这里起作用。现在我得到了几个不同的I/O错误,但至少它是动态的(不确定是否有进展)。我还了解到这是一个.NET bug,自2.0以来就存在。我仍然希望得到任何帮助,但如果我弄清楚了,我会回报的。Zach的代码(上面链接的解决方法)如下:
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天:我还在努力解决这个问题。我的水供应很少,但是我仍在苦苦挣扎。我感到有人一定会来帮忙的。谁找到这个日志,请把我的遗骸带回加拿大并找到Nicole。告诉她我爱她。
但说真的,我不知道是什么原因导致了这个问题。我想知道是不是纯粹在嵌入式方面引起的;也许是由于它是USB On-The-Go(OTG),或者因为该设备也能够成为主机。有没有人遇到过这个问题?虽然我可以使用Termite(一个终端程序,对于那些刚加入我们的观众们来说),但这并不能解释为什么。我一直在尝试找到一个开源终端程序,a)可用并且b)看a)。像往常一样,如果我在这里发现了问题,我会报告的,因为我现在已经发现了无数论坛,听起来人们从2006年就有了这个问题。
编辑4:所以根据给出的建议,我下载了一个端口监视软件应用程序(我得到了Eltima Serial Port Monitor),看起来确实是波特率的问题:
但是奇怪的是,无论我设置什么波特率,它都失败了。还有,有人能解释一下上下的意思吗?我试着在谷歌上搜索,但关键词太普遍了。通常情况下,我会继续报告任何变化。此外,为了记录,我可以使用115200的波特率(与Termite相同)连接Eltima。不幸的是,在Visual Studio中这样做行不通。
编辑5:我们的情节出现了惊喜的转折。当Termite连接到相关的COM端口时,我正在监视发生了什么,突然间!Termite抛出了与我的程序完全相同的错误,但它却忽略了它。天才,对吧?粗心,但它起作用了。现在我需要学习如何忽略IOExceptions。我将在弄清楚后再报告。
编辑6:事实证明这是一个波特率问题,但它更深入。我一直在使用Eltima串行端口监控软件,它非常直观和易于使用。我会推荐它。经过一些研究,我了解到你不能忽略这个异常并仍然使用.NET库连接到串行端口。
所以我必须深入了解Win32 API并编写自己的代码。我找到了一些相关页面,但说实话我以前从未做过这样的事情,所以在报告之前可能需要一段时间,但我一定会弄清楚并回复大家。有太多人遭受这个问题的困扰。
我发现了很多论坛和网站,可以看到完全相同的症状,但除了说“是的,.NET很糟糕”之外,没有什么实质性的帮助。我计划编写一个完整的静态库类,然后发布到我的网站、这里和所有其他地方。希望.NET能够注意到这个问题(这个错误从2.0版本就存在)。