下面再來看第2個函數Set_USBClock()-------兩句話:
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);/*EnableUSBclock*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB,ENABLE);72M除1。5=48然后允許USB的時鐘。這個要看一下數據手冊。從數據手冊比較好理解。它是直接從PCLK中除一個數,可以除1也可以除1.5.。這段還是比較好理解的。
再看第3個函數USB_Interrupts_Config()-------配置USB中斷
在該函數中使能了兩個中斷,一個是USB,一個是串口。至于中斷放在RAM或FLASH當然一般是后者,所以在這也就沒有什么意義了。串口優先級為1,USB為0。中斷分組中我們將一位作為可重入的優先組,另3位作為優先級組。由于一個為0一個為1,故這兩個中斷都不會相互被另一個中斷打斷。
現在既然允許了兩個中斷,估計在中斷中將做很多事情,大多數事情都在中斷中完成的。這個中斷程序等一會馬上就來解讀。最后是USB_Init()這個函數了。在這是里先看到:
pInformation=&Device_Info;這個是設備資料部分,里面的全部變量,靜態的。pInformation-》ControlState=2;
pInformation是一個指向Device_Info的指針。不知為什么要這樣大費周折。不可以直接這樣寫嗎:
Device_Info.ControlState=2
接下來:
pProperty=&Device_Property;
pUser_Standard_Requests=&User_Standard_Requests;pProperty是一個指針,指向DEVICE_PROP這個是設備屬性部分
設備屬性部分包含一些方法,即函數。也包括兩個參數,一個是接收區的緩沖區地址,一個是最大的包的長度。都是用字節表示的。
這個屬性是一個通用的屬性,它指以相當于實例化套到USB這個頭上去。故我們在這里看上去運行一個pProperty-》Init();實際上運行的是DEVICE_PROP中的Virtual_Com_Port_init()這個函數。我們看在這個函數中做了什么:
Get_SerialNum();設置芯片序列號,將描述符中的例如STM等字符串修改沒太大意義。
PowerOn(void)先使能芯片(三極管B極變高)強迫USB復位。再將全部USB中斷都屏蔽后,將中斷清除,最后再允許以下中斷:CNTR_RESETM|CNTR_SUSPM|CNTR_WKUPM;
接下來,再一次清除中斷標志,然后使能中斷(CNTR_CTRM|CNTR_SOFM|CNTR_RESETM)這幾個中斷就是復位中斷,正確傳輸中斷,SOF中斷
配置串口至缺省狀態---在這里波特率被設為9600,并且允許了接收中斷。發送中斷沒有允許。
將當前的狀態定義為未連接狀態。bDeviceState=UNCONNECTED;什么時候連接不知道。
至此,初始化結束。我們現在要看的是中斷函數了。中斷函數不外于一個是串口的接收中斷。串口的發送中斷是沒有允許的。
串口是如何發送的呢?它直接寫串口寄存器,顯然如果有大量數據發送時就會出問題的。因為它根本不判斷是否發送緩沖區為空。因此,感覺這個程序要進行大量的數據交互不可能,最多是敲打一下鍵盤可能還差不多。
看它的庫中的函數:直接發送,也不管是否空。難道它有16字節緩沖嗎?沒有。voidUSART_SendData(USART_TypeDef*USARTx,u16Data){
/*TransmitData*/
USARTx-》DR=(Data&(u16)0x01FF);}
先從簡單的看起,串口的接收中斷,它在哪里呢?發現它在stm32f10x_it.c中有如下:
USART_To_USB_Send_Data();表示從串口向USB端發送數據。
再看這個定義如下:
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);}
輸入的數據長度++即count_in++
將收到的數據拷貝到端口1的發送緩沖區中。設置發送緩沖區的長度
發送數據,它是從ENDP1發送。
我相信,發送完后,這個count_in會被清零。
果然,在EP1_IN_Callback()函數中,它被清零。
最后,我們就來看一下USB的中斷。USB的中斷入口有一個還是多個?它有一個高優先級中斷和一個低優先級中斷。應該只用其中一個。
看程序中有下列:
voidUSB_LP_CAN_RX0_IRQHandler(void){
USB_Istr();}
這個說明,在程序中將USB設為相對低的優先級中斷。回想起我們好象在什么地方這樣設過?果然,在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);
所以所有的中斷都是進到這個中斷中去了。趕緊看一看,這個是怎么處理的?它被發現在usb_istr.c中。我想所有的最麻煩的部分就是比較精彩的部分應該就在這里了(對初學者)下面我們就來分析這個部分,分析完之后就可以回去了,做完今天的工作。因為精彩,所以拷貝在下面了:
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*/
評論
查看更多