在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32--USB詳細(xì)使用說明

            STM32--USB詳細(xì)使用說明

            作者: 時間:2016-11-27 來源:網(wǎng)絡(luò) 收藏

            ***************(3)**************

            1.獲取設(shè)備描述符

            usb_int.c的文件里面

            低優(yōu)先級中斷 在控制 中斷 批量傳輸下使用(在單緩沖模式下使用)
            當(dāng)一次正確的OUT,SETUP,IN數(shù)據(jù)傳輸完成后,硬件會自動設(shè)置此位為NAK狀態(tài),使應(yīng)用程序有足夠的時間處理完當(dāng)前傳輸?shù)臄?shù)據(jù)后,響應(yīng)下一個數(shù)據(jù)分組

            void CTR_LP(void)
            {
            __IO uint16_t wEPVal = 0;

            while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
            {

            EPindex = (uint8_t)(wIstr & ISTR_EP_ID);//讀出端點(diǎn)ID
            if (EPindex == 0)//如果是端點(diǎn)0
            {





            SaveRState = _GetENDPOINT(ENDP0);//讀取端點(diǎn)0寄存器USB_EP0R
            SaveTState = SaveRState & EPTX_STAT;//保存發(fā)送狀態(tài)位
            SaveRState &= EPRX_STAT;//保存接受狀態(tài)位
            _SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK);//端點(diǎn)以NAK分組響應(yīng)所有的發(fā)送和接受請求(解釋在上面)

            if ((wIstr & ISTR_DIR) == 0)//IN令牌,數(shù)據(jù)被取走

            {



            _ClearEP_CTR_TX(ENDP0);//清除正確發(fā)送標(biāo)志位
            In0_Process();//處理INT事件

            _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
            return;
            }
            else
            {


            wEPVal = _GetENDPOINT(ENDP0);//得到端點(diǎn)0寄存器的數(shù)據(jù)
            if ((wEPVal &EP_SETUP) != 0)//SETUP分組傳輸完成標(biāo)志
            {
            _ClearEP_CTR_RX(ENDP0);
            Setup0_Process();//處理SETUP事件

            //程序會進(jìn)入到這個函數(shù)里面

            _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
            return;
            }

            else if ((wEPVal & EP_CTR_RX) != 0)
            {
            _ClearEP_CTR_RX(ENDP0);
            Out0_Process();//處理OUT事件

            _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
            return;
            }
            }
            }
            else//如果是除端點(diǎn)0以外的端點(diǎn)
            {


            wEPVal = _GetENDPOINT(EPindex);//得到相應(yīng)端點(diǎn)寄存器值
            if ((wEPVal & EP_CTR_RX) != 0)//檢測正確接收標(biāo)志 PC-USB OUT int
            {

            _ClearEP_CTR_RX(EPindex);//清除相應(yīng)的標(biāo)志


            (*pEpInt_OUT[EPindex-1])();//調(diào)用OUT int服務(wù)功能

            }

            if ((wEPVal & EP_CTR_TX) != 0)//檢測正確發(fā)送標(biāo)志 USB-PC IN int
            {

            _ClearEP_CTR_TX(EPindex);//清除相應(yīng)的標(biāo)志


            (*pEpInt_IN[EPindex-1])();//調(diào)用IN int服務(wù)功能
            }

            }

            }
            }

            usb_coer.c的文件里面,主要是得到主機(jī)發(fā)來的標(biāo)準(zhǔn)請求命令

            uint8_t Setup0_Process(void)
            {

            union
            {
            uint8_t* b;
            uint16_t* w;
            } pBuf;

            #ifdef STM32F10X_CL
            USB_OTG_EP *ep;
            uint16_t offset = 0;
            ep = PCD_GetOutEP(ENDP0);
            pBuf.b = ep->xfer_buff;
            #else
            uint16_t offset = 1;
            //得到接受緩沖區(qū)地址寄存器地址
            pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2);
            #endif

            if (pInformation->ControlState != PAUSE)
            {
            pInformation->USBbmRequestType = *pBuf.b++;

            pInformation->USBbRequest = *pBuf.b++;

            pBuf.w += offset;
            pInformation->USBwValue = ByteSwap(*pBuf.w++);

            pBuf.w += offset;
            pInformation->USBwIndex = ByteSwap(*pBuf.w++);

            pBuf.w += offset;
            pInformation->USBwLength = *pBuf.w;

            }

            pInformation->ControlState = SETTING_UP;
            if (pInformation->USBwLength == 0)
            {

            NoData_Setup0();
            }
            else
            {

            Data_Setup0();//由于是有數(shù)據(jù)的傳輸,所有要進(jìn)入到這個函數(shù)
            }
            return Post0_Process();
            }

            usb_core.c的文件里面,這里只是選取了GET DESCRIPTOR

            的程序部分,其他的部分刪除了

            void Data_Setup0(void)
            {
            uint8_t *(*CopyRoutine)(uint16_t);
            RESULT Result;
            uint32_t Request_No = pInformation->USBbRequest;

            uint32_t Related_Endpoint, Reserved;
            uint32_t wOffset, Status;

            CopyRoutine = NULL;
            wOffset = 0;

            //看標(biāo)準(zhǔn)請求碼格式就知道了
            if (Request_No == GET_DESCRIPTOR)
            {
            //pInformation->USBbmRequestType是下面的兩種 標(biāo)準(zhǔn)請求或設(shè)備請求
            if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
            {
            uint8_t wValue1 = pInformation->USBwValue1;//高一字節(jié)得到描述表種類 一共有5種
            if (wValue1 == DEVICE_DESCRIPTOR)//設(shè)備描述
            {
            CopyRoutine = pProperty->GetDeviceDescriptor;
            }
            else if (wValue1 == CONFIG_DESCRIPTOR)
            {
            CopyRoutine = pProperty->GetConfigDescriptor;//配置描述
            }
            else if (wValue1 == STRING_DESCRIPTOR)
            {
            CopyRoutine = pProperty->GetStringDescriptor;//字符串描述
            }
            }
            }

            if (CopyRoutine)
            {
            pInformation->Ctrl_Info.Usb_wOffset = wOffset;//本子程序的wOffset是0
            pInformation->Ctrl_Info.CopyData = CopyRoutine;//使指針pInformation->Ctrl_Info.CopyData指向CopyRoutine


            (*CopyRoutine)(0);//第一次執(zhí)行時Length=0 返回的是有效數(shù)據(jù)的長度 存儲到pInformation->Ctrl_Info.Usb_wLength
            Result = USB_SUCCESS;
            }
            else
            {//如果標(biāo)準(zhǔn)請求不存在 看類 廠商請求中是否有
            Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest);
            if (Result == USB_NOT_READY)
            {
            pInformation->ControlState = PAUSE;
            return;
            }
            }

            if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF)//如果字符的長度是0xffff
            {

            pInformation->ControlState = PAUSE;
            return;
            }
            if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0))
            {

            pInformation->ControlState = STALLED;
            return;
            }

            if (ValBit(pInformation->USBbmRequestType, 7))//D7表示數(shù)據(jù)傳輸方向 1:設(shè)備向主機(jī)
            {

            __IO uint32_t wLength = pInformation->USBwLength;

            //設(shè)置使其為USB主機(jī)設(shè)置的長度 本程序HID 鼠標(biāo) pProperty->MaxPacketSize是0x40
            if (pInformation->Ctrl_Info.Usb_wLength > wLength)//字符的長度大于主機(jī)要求的長度

            {
            pInformation->Ctrl_Info.Usb_wLength = wLength;

            //將其設(shè)置為主機(jī)要求的
            }
            else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength)//字符的長度小于主機(jī)要求的
            {
            if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) //如果字符的長度長度小于每包數(shù)據(jù)最大字節(jié)數(shù)
            {
            Data_Mul_MaxPacketSize = FALSE;
            }
            else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0)//如果是其整數(shù)倍
            {
            Data_Mul_MaxPacketSize = TRUE;
            }
            }

            pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;
            DataStageIn();
            }
            else//主機(jī)向設(shè)備
            {
            pInformation->ControlState = OUT_DATA;
            vSetEPRxStatus(EP_RX_VALID);
            }

            return;
            }

            usb_coer.c的文件里面

            void DataStageIn(void)
            {
            ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;//端點(diǎn)信息保存在指針變量中
            uint32_t save_wLength = pEPinfo->Usb_wLength;//得到字符的長度
            uint32_t ControlState = pInformation->ControlState;//得到當(dāng)前的狀態(tài)

            uint8_t *DataBuffer;
            uint32_t Length;

            if ((save_wLength == 0) && (ControlState == LAST_IN_DATA))//如果字符長度為0 且控制狀態(tài)是最后輸入的數(shù)據(jù)
            {
            if(Data_Mul_MaxPacketSize == TRUE)//如果字符的長度是數(shù)據(jù)包的整數(shù)倍
            {

            Send0LengthData();
            ControlState = LAST_IN_DATA;
            Data_Mul_MaxPacketSize = FALSE;//這一次發(fā)送0字節(jié) 狀態(tài)轉(zhuǎn)為最后輸入階段
            }
            else//字符的長度比數(shù)據(jù)包要小
            {//數(shù)據(jù)已經(jīng)發(fā)送完

            ControlState = WAIT_STATUS_OUT;

            #ifdef STM32F10X_CL
            PCD_EP_Read (ENDP0, 0, 0);
            #endif
            #ifndef STM32F10X_CL
            vSetEPTxStatus(EP_TX_STALL);//設(shè)置端點(diǎn)的發(fā)送狀態(tài)停止
            #endif
            }
            goto Expect_Status_Out;
            }

            Length = pEPinfo->PacketSize;//得到數(shù)據(jù)包大小 64字節(jié)
            ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;//比較大小得到是LAST_IN_DATA還是IN_DATA 18字節(jié)<64字節(jié) ControlState = LAST_IN_DATA

            if (Length > save_wLength)
            {
            Length = save_wLength;
            }

            DataBuffer = (*pEPinfo->CopyData)(Length);//DataBuffer指向要復(fù)制數(shù)據(jù)的地址 這個地址是隨Usb_wOffset變化的

            #ifdef STM32F10X_CL
            PCD_EP_Write (ENDP0, DataBuffer, Length);
            #else
            //GetEPTxAddr(ENDP0) 得到發(fā)送緩沖區(qū)相應(yīng)端點(diǎn)的地址
            //將DataBuffer中的數(shù)據(jù)復(fù)制到相應(yīng)的發(fā)送緩沖區(qū)中
            UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
            #endif

            SetEPTxCount(ENDP0, Length);//設(shè)置相應(yīng)的端點(diǎn)要發(fā)送的字節(jié)數(shù)

            pEPinfo->Usb_wLength -= Length;//等于0
            pEPinfo->Usb_wOffset += Length;//偏移到18
            vSetEPTxStatus(EP_TX_VALID);//使能發(fā)送端點(diǎn) 只要主機(jī)的IN令牌包一來 SIE就會將描述符返回給主機(jī)

            USB_StatusOut();
            //設(shè)置接收端點(diǎn)有效 這個實(shí)際上使接受也有效,

            Expect_Status_Out:
            pInformation->ControlState = ControlState;//保存控制狀態(tài)
            }

            ***************(4)**************

            uint8_t In0_Process(void)
            {
            uint32_t ControlState = pInformation->ControlState;

            if ((ControlState == IN_DATA) || (ControlState ==LAST_IN_DATA))//進(jìn)入到這里

            {
            DataStageIn();//第一次取設(shè)備描述符只取一次當(dāng)前的狀態(tài)變?yōu)閃AIT_STATUS_IN表明設(shè)備等待狀態(tài)過程 主機(jī)輸出0字節(jié)

            ControlState = pInformation->ControlState;
            }

            else if (ControlState == WAIT_STATUS_IN)//設(shè)置地址狀態(tài)階段進(jìn)入這個程序
            {
            if ((pInformation->USBbRequest == SET_ADDRESS) &&
            (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
            {
            SetDeviceAddress(pInformation->USBwValue0);//設(shè)置使用新的地址
            pUser_Standard_Requests->User_SetDeviceAddress();
            }
            (*pProperty->Process_Status_IN)();
            ControlState = STALLED;//變?yōu)檫@個狀態(tài)
            }

            else
            {
            ControlState = STALLED;
            }

            pInformation->ControlState = ControlState;

            return Post0_Process();
            }



            關(guān)鍵詞: STM32USB使用說

            評論


            技術(shù)專區(qū)

            關(guān)閉