最終更新
それはずっと私たちのファームウェアでした。ある程度恥ずかしいことですが、前進できることをうれしく思います。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
COM ポートをエミュレートするために Stellaris LM4F232 を使用しています。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 を開くことができます。これは、すべての意図と目的において同一のデバイスです。COM5 は Termite で開くことができるので、接続が良好であることはわかっています)。いいえ、同時に開こうとしているわけではありません。さらに情報が必要な場合はお知らせください。さらに投稿できます。
編集:私はこれを理解しようとして3日目ですが、まだ運がありません。私が見る限り、まったく違いがないのに、なぜ自分のCOMポートではなくターミナルプログラムを介してこのCOMポートにアクセスできるのか、私にはよくわかりません。COMポートを「調べて」そのプロパティを確認できるプログラムはありますか(Windowsマネージャー以外に)?私はかなりイライラしており、これを理解するまでプロジェクトで立ち止まっているようなものです...
EDIT2: 明らかな回避策を見つけましたが、まだここで機能させるには至っていません。現在、いくつかの異なる I/O エラーが発生していますが、少なくともモーションです (進行中かどうかはわかりません)。また、これは .NET のバグであり、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");
}
}
}
}
EDIT3: 6 日目: 私はまだこれに取り組んでいます。水の配給は少ないですが、それでも頑張っています。助けは確実に間近に迫っているに違いないと感じています。この日誌を見つけた人は誰でも私の遺体をカナダに持ち帰り、ニコールを見つけてください。私が彼女を愛していると彼女に伝えてください。
しかし、真剣に、何がこの問題を引き起こしているのかわかりません。純粋に組み込み側にあるのだろうかと思います。おそらく、USB On-The-Go (OTG) であるか、デバイスがホストにもなることができるためです。誰かがその問題に遭遇しましたか? ただし、Termite (参加したばかりの視聴者向けの端末プログラム) を使用できる理由については説明していません。私は、a) 動作し、b) a) を参照できるオープン ソース ターミナル プログラムを見つけようとしています。いつものように、2006 年にさかのぼってこの問題が発生したと思われるフォーラムを無数に見つけたので、ここで問題を発見したら報告します。
EDIT4:与えられたアドバイスに従って、ポート監視ソフトウェアアプリケーションをダウンロードしました(Eltima Serial Port Monitorを入手しました)、ボーの問題のように見えます:
しかし、奇妙なことに、どのボーを設定しても失敗します。また、誰かがアップ/ダウンの意味を説明できますか? ググってみましたが、キーワードが一般的すぎます。いつものように、私は変更を報告し続けます。
また、記録のために、115200 ボー (Termite と同じ) で Eltima を使用して接続できます。残念ながら、これは Visual Studio では機能しません。
EDIT5: 私たちの筋書きは意外なひねりを加えています。シロアリが問題の COM ポートに接続したときに何が起こるかを監視していて、BLAM! シロアリは私のプログラムとまったく同じエラーをスローしますが、無視します。天才ですね。ずさんですが、うまくいきます。ここで、IOExceptions を無視する方法を学ぶ必要があります。判明したらまた報告します。
EDIT6:ボーレートの問題であることが判明しましたが、さらに深くなります。Eltima Serial Port Monitoring ソフトウェアを使用していますが、非常に直感的で使いやすいです。私はそれをお勧めします。調査の結果、この例外を無視することはできず、.NET のライブラリを使用してシリアル ポートに接続できないことがわかりました。
そのため、Win32 API をさらに深く掘り下げ、独自の API を作成する必要があります。これに触れているページをいくつか見つけましたが、正直なところ、このようなことはこれまでに行ったことがありません。この問題に苦しんでいる人が多すぎます。
まったく同じ症状が見られるフォーラムや Web サイトをかなり見つけましたが、「ああ、.NET は最悪だ」と言う以外に実際に多くのことを行った人は誰もいません。私は完全な静的ライブラリ クラスを作成し、自分の Web サイト、ここ、およびその他の場所で公開する予定です。うまくいけば、.NET が気付くでしょう (このバグは 2.0 から存在しています)。