无法打开和关闭一次com端口(通过usb)无法工作

时间:2015-12-25 02:54:55

标签: c# serial-port ftdi

我正在构建一个生成DMX输出的应用程序。应用程序通过USB接口将此数据提供给硬件。由于DMX使用RS485协议,因此几乎可以使用任何RS485 USB转串口转换器。我希望我的应用程序可以通过用户编写的插件进行扩展,这些插件继承自我的基类,而不是处理应用程序和接口之间的通信。 所以这是我的问题:
应用程序启动后,当界面插入时,我无法与界面通信。我使用WqlEventQueryManagementEventWatcher类来检测usb事件(插件和输出)和加载&相应地卸载我的类。调试时我注意到驱动程序类确实看到了设备,但无法从中读取(例如序列号)。在端口可用之前我是否需要重置一些东西? 在status之后FT_INVALID_HANDLE设置为FT_Open,这意味着永远不会完成通信。
FTD2xx类正常工作,除非在启动应用程序后插入接口。
  

<小时/> 的修改
我搞定了。但是为了使我的应用程序中的串行可用,我必须从C#SerialPort类打开,关闭和处理一次。这是为什么?

var ports = SerialPort.GetPortNames();
SerialPort port = new SerialPort(ports[0]);
port.Open();
port.Close();
port.Dispose();
-> Following code works

<小时/> 的代码:
基础驱动程序类

public abstract class Driver
{
    public abstract string FullName { get; set; }
    public virtual string Description { get; set; }
    public abstract string[] HardwareIDs { get; set; }

    public virtual int FrameRate { get; set; }

    public Driver(int framerate) 
    {
        this.FrameRate = framerate;
    }

    public abstract void Start();

    public abstract void Stop();

    public abstract void SetDMXValue(int channel, byte value);
}

FTD2xx驱动程序类

    public class FTD2XX : Driver
    {
        public override string FullName
        { 
            get { return "FTD2XX Usb-Interface"; } 
            set {} 
        }

        public override string Description
        { 
            get { return "Driver for the FTD2xx usb-to-dmx interface"; } 
            set {} 
        }

        public override string[] HardwareIDs
        { 
            get { return new string[] { @"USB\VID_0403&PID_6001" }; } 
            set {} 
        }

        public byte[] buffer { get; private set; }
        public uint handle;
        public bool done = false;
        public int bytesWritten = 0;
        public FT_STATUS status;

        public const byte BITS_8 = 8;
        public const byte STOP_BITS_2 = 2;
        public const byte PARITY_NONE = 0;
        public const UInt16 FLOW_NONE = 0;
        public const byte PURGE_RX = 1;
        public const byte PURGE_TX = 2;

        Thread workThread;

        // DLL IMPORT'S LEFT OUT FOR SIZE //

        public FTD2XX(int frameRate) : base(frameRate)
        {
            this.buffer = new byte[255];
        }

        public override void Start()
        {
            handle = 0;
            status = FT_Open(0, ref handle);
            workThread = new Thread(new ThreadStart(writeData));
            workThread.Start();
        }

        public override void SetDMXValue(int channel, byte value)
        {
            if (buffer != null)
            {
                buffer[channel] = value;
            }
        }

        public void writeData()
        {
            while (!done)
            {
                InitOpenDMX();
                FT_SetBreakOn(handle);
                FT_SetBreakOff(handle);
                bytesWritten = write(handle, buffer, buffer.Length);
                Thread.Sleep(FrameRate);
            }
        }

        public  int write(uint handle, byte[] data, int length)
        {
            IntPtr ptr = Marshal.AllocHGlobal((int)length);
            Marshal.Copy(data, 0, ptr, (int)length);
            uint bytesWritten = 0;
            status = FT_Write(handle, ptr, (uint)length, ref bytesWritten);
            return (int)bytesWritten;
        }

        public void InitOpenDMX()
        {
            status = FT_ResetDevice(handle);
            status = FT_SetDivisor(handle, (char)12);  // set baud rate
            status = FT_SetDataCharacteristics(handle, BITS_8, STOP_BITS_2, PARITY_NONE);
            status = FT_SetFlowControl(handle, (char)FLOW_NONE, 0, 0);
            status = FT_ClrRts(handle);
            status = FT_Purge(handle, PURGE_TX);
            status = FT_Purge(handle, PURGE_RX);
        }

        public override void Stop()
        {
            this.done = true;
            this.workThread.Abort();
            this.workThread = null;
            status = FT_ResetDevice(handle);
            status = FT_Close(handle);
        }

        /// <summary>
        /// Enumaration containing the varios return status for the DLL functions.
        /// </summary>
        public enum FT_STATUS
        {
            FT_OK = 0,
            FT_INVALID_HANDLE,
            FT_DEVICE_NOT_FOUND,
            FT_DEVICE_NOT_OPENED,
            FT_IO_ERROR,
            FT_INSUFFICIENT_RESOURCES,
            FT_INVALID_PARAMETER,
            FT_INVALID_BAUD_RATE,
            FT_DEVICE_NOT_OPENED_FOR_ERASE,
            FT_DEVICE_NOT_OPENED_FOR_WRITE,
            FT_FAILED_TO_WRITE_DEVICE,
            FT_EEPROM_READ_FAILED,
            FT_EEPROM_WRITE_FAILED,
            FT_EEPROM_ERASE_FAILED,
            FT_EEPROM_NOT_PRESENT,
            FT_EEPROM_NOT_PROGRAMMED,
            FT_INVALID_ARGS,
            FT_OTHER_ERROR
        };
    }
}

USB事件处理程序

private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach(Driver driver in this.drivers)
    {
        if (driver.HardwareIDs.Any(hID => (instance.Properties["DeviceID"].Value as string).StartsWith(hID)))
        {
            driver.Start();

            if (this.OnDriverLoaded != null)
                this.OnDriverLoaded(this, new PluginLoadUnloadEventArgs(driver));

            break;
        }
    }
}

Unplug基本相同,但使用了.Stop()OnDriverUnload()

启动后检测任何兼容的USB设备(如果是这样,代码可以正常工作

    ManagementObjectCollection collection;
    using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub"))
        collection = searcher.Get();

    foreach (var device in collection)
    {
        foreach (Driver driver in this.drivers)
        {
            if (driver.HardwareIDs.Any(hID => (device.GetPropertyValue("DeviceID") as string).StartsWith(hID)))
            {
                driver.Start();

                if (this.OnDriverLoaded != null)
                    this.OnDriverLoaded(this, new PluginLoadUnloadEventArgs(driver));

                goto End;
            }
        }
    }
End:
    return;

0 个答案:

没有答案