我想检测串口引脚上是否有触发信号,应该是这样的吧:4(DTR)配1(DCD)、6(DSR)、8(CTS)。
可是无论我怎么操作,GetCommModemStatus返回的状态都是0。困扰好多天了,请哪位大虾帮忙分析一下。多谢了!以下是代码://开始监控
private void button1_Click(object sender, EventArgs e)
{
    if (comboBox1.SelectedIndex < 0) return;    try
    {
        comPort = comboBox1.SelectedItem.ToString();        comm_handle = CreateFile(comPort, FileAccess.ReadWrite, FileShare.None, 0, FileMode.Open, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
        if (comm_handle.Equals(INVALID_HANDLE_VALUE)) return;        SpThread = new Thread(SPortThreadExecute);
        SpThread.Start();        AddNewLine("串口 " + comPort + " 打开成功!");        comboBox1.Enabled = false;
        button1.Enabled = false;
        button2.Enabled = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}//停止监控
private void button2_Click(object sender, EventArgs e)
{
    try
    {
        if (!comm_handle.Equals(INVALID_HANDLE_VALUE)) CloseHandle(comm_handle);        while ((SpThread != null) && SpThread.IsAlive)
        {
            SpThread.Abort();
            Thread.Sleep(100);
        }        AddNewLine("串口 " + comPort + " 关闭成功!");        comboBox1.Enabled = true;
        button1.Enabled = true;
        button2.Enabled = false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}//监控线程
private void SPortThreadExecute()
{
    OVERLAPPED m_ov = new OVERLAPPED();
    m_ov.hEvent = CreateEvent(IntPtr.Zero, true, false, null);    if (m_ov.hEvent > 0)
    {
        bool bSuccess = SetCommMask(comm_handle, EV_CTS | EV_DSR | EV_RLSD);
        if (!bSuccess)
        {
            MessageBox.Show("SetCommMask 出错!");
            CloseHandle(m_ov.hEvent);
            return;
        }        while (true)
        {
            uint dwEventMask = 0;
            bSuccess = WaitCommEvent(comm_handle, ref dwEventMask, ref m_ov);
            if (!bSuccess)
            {
                int errorCode = GetLastError();
                if (errorCode != ERROR_IO_PENDING)
                {
                    continue;
                }
            }            //重叠 I/O 操作正在进行中,可以继续做
            uint Event = WaitForSingleObject(m_ov.hEvent, Timeout.Infinite);
            if (Event == WAIT_OBJECT_0)
            {
                uint BytesLen = 0;
                if (!GetOverlappedResult(comm_handle, ref m_ov, ref BytesLen, false))
                    this.Invoke(new ShowString(AddNewLine), new object[] { "GetOverlappedResult return false. " });
                else
                    this.Invoke(new ShowString(AddNewLine), new object[] { "GetOverlappedResult successfully, " + BytesLen.ToString() + " bytes read. " });                uint dwModemStatus = 0;
                if (GetCommModemStatus(comm_handle, ref dwModemStatus))
                {
                    if ((dwModemStatus & MS_CTS_ON) > 0)
                    { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_CTS_ON is be detected" }); }                    if ((dwModemStatus & MS_DSR_ON) > 0)
                    { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_DSR_ON is be detected" }); }                    if ((dwModemStatus & MS_RLSD_ON) > 0)
                    { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_RLSD_ON is be detected" }); }                    this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return true. Status = " + dwModemStatus.ToString() + ", Now time is " + DateTime.Now.ToString() });
                }
                else
                    this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return false. " });
            }            ResetEvent(m_ov.hEvent);        } //end while
    }

解决方案 »

  1.   

    GetCommModemStatus 函数是怎么写的?
      

  2.   

    这么写的:[DllImport("kernel32.dll")]
    private static extern bool SetCommMask(int hFile, uint dwEvtMask);[DllImport("kernel32.dll")]
    private static extern bool WaitCommEvent(int hFile, ref uint lpEvtMask, ref OVERLAPPED lpOverlapped);[DllImport("kernel32.dll")]
    private static extern bool GetCommModemStatus(int hFile, ref uint modemStat);   //EV_CTS|EV_DSR|EV_RLSD[DllImport("kernel32.dll")]
    private static extern uint WaitForSingleObject(int hFile, int dwMilliseconds);
      

  3.   

    问题从这几方面找:
    1, 把uint 类型改为 int:
    [DllImport("kernel32.dll", SetLastError=true)] static extern int GetCommModemStatus ( int hFile, ref int lpModemStat) 2,保CTS,DSR,RING,RLSD的常量是否正确:
    MS_CTS_ON:0x0010
    The CTS (clear-to-send) signal is on.MS_DSR_ON:0x0020
    The DSR (data-set-ready) signal is on.MS_RING_ON:0x0040
    The ring indicator signal is on.MS_RLSD_ON:0x0080
    The RLSD (receive-line-signal-detect) signal is on.
      

  4.   


                    int dwModemStatus = 0;
                    if (GetCommModemStatus(comm_handle, ref dwModemStatus))
                    {
                        Console.WriteLine(dwModemStatus.ToString());//它的状态为0吗?
                        if ((dwModemStatus & MS_CTS_ON) > 0)
                        { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_CTS_ON is be detected" }); }                    if ((dwModemStatus & MS_DSR_ON) > 0)
                        { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_DSR_ON is be detected" }); }                    if ((dwModemStatus & MS_RLSD_ON) > 0)
                        { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_RLSD_ON is be detected" }); }                    this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return true. Status = " + dwModemStatus.ToString() + ", Now time is " + DateTime.Now.ToString() });
                    }
                    else
                        this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return false. " }); 
    要不就是硬件方面问题啊
      

  5.   

    你指API GetCommModemStatus 返回false,还是指它传出的参数dwModemStatus=0?
      

  6.   

    private const UInt32 EV_RXCHAR = 0x0001;    //A character was received and placed in the input buffer. 
    private const UInt32 EV_RXFLAG = 0x0002;    //The event character was received and placed in the input buffer. 
    private const UInt32 EV_TXEMPTY = 0x0004;   //The last character in the output buffer was sent. 
    private const UInt32 EV_CTS = 0x0008;       //The CTS (clear-to-send) signal changed state. 
    private const UInt32 EV_DSR = 0x0010;       //The DSR (data-set-ready) signal changed state. 
    private const UInt32 EV_RLSD = 0x0020;      //The RLSD (receive-line-signal-detect) signal changed state. 
    private const UInt32 EV_BREAK = 0x0040;     //A break was detected on input. 
    private const UInt32 EV_ERR = 0x0080;       //A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 
    private const UInt32 EV_RING = 0x0100;      //A ring indicator was detected. private const UInt32 MS_CTS_ON = 0x0010;    //The CTS (clear-to-send) signal is on. 
    private const UInt32 MS_DSR_ON = 0x0020;    //The DSR (data-set-ready) signal is on. 
    private const UInt32 MS_RING_ON = 0x0040;   //The ring indicator signal is on. 
    private const UInt32 MS_RLSD_ON = 0x0080;   //The RLSD (receive-line-signal-detect) signal is on.//我指的是它传出的参数dwModemStatus=0
    //改成int还是一样
    uint Event = WaitForSingleObject(m_ov.hEvent, Timeout.Infinite);
    if (Event == WAIT_OBJECT_0)
    {
        uint BytesLen = 0;
        if (!GetOverlappedResult(comm_handle, ref m_ov, ref BytesLen, false))
            this.Invoke(new ShowString(AddNewLine), new object[] { "GetOverlappedResult return false. " });
        else
            this.Invoke(new ShowString(AddNewLine), new object[] { "GetOverlappedResult successfully, " + BytesLen.ToString() + " bytes read. " });    int dwModemStatus = 0;
        if (GetCommModemStatus(comm_handle, ref dwModemStatus))
        {
            if ((dwModemStatus & MS_CTS_ON) > 0)
            { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_CTS_ON is be detected" }); }        if ((dwModemStatus & MS_DSR_ON) > 0)
            { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_DSR_ON is be detected" }); }        if ((dwModemStatus & MS_RLSD_ON) > 0)
            { this.Invoke(new ShowString(AddNewLine), new object[] { "MS_RLSD_ON is be detected" }); }        this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return true. Status = " + dwModemStatus.ToString() + ", Now time is " + DateTime.Now.ToString() });
        }
        else
            this.Invoke(new ShowString(AddNewLine), new object[] { "GetCommModemStatus return false. " });
    }
      

  7.   

    你最好单步调试一下.
    试试更改以下代码(ref --> out) :[DllImport("kernel32.dll")]
    private static extern bool GetCommModemStatus(int hFile, out uint modemStat);  //EV_CTS|EV_DSR|EV_RLSD 
    int dwModemStatus = 0;
    if (GetCommModemStatus(comm_handle, out dwModemStatus)) 
    参考串口监控示例
      

  8.   

    不知道WaitForSingleObject这个用法是否有问题?
    事实上如何触发它我并不确定,因为4配168几乎从来没有成功过,
    偶尔的几次都是4、5触发,或者是串口掉地上了然后莫明其妙就触发了 我用的是COM5(5以下的串口都坏了。。),用它来进行485通讯是没有问题的也许问题并不在于GetCommModemStatus?
      

  9.   

    调试一下,看comm_handle的值是否正确
      

  10.   

    [DllImport("kernel32.dll")] 
    private static extern bool GetCommModemStatus(int hFile, ref uint modemStat); 
    改成这样试试,当然,其它的API函数也要修改。
    [DllImport("kernel32.dll", EntryPoint="GetCommModemStatus", CharSet=CharSet.Auto)]
    private static extern bool GetCommModemStatus(IntPtr hFile, ref int modemStat);