stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet

时间:2024-05-31 08:17:52

一 上位机的实现

USB上位机使用c#编写,使用到是著名的USB开源库LibUsbDotNet,驱动也是通过LibUsbDotNet自带的InfWizard.exe生成的,实现效果如图1所示,stm32 上电时,软件能够自动检测并显示相关信息,点击亮按钮,上位机通过端点1发一个字节到下位机stm32板上并控制板上的ledstm32收到数据后通过端点2上传2字节的反馈信息。

stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet


stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet

stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet

实现效果图


代码如下:

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

using LibUsbDotNet;

using LibUsbDotNet.Info;

using LibUsbDotNet.Main;

using LibUsbDotNet.DeviceNotify;

 

namespace stm32_USB_led控制

{

 

    public partial class Form1 : Form

    {

        const  ushort PID = 0x5712;  /*产品ID*/

        const  ushort VID = 0x0483;  /*厂商ID*/

        private  UsbDevice stm32UsbDevice;

        private UsbDeviceFinder stm32UsbFinder = new UsbDeviceFinder(VID, PID);

        private IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();

        private UsbEndpointWriter WR;

        private UsbEndpointReader RD;

        public Form1()

        {

 

            InitializeComponent();

            

        }

        //窗体载入事件

        private void Form1_Load(object sender, EventArgs e)

        {

            UsbDeviceNotifier.OnDeviceNotify += OnDeviceNotifyEvent;

            FindUsbDevice();

        }

        //设备通知事件

        private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)

        {

            UsbRegDeviceList DeviceList = UsbDevice.AllLibUsbDevices;

            UsbRegistry RegInfo = DeviceList.Find(stm32UsbFinder);

            if (e.EventType == EventType.DeviceArrival)

            {

                //匹配插入的设备

                if (e.Device.IdProduct == PID && e.Device.IdVendor == VID)

                {

                    try

                    {

                        /*打开Usb----------------------------------------------------------------*/

                        stm32UsbDevice = UsbDevice.OpenUsbDevice(stm32UsbFinder);

                        /*打开端点2,类型为中断端点--------------------------------------*/

                        WR = stm32UsbDevice.OpenEndpointWriter(WriteEndpointID.Ep02, EndpointType.Interrupt);

                        RD = stm32UsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);

                        RD.DataReceived += (OnRxEndPointData);

                        RD.DataReceivedEnabled = true;

            label.Text = "连接信息:设备已连接";

                    Manufaturer.Text = "生产厂商:" + RegInfo.FullName;

                    ProductDecrip.Text = "产品描述:" + RegInfo.Name;

                    SerialNum.Text = "***:" + e.Device.SerialNumber;

                    }

                    catch (Exception)

                    {

                        MessageBox.Show("USB打开失败!");

                    }

        

                }

            }

            else if (e.EventType == EventType.DeviceRemoveComplete)

            {

                //匹配移除的设备

                if (e.Device.IdProduct == PID && e.Device.IdVendor == VID)

                {

                    label.Text = "连接信息:设备已移除";

                    Manufaturer.Text = "生产厂商:";

                    ProductDecrip.Text = "产品描述:" ;

                    SerialNum.Text = "***:" ; 

  CloseUSB();

                }

            }

        }

        /*寻找指定VIDUSB设备,只在软件初始化时用到----------------------*/

        bool FindUsbDevice()

        {

            UsbRegDeviceList DeviceList = UsbDevice.AllLibUsbDevices;

            UsbRegistry  RegInfo =  DeviceList.Find(stm32UsbFinder);

            if (RegInfo != null)

            {

                try

                {    

                    /*打开Usb---------------------------------------*/                   

                    stm32UsbDevice = UsbDevice.OpenUsbDevice(stm32UsbFinder);

               

                    /*打开端点2,类型为中断端点----------------------*/

                    WR = stm32UsbDevice.OpenEndpointWriter(WriteEndpointID.Ep02, EndpointType.Interrupt);

                }

                catch (Exception)

                {

                    MessageBox.Show("USB打开失败!");

                    return false;

                }

                label.Text = "连接信息:设备已连接";

                Manufaturer.Text = "生产厂商:" + RegInfo.FullName;

                ProductDecrip.Text = "产品描述:"+ RegInfo.Name;

                SerialNum.Text = "***:" + RegInfo.SymbolicName;                

                return true;

            }

            else

            {

                label.Text = "连接信息:已断开连接";

                Manufaturer.Text = "生产厂商:";

                ProductDecrip.Text = "产品描述:";

                SerialNum.Text = "***:";

            }

            return false;

        }

        //关闭USB设备

        private void CloseUSB()

        {

            if (!ReferenceEquals(WR, null))

                WR.Dispose();

            if (!ReferenceEquals(stm32UsbDevice, null))

                stm32UsbDevice.Close();

 

        }

        private void button_Click(object sender, EventArgs e)

        {

            byte[] txBuf = new byte[2];

            int i=0;

            if (led.Value)

            {

                led.Value = false;

                txBuf[0] = 0x00;

                button.Text = "";

            }   

            else 

            {

                led.Value = true;

                txBuf[0] = 0x01;

                button.Text = "";

            }

            if (stm32UsbDevice.IsOpen)

            WR.Write(txBuf, 1000, out i);

        }

         //USB接收事件

        private static void OnRxEndPointData(object sender, EndpointDataEventArgs e)

        {

            MessageBox.Show("收到数据:"+e.Count.ToString()+"Bytes");

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)

        {

            CloseUSB();

        }

    }

}

 

二 下位机的实现

收发回调函数如下

void EP1_IN_Callback(void)

{

GUI_DispStringAt("send complete!",60,200);

}

void EP2_OUT_Callback(void)

{

u8 DataBuf[8];

u8 len;

len = USB_SIL_Read(EP2_OUT,DataBuf);

SetEPRxValid(ENDP2);

if(DataBuf[0] == 1)

{

GPIOE->ODR |=  (1<<0);

GUI_DispStringAt("led on!  ",60,120);

}

else if (DataBuf[0] == 0)

{

GUI_DispStringAt("led off! ",60,120);

GPIOE->ODR = ~GPIOD->ODR;

}

GUI_DispDecAt(len,60,150,2);

GUI_DispString("Bytes");

    /*返回2字节到上位机---------------------------------------------------------------------*/

USB_SIL_Write(EP1_IN,DataBuf,2);

SetEPTxValid(ENDP1);

}

设备描述符定义如下

 

/* USB标准设备描述符(固定为18个字节)------------------------------------------------*/

const uint8_t USB_DeviceDesc[18] =

{

    18,                         /*设备描述符长度--------------------------------*/

    USB_DeviceDescTyp,          /*描述符类型-------------------------------------*/

    0x00,                       /*bcdUSB-------------------------------------------*/

    0x02,

    0xff,                       /*bDeviceClass:0xff表示自定义*/

    0xff,                       /*bDeviceSubClass:0xff表示自定义*/

    0xff,                       /*bDeviceProtocol:0xff表示自定义*/

    0x40,                       /*bMaxPacketSize 64*/

  

    0x83,                       /*销售商的ID:先低后高*/

    0x04,

  

    0x12,                       /*产品ID:先低后高*/

    0x57,

    

    0x00,                       /*bcdDevice rel. 2.00*/

    0x02,

    1,                          /*manufacturer:厂商描述在字符串描述符中的索引*/

    2,                          /*product:产品描述在字符串描述符中的索引*/

    3,                          /*SerialNum:***在字符串描述符中的索引*/

    0x01                        /*bNumConfigurations*/

}; /* USBDevice_DeviceDescriptor */

 

/* 配置描述符(固定为9个字节)------------------------------------------------------------*/

const uint8_t USB_ConfigDesc[] =

{

    0x09, /* bLength: Configuation Descriptor size--------------------------------------------*/

    USB_ConfigDescTyp, /* bDescriptorType: Configuration-------------------------------*/

    32 ,0x00,/* 配置+接口+端点字节数------------------------------------------------------*/

    

    0x01,         /*接口数: 1 个接口*/

    0x01,         /*配置值配置的ID1*/

    0x00,         /*iConfiguration: Index of string descriptor describing

                                     the configuration*/

    0xc0,         /*属性: bus powered */

    0x64,         /*功耗以2mA为单位----------------------------------------------------*/

/* 接口描述符(固定为9个字节)----------------------------------------------------------------*/

    0x09,         /*bLength: Interface Descriptor size*/

    USB_IntefaceDescTyp,/*bDescriptorType: Interface descriptor type*/

    0x00,         /*接口号*/

    0x00,         /*bAlternateSetting: Alternate setting*/

    0x02,         /*接口所使用的端点数(不包括端点0)*/

    0xff,         /*bInterfaceClass: 通信接口*/

    0xff,         /*bInterfaceSubClass : 1=BOOT, 0=no boot------------------------------*/

    0xff,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse------------------*/

    0,           /*接口描述符在字符串描述中的索引------------------------------------*/

   /* 端点描述符(包含2个端点)----------------------------------------------------------------*/

/*端点1描述符*/

0x07,          /*bLength: Endpoint Descriptor size------------------------------------*/

USB_EndPDescTyp, /*bDescriptorType:*/

 

0x81,          /*端点地址bEndpointAddress: Endpoint Address (IN)------------*/

0x03,          /*端点属性bmAttributes: Interrupt endpoint*/

0x08,          /*最大包长度wMaxPacketSize: 8 Byte max------------------------*/

0x00,

0x20,          /*主机轮询周期(1ms为单位): 32 ms--------------------------------*/

 

/*端点2描述符*/

0x07,          /*bLength: Endpoint Descriptor size----------------------------------*/

USB_EndPDescTyp, /*bDescriptorType:*/

0x02,          /*端点地址bEndpointAddress: Endpoint Address (OUT)----------*/

0x03,          /*端点属性bmAttributes: Interrupt endpoint*/

0x02,          /*最大包长度wMaxPacketSize: 8 Byte max */

0x00,

0x20,           /*主机轮询周期(1ms为单位): 32 ms----------------------------*/

};

 

 

/* USB String Descriptors (optional) */

const uint8_t USBDevice_StringLangID[] =

{

6,

USB_StrDescTyp,

0x09,

0x04,

0x04,

0x08

}; /* LangID = 0x0409: U.S. English LangID = 0x0804: chinese*/

 

const uint8_t USBDevice_StringVendor[] =

{

10, 

USB_StrDescTyp,  /* bDescriptorType*/

/**-------------------------------

ASCII输入:lw技术

UNICODE输出

size:8Bytes

---------------------------------*/

0x6c,0x0,0x77,0x0,

0x80,0x62,0x2f,0x67

 

};

 

const uint8_t USBDevice_StringProduct[] =

{

24,                    /* bLength -------------------------------------*/

USB_StrDescTyp,        /* bDescriptorType ----------------------------*/ 

/**-------------------------------

ASCII输入:stm32中断传输实验

UNICODE输出

size:22Bytes

---------------------------------*/

   0x73,0x0,0x74,0x0,0x6d,0x0,0x33,0x0,

   0x32,0x0,0x2d,0x4e,0xad,0x65,0x20,0x4f,

   0x93,0x8f,0x9e,0x5b,0x8c,0x9a

};

const uint8_t USBDevice_StringSerial[] =

{

20,                     /* bLength --------------------------------------------*/

USB_StrDescTyp,        /* bDescriptorType -----------------------------------*/

/**-------------------------------

ASCII输入:roger-wen

UNICODE输出

size:18Bytes

---------------------------------*/

0x72,0x0,0x6f,0x0,0x67,0x0,0x65,0x0,

    0x72,0x0,0x2d,0x0,0x77,0x0,0x65,0x0,

    0x6e,0x0

};








































stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet



from: http://bbs.elecfans.com/infocenter.php?mod=space&uid=1516870&do=blog&id=363893