• 基于MCU_USB的虚拟串口助手实现


    一 、实验目的:

    通过MCU的USB模块加串口模块,实现一个串口助手的功能。具体操作为把USB接收到的数据通过串口发送,同时实现串口接收的数据回传到USB,从而实现从USB到TTL的电平转换。

    二、实验环境:

    1.mcu: 国芯ccm4202

    2.开发环境:Keil

    三、操作步骤:

    1.USB设置为CDC类

    USB CDC类的通信部分主要包含三部分:枚举过程、虚拟串口操作和数据通信。其中虚拟串口操作部分并不一定强制需要,因为若跳过这些虚拟串口的操作,实际上USB依然是可以通信的,这也就是为什么上图中,在操作虚拟串口之前会有两条数据通信的数据。之所以会有虚拟串口操作,主要是我们通常使用PC作为Host端,在PC端使用一个串口工具来与其进行通信,PC端的对应驱动将其虚拟成一个普通串口,这样一来,可以方便PC端软件通过操作串口的方式来与其进行通信,但实际上,Host端与Device端物理上是通过USB总线来进行通信的,与串口没有关系,这一虚拟化过程,起决定性作用的是对应驱动,包含如何将每一条具体的虚拟串口操作对应到实际上的USB操作。需要注意的是,Host端与Device端的USB通信速率并不受所谓的串口波特率影响,它就是标准的USB2.0全速(12Mbps)速度,实际速率取决于总线的实际使用率、驱动访问USB外设有效速率(两边)以及外部环境对通信本身造成的干扰率等因素组成。

    2.接口映射

    初始化MCU的UART,实现通过UART把USB的数据进行收发。

    四、软件实现:

    1.USB设置为CDC类

    void USB_CDC_Init(void)
    {
    	//USB1.1, 同时配置USB配置项为USB1.1模式
    	g_usbVer = 0;
    	//0:internal oscillator;  1:external oscillator
    	USBC_PHY_Init(0);
    
    	CCM->PHYPA |= 0x0e00;	//no need to supply VBUS.
    
    	/* Global USB Register */
    	//gUSBC_fifoReg = (USBCFIFO_Reg*)(USBC_BASE_ADDR+0x1A);
    	gUSBC_fifoReg = (USBCFIFO_Reg*)(USBC_BASE_ADDR+0x60);
    
    	gUSBC_ComReg = (USBCCommonReg*)USBC_BASE_ADDR;
    	gUSBC_IdxReg = (USBCIndexedReg*)(USBC_BASE_ADDR+0x10);
    	//USB data buffer
    	g_databuf = USB_BUFFER_ADDR;
    	//The suspend mode is disable before BULK-Only tranfer start
    	g_suspendMode = 0;
    	/* Setup USB register */
    	//enable usb common interrupt
    	//0		1		2		3		4		5		6		7 (bit)
    	//Susp	Resume	Reset	SOF		Conn	Discon	SessReq	VBusErr
    	gUSBC_ComReg->INTRUSBE = USB_INTERRUPT_RESET|USB_INTERRUPT_CONNECT|USB_INTERRUPT_DISCON|USB_INTERRUPT_SUSPEND|USB_INTERRUPT_RESUME;
    	//enable ep0 and ep1 tx interrupts,clear other tx interrupts
    
    	gUSBC_ComReg->INTRTXE_L = USB_INTERRUPT_EP0|(1<INTRRXE_L = (1<EINDEX = CONTROL_EP;
    
    	//Enable Soft connection
    	if(g_usbVer == 1)
    		gUSBC_ComReg->UCSR  = USB_POWER_SOFT_CONN|USB_POWER_HS_ENAB;
    	else
    		gUSBC_ComReg->UCSR  = USB_POWER_SOFT_CONN;
    
    	g_USBAddrFlag = 0;
    	g_USBNewAddr = 0;
    
    	NVIC_Init(3, 3, USBC_IRQn, 2);
    }

    2.初始化串口为中断方式

    void Usb_UART_init(void)
    {
    	UART_InitTypeDef UART_InitStruct;
    	UART_InitStruct.UART_BaudRate = LineCoding.bitrate;
    	UART_InitStruct.UART_Mode = UART_INT_MODE;
    	UART_InitStruct.UART_Parity = UART_PARITY_NONE;
    	if( LineCoding.format == 0)
    	{
    		UART_InitStruct.UART_FrameLength = UART_DATA_FRAME_LEN_10BIT;
    		UART_InitStruct.UART_StopBits = 1;
    	}
    	else
    	{
    		UART_InitStruct.UART_FrameLength = UART_DATA_FRAME_LEN_11BIT;
    		UART_InitStruct.UART_StopBits = 2;
    	}
    	UART_Init(Usb_Uart, &UART_InitStruct);
    }

    3.串口接收数据,通过USB发送到上位机。当数据间隔大于50毫秒默认为两包数据

    		ret = UART_RecvByte(Usb_Uart, &temp);
    		if(STATUS_OK == ret)
    		{
    			uart_data_buf_[i++] = temp;
    			len = i ;
    		}
    		else
    		{
    			if( Tool_Tc_cnt >= 50)
    			{
    				Tool_Tc_cnt = 0 ;
    				if(len!= 0 )
    				{
    					usb_cdc_send(INDEX_EP1, (UINT8*)uart_data_buf_, len);
    					i = 0 ;
    					len = 0 ;
    				}
    			}
    		}

    4.USB接收数据,并将数据通过UART发出

    void USBDev_DoCDCCmd_(void)
    {
    	UINT16 recvLen = 0;
    	UINT16 len;
    
    	len = 64;
    
    	memset(cdc_ctl_buf_, 0x00, sizeof(cdc_ctl_buf_));
    	recvLen = usb_cdc_receive(INDEX_EP2, (UINT8 *)cdc_ctl_buf_);
    	if (recvLen == 0)
    		return;
    	len = recvLen;
    	UART_SendData(Usb_Uart, cdc_ctl_buf_,len);
    }
    
    void usb_cdc_poll_(void)
    {
    	if( (g_uchUSBStatus & BIT1) == BIT1 )     //接收到一包数据
    	{
    		g_uchUSBStatus &= ~BIT1;
    		USBDev_DoCDCCmd_();
    	}
    }

    五、实验现象:

    如图所示,通过MCU模拟出来的串口助手可以实现USB_TTL芯片相同效果,进行数据收发。

    六、注意点

    1.串口需要采用中断方式,轮训会造成数据接收转发不完全

    2.usb虚拟串口部分,需要设置MCU的波特率,数据位,停止位等信息,否则会导致数据乱码。

  • 相关阅读:
    如何使用前端表格控件实现多数据源整合?
    第46节——redux中使用不可变数据+封装immer中间件——了解
    JPA Audit and Envers
    Java集合框架面试指南
    langchain pdf链检索,提问式表单(实体命名识别)
    SQL Server 临时对象缓存
    react使用内联css样式的注意点
    探索人工智能领域——每日30个名词详解【day3】
    windows下 解决PHP-CGI 进程崩溃502
    错误:Some packages could not be installed.
  • 原文地址:https://blog.csdn.net/darin_wang/article/details/127670138