下面再来看第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*/
评论