一、前言

记录在使用stm32的usb虚拟串口通讯时,无法接收0x0d字节,并且后续数据断包问题。

二、环境

stm32/GD32系列,使用标准USB_CORE和USB_CONFIG库文件

三、正文

usb库

使用虚拟串口时,main函数初始化部分如下所示

 
int main(void)
{	 
	u32 len;	
	u8 usbstatus=0;	
 
	//初始化系统
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 
 
 
	delay_ms(500);
	USB_Port_Set(0); 	//USB先断开
	delay_ms(200);
	USB_Port_Set(1);	//USB再次连接
	Set_USBClock();   
	USB_Interrupts_Config();    
	USB_Init();	
	while(1)
	{
			/**************************USB虚拟串口部分*************************/
			//检测usb热插拔状态
			if(usbstatus!=bDeviceState){//USB连接状态发生了改变.
					usbstatus=bDeviceState;//记录新的状态
					//if(usbstatus==CONFIGURED)printf("USB连接成功\r\n");//提示USB连接成功
					//else printf("USB连接断开\r\n");//提示USB断开
			}
			//终端接收usb虚拟串口数据
			if(USB_USART_RX_STA&0x8000){	
					len=USB_USART_RX_STA&0x3FFF;//得到此次接收到的数据长度
					USB_USART_RX_STA=0;
				  if(USB_USART_RX_BUF[0]==0x5A&&USB_USART_RX_BUF[1]==0xA5){//头
 
						
					}
					
					memset(USB_USART_RX_BUF,0,sizeof(USB_USART_RX_BUF));//缓存清零			
			}
			if(usbstatus==CONFIGURED){//判断USB已经连接
	
			}
			else{//USB未连接
			
			}
			/**************************USB虚拟串口部分end*************************/
		
	}
}

当定义的协议中有0x0d字节时,接收USB_USART_RX_BUF就会不全,这是我们跳转到原函数写法那里查看代码

//void USB_To_USART_Send_Data(u8* data_buffer, u8 Nb_bytes)
//{ 
//	u8 i;
//	u8 res;
//	for(i=0;i<Nb_bytes;i++)
//	{  
//		res=data_buffer[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;//接收数据错误,重新开始接收	
//				}					
//			}
//		}   
//	}  
//} 

 这是原函数写法,我全部注释了,没有打开,其中就是判断0x0d在判断0x0a去获取数据发送完毕,这里缺点就很明显了,也不是我们想要的方式,因为数据中万一出现0x0d,就会接收处理异常,还有就是发送还必须得加上0x0d和0x0a,比较麻烦

将接收函数改成如下方式:

void USB_To_USART_Send_Data(u8* data_buffer, u8 Nb_bytes)
{ 
		u8 i;
		u8 res;
		for(i=0;i<Nb_bytes;i++)
		{  
				res=data_buffer[i]; 
				if((USB_USART_RX_STA&0x8000)==0)		//接收未完成
				{
					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;//接收数据错误,重新开始接收	
 
				} 
		}  
		USB_USART_RX_STA|=0x8000;	//接收完成了 
} 

这样发送数据完毕之后同样会进入主循环的判断条件中,并且在发送数据时不用必须发送0x0d和0x0a字节。

四、结语

本文到此结束,快去试试吧,祝君成功!