串口类问题

时间:2016-02-10 09:35:25

标签: c# serial-port

我有一个类似于此的串口类:

 public static class OldHaspCommunication
 {
    private static SerialPort m_port;
    private static string m_portName;
    private static bool m_isOpen = false;

    private static int m_baudRate;
    private static Parity m_parity;
    private static int m_dataBits;
    private static StopBits m_stopBits;
    private static bool m_xonxoff;
    private static bool m_dtr;
    private static bool m_rts;

    // ................................

    // Open port.
    public static void OpenPort(string portName,
                                int baudRate,
                                Parity parity,
                                int dataBits,
                                StopBits stopBits,
                                bool dtr,
                                bool rts,
                                bool xonxoff = false)
    {

        // Create new Serial Port object
        m_port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);

        // .........................................
        // Set class member variables.

        m_portName = portName;
        m_baudRate = baudRate;
        m_parity = parity;
        m_dataBits = dataBits;
        m_stopBits = stopBits;
        m_xonxoff = xonxoff;
        m_dtr = dtr;
        m_rts = rts;

        // ............................................
        // Initialize some port object properties

        // XOnXOff - parameter
        if (xonxoff)
            m_port.Handshake = Handshake.XOnXOff;

        // Set DTR/RTS 
        m_port.DtrEnable = dtr;
        m_port.RtsEnable = rts;

        // Set
        m_port.ReadTimeout = 500;
        m_port.WriteTimeout = 500;

        // ..............................................
        // Some final steps.

        // Open the port for communications
        m_port.Open();

        // If we get this far, mark port as opened.
        m_isOpen = true;
    }

    /// <summary>
    /// Just makes sure to read the specified number of bytes from the serial port.
    /// Typical reads may return fewer bytes then told to read. This method is used
    /// to avoid this problem.
    /// Based on a similar function from Jon Skeet: http://jonskeet.uk/csharp/readbinary.html
    /// </summary>
    /// <param name="data"> [OUT] Data read should be stored here</param>
    /// <param name="length"> [IN] How much data to read exactly </param>
    /// <param name="count"> [IN] Some kind of retry count parameter.</param>
    private static void ReadAll(byte[] data, uint length, int retryCount)
    {

        // Check data length parameter.
        if (length > data.Length)
        {
            throw new Exception("Wrong data length in ReadAll");
        }

        int offset = 0;
        int i = 0;
        int remaining = checked((int)length); // NOTE: Will throw OverflowException if length > Int32.MaxValue due to checked keyword.

        // Start reading.
        while (remaining > 0)
        {
            // Just a retry count check
            if (i >= retryCount)
            {
                throw new Exception("Exceeded retry count parameter during reading in ReadAll");
            }

            // Read Certain amount of bytes
            int read = m_port.Read(data, offset, remaining);

            // Was there error?
            if (read <= 0)
            {
                throw new EndOfStreamException(String.Format("ReadAll(OldHaspCommunication) - End of data reached with {0} bytes left to read", remaining));
            }

            // Advance offset, and decrease remaining count.
            remaining -= read;
            offset += read;

            i++;

        }


    }

    /// <summary>
    /// Write specified number of bytes to the serial port
    /// </summary>
    /// <param name="data"> [IN] Buffer from which to write data</param>
    /// <param name="length"> [IN] How many bytes to write</param>
    private static void WriteAll(byte[] data, uint length)
    {           
        // TODO: Maybe we should add a retry count as in C++

        int len = checked((int)length); // NOTE: Will throw OverflowException if length > Int32.MaxValue due to checked keyword.

        // We can't write more data to serial port than available in the array.
        if (len > data.Length)
        {
            throw new Exception("Wrong data length in WriteAll");
        }

        // Do the write.
        m_port.Write(data, 0, len);
    }





    /// <summary>
    /// Close the serial port.
    /// NOTE: Don't forget to call this one.
    /// </summary>
    public static void ClosePort()
    {
        if (m_isOpen)
        {
            Reset(); // Calls our custom Reset function.
            m_port.Close(); // Close port
            m_isOpen = false; // Mark this object as closed.
        }
    }

    // ...
    private static void Reset()
    {
        m_port.DiscardInBuffer();
        m_port.DiscardOutBuffer();
    }


}

它似乎工作正常,但在这种情况下我遇到了问题。 当我的设备HASP插入计算机时,一切都很顺利。 然后我拔掉了搭扣并继续使用该类,但我收到的错误是我正在错误地计算数据(签名错误,我使用写/读调用计算)。

然后我再次插入我的HASP并得到了这样的异常(带有堆栈跟踪):

2016-02-10 13:01:14 - [LOG_ERROR] [THREAD ID: 11] General Exception: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
   at ProcessingLibrary.OldHaspCommunication.Reset() in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\HASP\OldHaspCommunication.cs:line 270
   at ProcessingLibrary.OldHaspCommunication.QueryParam(Byte[] in_buffer, UInt32 length, Byte command, Byte[] out_buffer, UInt32 szBuf, Byte& ret_code, Int32 l_entry, Int32 l_loop, Boolean quick_ser_no) in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\HASP\OldHaspCommunication.cs:line 303
   at ProcessingLibrary.OldHaspCommunication.Query(Byte[] in_buffer, UInt32 length, Byte command, Byte[] out_buffer, UInt32 szBuff, Byte& retcode) in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\HASP\OldHaspCommunication.cs:line 277
   at ProcessingLibrary.OldHaspCommunication.QueryCmd8(Byte[] in_buffer, Byte command, Byte[] out_buffer) in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\HASP\OldHaspCommunication.cs:line 286
   at ProcessingLibrary.CryptographyUtilities.SetSessionKey() in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\Security\CryptographyUtilities.cs:line 94
   at ProcessingLibrary.CryptographyUtilities.OldHASPSign(Byte[] buffer, UInt32 size, Byte[] outbuffer, Boolean session) in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\Security\CryptographyUtilities.cs:line 137
   at ProcessingLibrary.UpdateTerminalInfoMethods.TestConnection(ProcessingErrorInfo& errorInfo, String terminalID, UInt32 STAN) in c:\Users\g.\Documents\Visual Studio 2012\Projects\ProcessingLibrary\ProcessingLibrary\src\Processing Functions\UpdateTerminalInfoMethods.cs:line 70 

Query函数(上面列出的)也来自HASP类 - 为了清楚起见,我删除了它们,它们只是以不同方式调用read/write方法,在某些情况下可能Reset

您能否解释一下发生了什么问题?为什么? (Reset函数被Query函数之一调用了。 这必须与我拔掉HASP的事实有关? 但是为什么会出现这种异常呢?

如何修改我的课程,以便如果有人拔出HASP然后插入,那么对HASP的调用是否仍然成功?

请注意,我的设计最初是在申请时拨打OpenPort。并且在申请时也要拨打ClosePort一次。

1 个答案:

答案 0 :(得分:0)

虽然捕获异常代价很高,但我认为你需要抓住它,如果我没有弄错,你使用的HASP是USB-to-COM模拟器?

  • 您可以使用WMI或
  • 检测HASP(USB)连接
  • 在ReadAll / WriteAll / Reset - 或
  • 断开连接期间捕获异常
  • 创建线程以监视异常并重新启动线程以再次尝试连接。

将尝试在一段时间内提供伪代码。