下面再來看第2個(gè)函數(shù)Set_USBClock()-------兩句話:
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);/*EnableUSBclock*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB,ENABLE);72M除1。5=48然后允許USB的時(shí)鐘。這個(gè)要看一下數(shù)據(jù)手冊。從數(shù)據(jù)手冊比較好理解。它是直接從PCLK中除一個(gè)數(shù),可以除1也可以除1.5.。這段還是比較好理解的。
再看第3個(gè)函數(shù)USB_Interrupts_Config()-------配置USB中斷
在該函數(shù)中使能了兩個(gè)中斷,一個(gè)是USB,一個(gè)是串口。至于中斷放在RAM或FLASH當(dāng)然一般是后者,所以在這也就沒有什么意義了。串口優(yōu)先級為1,USB為0。中斷分組中我們將一位作為可重入的優(yōu)先組,另3位作為優(yōu)先級組。由于一個(gè)為0一個(gè)為1,故這兩個(gè)中斷都不會相互被另一個(gè)中斷打斷。
現(xiàn)在既然允許了兩個(gè)中斷,估計(jì)在中斷中將做很多事情,大多數(shù)事情都在中斷中完成的。這個(gè)中斷程序等一會馬上就來解讀。最后是USB_Init()這個(gè)函數(shù)了。在這是里先看到:
pInformation=&Device_Info;這個(gè)是設(shè)備資料部分,里面的全部變量,靜態(tài)的。pInformation-》ControlState=2;
pInformation是一個(gè)指向Device_Info的指針。不知為什么要這樣大費(fèi)周折。不可以直接這樣寫嗎:
Device_Info.ControlState=2
接下來:
pProperty=&Device_Property;
pUser_Standard_Requests=&User_Standard_Requests;pProperty是一個(gè)指針,指向DEVICE_PROP這個(gè)是設(shè)備屬性部分
設(shè)備屬性部分包含一些方法,即函數(shù)。也包括兩個(gè)參數(shù),一個(gè)是接收區(qū)的緩沖區(qū)地址,一個(gè)是最大的包的長度。都是用字節(jié)表示的。
這個(gè)屬性是一個(gè)通用的屬性,它指以相當(dāng)于實(shí)例化套到USB這個(gè)頭上去。故我們在這里看上去運(yùn)行一個(gè)pProperty-》Init();實(shí)際上運(yùn)行的是DEVICE_PROP中的Virtual_Com_Port_init()這個(gè)函數(shù)。我們看在這個(gè)函數(shù)中做了什么:
Get_SerialNum();設(shè)置芯片序列號,將描述符中的例如STM等字符串修改沒太大意義。
PowerOn(void)先使能芯片(三極管B極變高)強(qiáng)迫USB復(fù)位。再將全部USB中斷都屏蔽后,將中斷清除,最后再允許以下中斷:CNTR_RESETM|CNTR_SUSPM|CNTR_WKUPM;
接下來,再一次清除中斷標(biāo)志,然后使能中斷(CNTR_CTRM|CNTR_SOFM|CNTR_RESETM)這幾個(gè)中斷就是復(fù)位中斷,正確傳輸中斷,SOF中斷
配置串口至缺省狀態(tài)---在這里波特率被設(shè)為9600,并且允許了接收中斷。發(fā)送中斷沒有允許。
將當(dāng)前的狀態(tài)定義為未連接狀態(tài)。bDeviceState=UNCONNECTED;什么時(shí)候連接不知道。
至此,初始化結(jié)束。我們現(xiàn)在要看的是中斷函數(shù)了。中斷函數(shù)不外于一個(gè)是串口的接收中斷。串口的發(fā)送中斷是沒有允許的。
串口是如何發(fā)送的呢?它直接寫串口寄存器,顯然如果有大量數(shù)據(jù)發(fā)送時(shí)就會出問題的。因?yàn)樗静慌袛嗍欠癜l(fā)送緩沖區(qū)為空。因此,感覺這個(gè)程序要進(jìn)行大量的數(shù)據(jù)交互不可能,最多是敲打一下鍵盤可能還差不多。
看它的庫中的函數(shù):直接發(fā)送,也不管是否空。難道它有16字節(jié)緩沖嗎?沒有。voidUSART_SendData(USART_TypeDef*USARTx,u16Data){
/*TransmitData*/
USARTx-》DR=(Data&(u16)0x01FF);}
先從簡單的看起,串口的接收中斷,它在哪里呢?發(fā)現(xiàn)它在stm32f10x_it.c中有如下:
USART_To_USB_Send_Data();表示從串口向USB端發(fā)送數(shù)據(jù)。
再看這個(gè)定義如下:
voidUSART_To_USB_Send_Data(void){
if(USART_InitStructure.USART_WordLength==USART_WordLength_8b){
buffer_in[count_in]=USART_ReceiveData(USART1)&0x7F;}
elseif(USART_InitStructure.USART_WordLength==USART_WordLength_9b){
buffer_in[count_in]=USART_ReceiveData(USART1);}
count_in++;
UserToPMABufferCopy(buffer_in,ENDP1_TXADDR,count_in);SetEPTxCount(ENDP1,count_in);SetEPTxValid(ENDP1);}
輸入的數(shù)據(jù)長度++即count_in++
將收到的數(shù)據(jù)拷貝到端口1的發(fā)送緩沖區(qū)中。設(shè)置發(fā)送緩沖區(qū)的長度
發(fā)送數(shù)據(jù),它是從ENDP1發(fā)送。
我相信,發(fā)送完后,這個(gè)count_in會被清零。
果然,在EP1_IN_Callback()函數(shù)中,它被清零。
最后,我們就來看一下USB的中斷。USB的中斷入口有一個(gè)還是多個(gè)?它有一個(gè)高優(yōu)先級中斷和一個(gè)低優(yōu)先級中斷。應(yīng)該只用其中一個(gè)。
看程序中有下列:
voidUSB_LP_CAN_RX0_IRQHandler(void){
USB_Istr();}
這個(gè)說明,在程序中將USB設(shè)為相對低的優(yōu)先級中斷。回想起我們好象在什么地方這樣設(shè)過?果然,在USB_Interrupts_Config()中,有這么一段:
NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN_RX0_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);
所以所有的中斷都是進(jìn)到這個(gè)中斷中去了。趕緊看一看,這個(gè)是怎么處理的?它被發(fā)現(xiàn)在usb_istr.c中。我想所有的最麻煩的部分就是比較精彩的部分應(yīng)該就在這里了(對初學(xué)者)下面我們就來分析這個(gè)部分,分析完之后就可以回去了,做完今天的工作。因?yàn)榫?,所以拷貝在下面了?/p>
voidUSB_Istr(void){
wIstr=_GetISTR();
#if(IMR_MSK&ISTR_RESET)
if(wIstr&ISTR_RESET&wInterrupt_Mask){
_SetISTR((u16)CLR_RESET);Device_Property.Reset();#ifdefRESET_CALLBACK
RESET_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if(IMR_MSK&ISTR_DOVR)
if(wIstr&ISTR_DOVR&wInterrupt_Mask){
_SetISTR((u16)CLR_DOVR);#ifdefDOVR_CALLBACK
DOVR_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if(IMR_MSK&ISTR_ERR)
if(wIstr&ISTR_ERR&wInterrupt_Mask){
SetISTR((u16)CLR_ERR);#ifdefERR_CALLBACK
ERR_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/#if(IMR_MSK&ISTR_WKUP)
if(wIstr&ISTR_WKUP&wInterrupt_Mask){
_SetISTR((u16)CLR_WKUP);Resume(RESUME_EXTERNAL);#ifdefWKUP_CALLBACK
WKUP_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/#if(IMR_MSK&ISTR_SUSP)
if(wIstr&ISTR_SUSP&wInterrupt_Mask){
/*checkifSUSPENDispossible*/if(fSuspendEnabled){
Suspend();}else{
/*ifnotpossiblethenresumeafterxxms*/Resume(RESUME_LATER);}
/*clearoftheISTRbitmustbedoneaftersettingofCNTR_FSUSP*/_SetISTR((u16)CLR_SUSP);#ifdefSUSP_CALLBACK
SUSP_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/#if(IMR_MSK&ISTR_SOF)
if(wIstr&ISTR_SOF&wInterrupt_Mask){
_SetISTR((u16)CLR_SOF);
bIntPackSOF++;
#ifdefSOF_CALLBACK
SOF_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/#if(IMR_MSK&ISTR_ESOF)
if(wIstr&ISTR_ESOF&wInterrupt_Mask){
_SetISTR((u16)CLR_ESOF);
/*resumehandlingtimingismadewithESOFs*/
Resume(RESUME_ESOF);/*requestwithoutchangeofthemachinestate*/#ifdefESOF_CALLBACK
ESOF_Callback();#endif}#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/#if(IMR_MSK&ISTR_CTR)
if(wIstr&ISTR_CTR&wInterrupt_Mask){
/*servicingoftheendpointcorrecttransferinterrupt*//*clearoftheCTRflagintothesub*/CTR_LP();
#ifdefCTR_CALLBACK
CTR_Callback();#endif}#endif
}/*USB_Istr*/
評論
查看更多