小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

USB的“JoyStickMouse”例程結(jié)構(gòu)分析

 haodafeng_org 2011-07-28

1、例程的結(jié)構(gòu)

1)底層結(jié)構(gòu)

包括5個(gè)文件:usb_core.cUSB總線數(shù)據(jù)處理的核心文件),usb_init.cusb_int.c(用于端點(diǎn)數(shù)據(jù)輸入輸入中斷處理),usb_mem.c(用于緩沖區(qū)操作),usb_regs.c(用于寄存器操作)。它們都包含了頭文件“usb_lib.h”。在這個(gè)頭文件中,又有以下定義:

#include "usb_type.h"

#include "usb_regs.h"

#include "usb_def.h"

#include "usb_core.h"

#include "usb_init.h"

#include "usb_mem.h"

#include "usb_int.h"

usb_lib.h中又包含了七個(gè)頭文件,其中usb_type.h中主要是用typedefstm32支持的數(shù)據(jù)類型取一些新的名稱。usb_def.h中主要是定義一些相關(guān)的數(shù)據(jù)類型。

還有一個(gè)未包含在usb_lib.h中的頭文件,usb_conf.h用于USB設(shè)備的配置。

2)上層結(jié)構(gòu)

上層結(jié)構(gòu)總共5個(gè)文件:hw_config.c(用于USB硬件配置)、usb_pwr.c(用于USB連接、斷開操作)、usb_istr.c(直接處理USB中斷)、usb_prop.c(用于上層協(xié)議處理,比如HID協(xié)議,大容量存儲(chǔ)設(shè)備協(xié)議)、usb_desc.c(具體設(shè)備的相關(guān)描述符定義和處理)。

可見,STUSB操作庫結(jié)構(gòu)十分清晰明了,我先不準(zhǔn)備直接閱讀源代碼。而是先利用MDK的軟件模擬器仿真執(zhí)行,先了解一下設(shè)備初始化的流程。

2、設(shè)備初始化所做的工作

1Set_System(void)

這個(gè)是main函數(shù)中首先調(diào)用的函數(shù),它位于hw_config.c文件中。它的主要功能是初始化時(shí)鐘系統(tǒng)、使能相關(guān)的外圍設(shè)備電源

配置了JoyStickMouse所用到的5個(gè)按鍵,并且配置了兩個(gè)EXTI中斷,一個(gè)是用于把USB從掛起模式喚醒,還有一個(gè)用途未知。

2USB_Interrupts_Config();

這個(gè)是main函數(shù)中調(diào)用的第二個(gè)函數(shù),它也位于hw_config.c文件中。主要功能是配置USB所用到的中斷

跟蹤到代碼中,主要設(shè)配置了USB低優(yōu)先級(jí)中斷和喚醒中斷,又有一個(gè)EXTI中斷功能未知。

3Set_USBClock()

這個(gè)是main函數(shù)中調(diào)用的第三個(gè)函數(shù),它也位于hw_config.c文件中。它的功能是配置和使能USB時(shí)鐘

4USB_Init(void)

這個(gè)是main函數(shù)中調(diào)用的第四個(gè)函數(shù),它也位于usb_init.c文件中。它初始化了三個(gè)全局指針,指向DEVICE_INFO、USER_STANDARD_REQUESTSDEVICE_PROP結(jié)構(gòu)體。

后面兩個(gè)是函數(shù)指針結(jié)構(gòu)體,里面都是USB請求實(shí)現(xiàn)、功能實(shí)現(xiàn)的函數(shù)指針。

void USB_Init(void)

{

pInformation = &Device_Info;

pInformation->ControlState = 2;

pProperty = &Device_Property;

pUser_Standard_Requests = &User_Standard_Requests;

/* Initialize devices one by one */

pProperty->Init();

}

這三個(gè)結(jié)構(gòu)體都是與具體設(shè)備枚舉和功能實(shí)現(xiàn)相關(guān)的,定義在usb_prop.cusb_desc.c文件中。

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 /*MAX PACKET SIZE*/
};

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_init()函數(shù)調(diào)用pProperty->Init()實(shí)質(zhì)上就是Joystick_init)完成設(shè)備的初始化。

上層程序調(diào)用下次函數(shù)是常規(guī)性的操作。而下層函數(shù)(usb_init相對于usb_prop是輸入底層操作文件)調(diào)用上層文件函數(shù)我們稱之為回調(diào)。

回調(diào)函數(shù)的意義在于同一種操作模式、提供不同的回調(diào)函數(shù)則可以實(shí)現(xiàn)不同的功能。Windows中處理消息,好像也用到了這種模式。

回調(diào)函數(shù)的實(shí)現(xiàn)方法是函數(shù)指針數(shù)組。這是指針的高級(jí)應(yīng)用。

這是函數(shù)的代碼:

void Joystick_init(void)

{

/* Update the serial number string descriptor with the data from the unique ID*/

Get_SerialNum();
//
獲取設(shè)備序列號(hào),轉(zhuǎn)變?yōu)?/span>unicode字符串

pInformation->Current_Configuration = 0;
/* Connect the device */

PowerOn();
//連接USB設(shè)備,實(shí)質(zhì)是能讓主機(jī)檢測到了。

/* USB interrupts initialization */

_SetISTR(0);
/* clear pending interrupts */

wInterrupt_Mask = IMR_MSK;

_SetCNTR(wInterrupt_Mask); /* set interrupts mask */

bDeviceState = UNCONNECTED;

}

實(shí)質(zhì)上,代碼執(zhí)行到這里,開發(fā)板已經(jīng)可以響應(yīng)主機(jī)發(fā)來的數(shù)據(jù)了。但我還是先把main()函數(shù)的代碼看完吧。

5SysTick_Config();

這個(gè)函數(shù)調(diào)用主要是為程序中用到的精確延時(shí)作配置。

3、進(jìn)入主循環(huán)

進(jìn)入主循環(huán)的工作就兩個(gè):

Joystick_Send(JoyState())。

JoyState()用來獲取按鍵的狀態(tài)。

Joystick_Send(JoyState())用來把按鍵狀態(tài)發(fā)到主機(jī)。當(dāng)然這里真正的發(fā)送工作并不是由該代碼完成的。它的工作只是將數(shù)據(jù)寫入IN端點(diǎn)緩沖區(qū),主機(jī)的IN令牌包來的時(shí)候,SIE負(fù)責(zé)把它返回給主機(jī)。

主要代碼如下:
UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 4);
//
從用戶復(fù)制四個(gè)字節(jié)到端點(diǎn)1緩沖區(qū),控制端點(diǎn)的輸入緩沖區(qū)。
SetEPTxValid(ENDP1);/* enable endpoint for transmission */

4、中斷處理過程大致理解

1usb_istr()函數(shù)中的中斷處理簡單分析

有用的代碼大概以下幾段,首先是處理復(fù)位的代碼,調(diào)用設(shè)備結(jié)構(gòu)中的復(fù)位處理函數(shù)。
wIstr = _GetISTR();

if (wIstr & ISTR_RESET & wInterrupt_Mask)

{

_SetISTR((u16)CLR_RESET); //
清復(fù)位中斷
Device_Property.Reset();
}

處理喚醒的代碼:
if (wIstr & ISTR_WKUP & wInterrupt_Mask)

{

_SetISTR((u16)CLR_WKUP);

Resume(RESUME_EXTERNAL);
}

處理總線掛起的代碼:
if (wIstr & ISTR_SUSP & wInterrupt_Mask)

{

if (fSuspendEnabled) /* check if SUSPEND is possible */

{

Suspend();
}

else

{

/* if not possible then resume after xx ms */

Resume(RESUME_LATER);

}

/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */

_SetISTR((u16)CLR_SUSP);

}

處理端點(diǎn)傳輸完成的代碼,這段是最重要的,它調(diào)用底層usb_int.c()文件中的CTR_LP()函數(shù)來處理端點(diǎn)數(shù)據(jù)傳輸完成中斷。
if (wIstr & ISTR_CTR & wInterrupt_Mask)

{

CTR_LP();/* servicing of the endpoint correct transfer interrupt */
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多