STM32 USB学习整理3

STM32 USB学习整理3

usbd_cdc_vcp.c

这个文件主要和 VCP 驱动有直接关系!很多部分都是空的内容,其中包含了一些参数的设置,需要注意的是 波特率的大小与USB速度没有关系,波特率的设置会影响串口速度;

//USB虚拟串口相关配置参数
LINE_CODING linecoding =
{
	115200,		//波特率  USBSlavede 速度与波特率没有关系,爱咋咋地
	0x00,   	//停止位,默认1位
	0x00,   	//校验位,默认无
	0x08    	//数据位,默认8位
}; 

u8  USART_PRINTF_Buffer[USB_USART_REC_LEN];	//usb_printf发送缓冲区(200字节)

//用类似串口1接收数据的方法,来处理USB虚拟串口接收到的数据.
u8 USB_USART_RX_BUF[USB_USART_REC_LEN]; 	//接收缓冲,最大USART_REC_LEN(200)个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USB_USART_RX_STA=0;       				//接收状态标记	 

 
extern uint8_t  APP_Rx_Buffer [];			//虚拟串口发送缓冲区(发给电脑) 
extern uint32_t APP_Rx_ptr_in;   			

//虚拟串口配置函数(供USB内核调用)
CDC_IF_Prop_TypeDef VCP_fops = 
{
	VCP_Init,
	VCP_DeInit,
	VCP_Ctrl,
	VCP_DataTx,
	VCP_DataRx
}; 

//初始化VCP
//返回值:USBD_OK
uint16_t VCP_Init(void)
{ 
	return USBD_OK;
} 
//复位VCP
//返回值:USBD_OK
uint16_t VCP_DeInit(void)
{ 
	return USBD_OK;
} 
//控制VCP的设置
//buf:命令数据缓冲区/参数保存缓冲区
//len:数据长度
//返回值:USBD_OK
uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
{ 
	switch (Cmd)
	{
		case SEND_ENCAPSULATED_COMMAND:
			break;   
		case GET_ENCAPSULATED_RESPONSE:
			break;  
		case SET_COMM_FEATURE:
			break;  
		case GET_COMM_FEATURE:
			break;  
 		case CLEAR_COMM_FEATURE:
			break;  
		case SET_LINE_CODING:/*当我们在PC端上的串口工具中修改串口通信的属性时就会触发CDC_SET_LINE_CODING请求*/
			linecoding.bitrate = (uint32_t)(Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24));
			linecoding.format = Buf[4];
			linecoding.paritytype = Buf[5];
			linecoding.datatype = Buf[6]; 
			//打印配置参数
			printf("linecoding.format:%d\r\n",linecoding.format);
			printf("linecoding.paritytype:%d\r\n",linecoding.paritytype);
			printf("linecoding.datatype:%d\r\n",linecoding.datatype);
			printf("linecoding.bitrate:%d\r\n",linecoding.bitrate);
			break; 
		case GET_LINE_CODING:
			Buf[0] = (uint8_t)(linecoding.bitrate);
			Buf[1] = (uint8_t)(linecoding.bitrate >> 8);
			Buf[2] = (uint8_t)(linecoding.bitrate >> 16);
			Buf[3] = (uint8_t)(linecoding.bitrate >> 24);
			Buf[4] = linecoding.format;
			Buf[5] = linecoding.paritytype;
			Buf[6] = linecoding.datatype; 
			break; 
		case SET_CONTROL_LINE_STATE:
			break;   
		case SEND_BREAK:
			break;   
		default:
			break;  
	} 
	return USBD_OK;
}

VCP_DataTx ();发送一个字节给虚拟串口(发给电脑),实际上是把一个8位数据发送到 u8的缓存区里面了,这个缓存区默认大小2048,从0开始写,写到2048个数之后,下一次重新写入到第1个位置,如此往复。

//返回值:USBD_OK
uint16_t VCP_DataTx (uint8_t data)
{  
	APP_Rx_Buffer[APP_Rx_ptr_in]=data;	//写入发送buf
	APP_Rx_ptr_in++;  					//写位置加1
	if(APP_Rx_ptr_in==APP_RX_DATA_SIZE)	//超过buf大小了,归零.
	{
		APP_Rx_ptr_in = 0;
	}   
	return USBD_OK;
} 

VCP_DataRx ();处理从USB虚拟串口接收到的数据(电脑发来的数据),与串口一的接收程序差不多。

//返回值:USBD_OK
uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
{
	u8 i;
	u8 res;
	for(i=0;i<Len;i++)
	{  
		res=Buf[i]; 
		if((USB_USART_RX_STA&0x8000)==0)		//接收未完成
		{
			if(USB_USART_RX_STA&0x4000)			//接收到了0x0d
			{
				if(res!=0x0a)
					USB_USART_RX_STA=0;//接收错误,重新开始
				else 
					USB_USART_RX_STA|=0x8000;	//接收完成了 
			}else //还没收到0X0D
			{	
				if(res==0x0d)
					USB_USART_RX_STA|=0x4000;
				else
				{
					USB_USART_RX_BUF[USB_USART_RX_STA&0X3FFF]=res;
					USB_USART_RX_STA++;
					if(USB_USART_RX_STA>(USB_USART_REC_LEN-1))
						USB_USART_RX_STA=0;//接收数据错误,重新开始接收	
				}					
			}
		}   
	}  
	return USBD_OK;
}

usb_printf();这个函数是最通用的发送函数,作用相当于 printf();但是实际上还是内部调用VCP_DataTx()。

//usb虚拟串口,printf 函数
//确保一次发送数据不超USB_USART_REC_LEN字节
void usb_printf(char* fmt,...)  
{  
	u16 i,j;
	va_list ap;
	va_start(ap,fmt);
	vsprintf((char*)USART_PRINTF_Buffer,fmt,ap);
	va_end(ap);
	i=strlen((const char*)USART_PRINTF_Buffer);//此次发送数据的长度
	for(j=0;j<i;j++)//循环发送数据
	{
		VCP_DataTx(USART_PRINTF_Buffer[j]); //200
	}
} 

usb_bsp.c

USB_OTG_BSP_Init();函数是底层IO口的初始化函数,STM32F429使用的是MicroUSB,此USB有5根线,VCC,D-,D+,NC,GND,PA11和PA12硬件上连接到D+.D-上。本例程的两个延时函数采用SYSTEM文件夹的delay.c里面的delay_us函数实现
,官方例程采用的是定时器2来实现的。此外,这里面还有中断优先级设置和中断使能。

//USB OTG 底层IO初始化
//pdev:USB OTG内核结构体指针
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
{
     GPIO_InitTypeDef  GPIO_InitStruct;
    __HAL_RCC_GPIOA_CLK_ENABLE();                   //使能GPIOA时钟
    __HAL_RCC_USB_OTG_FS_CLK_ENABLE();              //使能OTG FS时钟

    //配置PA11 12  PA11 PA12 硬件上连接D+  D-
    GPIO_InitStruct.Pin=GPIO_PIN_11|GPIO_PIN_12;    //PA11 12
    GPIO_InitStruct.Mode=GPIO_MODE_AF_PP;           //复用
    GPIO_InitStruct.Pull=GPIO_NOPULL;               //无上下拉
    GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;          //高速
    GPIO_InitStruct.Alternate=GPIO_AF10_OTG_FS;     //复用为OTG FS
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);         //初始化
    PCF8574_WriteBit(USB_PWR_IO,1);                 //开启USB HOST电源供电  我觉得就是主机供电
}

//USB OTG 中断设置,开启USB FS中断
//pdev:USB OTG内核结构体指针
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
{  	
    HAL_NVIC_SetPriority(OTG_FS_IRQn,0,3);          //抢占优先级0,子优先级3
    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);                //使能OTG USB FS中断 
}

//USB OTG 中断设置,开启USB FS中断0(本例程未用到)
//pdev:USB OTG内核结构体指针
void USB_OTG_BSP_DisableInterrupt(void)
{ 
	
}
//USB OTG 端口供电设置(本例程未用到)
//pdev:USB OTG内核结构体指针
//state:0,断电;1,上电
void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state)
{ 
}
//USB_OTG 端口供电IO配置(本例程未用到)
//pdev:USB OTG内核结构体指针
void  USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev)
{ 
} 
//USB_OTG us级延时函数
//usec:要延时的us数.
void USB_OTG_BSP_uDelay (const uint32_t usec)
{ 
   	delay_us(usec);
}
//USB_OTG ms级延时函数

//msec:要延时的ms数.
void USB_OTG_BSP_mDelay (const uint32_t msec)
{  
	delay_ms(msec);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值