新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32--USB詳細使用說明

        STM32--USB詳細使用說明

        作者: 時間:2016-11-27 來源:網絡 收藏
        說明:使用的是STM32F103ZET6

        硬件原理圖

        本文引用地址:http://www.104case.com/article/201611/322088.htm

        在開始枚舉設備的一些初始化

        void bsp_USBInit(void)
        {

        GPIO_InitTypeDef GPIO_InitStructure;


        RCC_APB2PeriphClockCmd(RCC_USB_PULL_UP, ENABLE);

        USB_CABLE_DISABLE();


        GPIO_InitStructure.GPIO_Pin = PIN_USB_PULL_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        {
        NVIC_InitTypeDef NVIC_InitStructure;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        }

        RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);


        USB_Init();

        }

        現在開始分析真正的初始化

        第一步:初始化,總線復位及向默認地址 0發送 GET_DESCRIPTOR 指令包,請求設備描述

        1)Index[4 - 5]:表示 USB插入總線復位;

        2)Index[7 - 8]:表示主機向默認地址發送GET_DESCRIPTOR指令包,詳細信
        息也抓出來了,如(圖二)所示

        3)Index[15 - 17]:表示設備向主機發送設備描述數據 Index[16]
        4)Index[18 - 19]:表示主機完成 GET_DESCRIPTOR指令后,給設備發送一個
        空應答

        現在具體的分析103的usb的執行過程 按順序向下執行

        ***************(1)**************

        DEVICE_INFO *pInformation;

        DEVICE_PROP *pProperty;

        DEVICE_PROP Device_Property =
        {
        Joystick_init,
        Joystick_Reset,
        Joystick_Status_In,
        Joystick_Status_Out,
        Joystick_Data_Setup,
        Joystick_NoData_Setup,
        Joystick_Get_Interface_Setting,
        Joystick_GetDeviceDescriptor,
        Joystick_GetConfigDescriptor,
        Joystick_GetStringDescriptor,
        0,
        0x40
        };

        USER_STANDARD_REQUESTS User_Standard_Requests =
        {
        Joystick_GetConfiguration,
        Joystick_SetConfiguration,
        Joystick_GetInterface,
        Joystick_SetInterface,
        Joystick_GetStatus,
        Joystick_ClearFeature,
        Joystick_SetEndPointFeature,
        Joystick_SetDeviceFeature,
        Joystick_SetDeviceAddress
        };

        //USB內核將主機發送過來的用于實現USB設備的設置包保存在設備信息結構表中
        typedef struct _DEVICE_INFO
        {
        uint8_t USBbmRequestType;
        uint8_t USBbRequest;
        uint16_t_uint8_t USBwValues;
        uint16_t_uint8_t USBwIndexs;
        uint16_t_uint8_t USBwLengths;

        uint8_t ControlState;
        uint8_t Current_Feature;
        uint8_t Current_Configuration;
        uint8_t Current_Interface;
        uint8_t Current_AlternateSetting;

        ENDPOINT_INFO Ctrl_Info;
        }DEVICE_INFO;

        usb_init.c文件里面的

        void USB_Init(void)
        {
        pInformation = &Device_Info;
        pInformation->ControlState = 2;
        pProperty = &Device_Property;
        pUser_Standard_Requests = &User_Standard_Requests;

        pProperty->Init();
        }

        ***************(2)**************通過函數指針指向這個初始化函數pProperty 在usb_prop.c文件里面

        void Joystick_init(void)
        {


        Get_SerialNum();//得到串行號

        pInformation->Current_Configuration = 0;//

        PowerOn();//將USB上電 連接設備


        USB_SIL_Init();//主要是CNTR寄存器的初始化
        bDeviceState = UNCONNECTED;//設備狀態標志 當前狀態未連接
        }

        hw_config.c文件里面 這個和標準的不一樣有改動,獲取設備版本號,將其存入到版本號字符串。

        void Get_SerialNum(void) //得到串行號
        {
        uint32_t Device_Serial0, Device_Serial1, Device_Serial2;
        Device_Serial0 = *(__IO uint32_t*)(0x1FFFF7E8);
        Device_Serial1 = *(__IO uint32_t*)(0x1FFFF7EC);
        Device_Serial2 = *(__IO uint32_t*)(0x1FFFF7F0);
        Device_Serial0 += Device_Serial2;
        if (Device_Serial0 != 0)
        {
        IntToUnicode (Device_Serial0, &Joystick_StringSerial[2] , 8);
        IntToUnicode (Device_Serial1, &Joystick_StringSerial[18], 4);
        }
        }

        usb_pwr.c文件里面 在這個文件里面只是使能了復位,掛起,喚醒中斷,在PowerOn函數使能了復位中斷以后,將進入到USB的復位中斷里面去。

        然后再執行函數USB_SIL_Init 將所有的USB中斷都打開。在D+被接通上拉以后,設備就能被主機檢測到。

        RESULT PowerOn(void)
        {
        #ifndef STM32F10X_CL
        uint16_t wRegVal;


        USB_Cable_Config(ENABLE);//將USB上電連接


        //對USB模塊強制復位,類似于USB總線上的復位信號。USB模塊將一直保持在復位狀態下
        //直到軟件清除此位。如果USB復位中斷被使能,將產生一個復位中斷。
        wRegVal = CNTR_FRES;//強制復位
        _SetCNTR(wRegVal);


        wInterrupt_Mask = 0;
        _SetCNTR(wInterrupt_Mask);//清除復位信號

        _SetISTR(0);

        //復位中斷屏蔽位 掛起中斷屏蔽位 喚醒中斷屏蔽位使能
        wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;

        _SetCNTR(wInterrupt_Mask);
        #endif

        return USB_SUCCESS;
        }

        usb_istr.c文件里面,下面只寫了進入到復位中斷函數,進入到USB連接狀態

        void USB_Istr(void)

        {

        wIstr = _GetISTR();

        #if (IMR_MSK & ISTR_RESET)//USB復位請求中斷
        if (wIstr & ISTR_RESET & wInterrupt_Mask)
        {
        _SetISTR((uint16_t)CLR_RESET);//清楚復位中斷標志
        Device_Property.Reset();//進入到復位中斷
        #ifdef RESET_CALLBACK
        RESET_Callback();
        #endif
        }
        #end

        }

        usb_prop.c文件里面,實現對端點的設置。

        void Joystick_Reset(void)
        {

        pInformation->Current_Configuration = 0;
        pInformation->Current_Interface = 0;


        pInformation->Current_Feature = Joystick_ConfigDescriptor[7];//供電模式選擇

        #ifdef STM32F10X_CL


        OTG_DEV_EP_Init(EP1_IN, OTG_DEV_EP_TYPE_INT, 4);
        #else

        SetBTABLE(BTABLE_ADDRESS);//分組緩沖區描述表地址設置


        SetEPType(ENDP0, EP_CONTROL);//初始化為控制端點類型
        SetEPTxStatus(ENDP0, EP_TX_STALL); //端點以STALL分組響應所有的發送請求。

        //也就是端點狀態設置成發送無效,也就是主機的IN令牌包來的時候,回送一個STALL。
        SetEPRxAddr(ENDP0, ENDP0_RXADDR);//設置端點0描述符的接受地址,

        SetEPTxAddr(ENDP0, ENDP0_TXADDR);//設置端點0描述符的發送地址

        Clear_Status_Out(ENDP0);

        //僅用于控制端點 如果STATUS_OUT位被清除,OUT分組可以包含任意長度的數據
        SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);

        //設置端點0的接受字節寄存器的最大值是64
        SetEPRxValid(ENDP0);//設置接受端點有效


        SetEPType(ENDP1, EP_INTERRUPT);//初始化為中斷端點類型
        SetEPTxAddr(ENDP1, ENDP1_TXADDR);//設置發送數據的地址
        SetEPTxCount(ENDP1, 4);//設置發送的長度
        SetEPRxStatus(ENDP1, EP_RX_DIS);//設置接受端點關閉
        SetEPTxStatus(ENDP1, EP_TX_NAK);//設置發送端點端點非應答


        SetDeviceAddress(0);//設置設備用缺省地址相應
        #endif

        bDeviceState = ATTACHED;//當前狀態連接
        }

        usb_sil.c的文件里面,主要是使能了如下這些中斷

        CNTR_CTRM 正確傳輸(CTR)中斷使能 CNTR_WKUPM 喚醒中斷使能
        CNTR_SUSPM 掛起(SUSP)中斷使能 CNTR_ERRM 出錯中斷使能
        CNTR_SOFM 幀首中斷使能 CNTR_ESOFM 期望幀首中斷使能CNTR_RESETM 設置此位將向PC主機發送喚醒請求。根據USB協議,如果此位在1ms到15ms內保持有效,主機將對USB模塊實行喚醒操作。

        uint32_t USB_SIL_Init(void)
        {
        #ifndef STM32F10X_CL


        _SetISTR(0);//清除中斷標志
        wInterrupt_Mask = IMR_MSK;

        //這組寄存器用于定義USB模塊的工作模式,中斷的處理,設備的地址和讀取當前幀的編號
        _SetCNTR(wInterrupt_Mask);//設置相應的控制寄存器
        #else

        OTG_DEV_Init();
        #endif

        return 0;
        }


        上一頁 1 2 3 下一頁

        關鍵詞: STM32USB使用說

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 福贡县| 开封市| 广东省| 绥中县| 牙克石市| 江门市| 曲麻莱县| 土默特左旗| 谢通门县| 左贡县| 郎溪县| 阆中市| 夏河县| 拉萨市| 桑日县| 平舆县| 宿州市| 大同县| 汾阳市| 乐清市| 安新县| 宝清县| 高阳县| 宜宾市| 鸡东县| 彭山县| 婺源县| 高雄市| 渝北区| 松江区| 蒙山县| 石景山区| 剑阁县| 静安区| 洛阳市| 博罗县| 琼结县| 刚察县| 满城县| 鄂托克前旗| 廊坊市|