基于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<<INDEX_EP1)|(1<<INDEX_EP3);
	gUSBC_ComReg->INTRRXE_L = (1<<INDEX_EP2);

	//ensure ep0 control/status regesters appeare in the memory map.
	gUSBC_ComReg->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的波特率,数据位,停止位等信息,否则会导致数据乱码。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
通过MCU实现串口调试助手发送数据的回显可以通过以下步骤实现: 1. 配置串口参数:首先,需要在MCU上配置串口的波特率、数据位、停止位和校验位等参数,以确保与串口调试助手的通信正常。 2. 接收数据:MCU需要设置串口接收中断,以便在接收到串口调试助手发送的数据时进行处理。可以使用MCU提供的串口接收函数来接收数据,将接收到的数据存储在缓冲区中。 3. 处理数据:接收到数据后,MCU可以对数据进行处理,例如解析命令、执行相应的操作等。在这个步骤中,可以根据需要对接收到的数据进行解析,并根据解析结果执行相应的操作。 4. 发送回显数据:在处理完接收到的数据后,MCU可以将处理结果或回显数据发送回串口调试助手。可以使用MCU提供的串口发送函数将数据发送到串口调试助手。 下面是一个示例代码,演示了如何通过MCU实现串口调试助手发送数据的回显: ```c #include <stdio.h> #include <string.h> // 定义串口接收缓冲区大小 #define BUFFER_SIZE 100 // 定义串口接收缓冲区 char rxBuffer[BUFFER_SIZE]; // 定义串口发送函数 void sendSerialData(const char* data) { // 将数据发送到串口调试助手 printf("%s", data); } // 定义串口接收中断处理函数 void serialInterruptHandler() { // 接收到数据后的处理逻辑 // 例如,将接收到的数据存储在缓冲区中 // 并发送回显数据到串口调试助手 if (strlen(rxBuffer) > 0) { sendSerialData(rxBuffer); memset(rxBuffer, 0, sizeof(rxBuffer)); } } int main() { // 初始化串口配置 // ... // 设置串口接收中断 // ... while (1) { // 主循环 // ... } return 0; } ``` 在上述示例代码中,我们定义了一个串口接收缓冲区rxBuffer,并在串口接收中断处理函数serialInterruptHandler中将接收到的数据存储在缓冲区中。然后,在主循环中,我们通过sendSerialData函数将缓冲区中的数据发送回串口调试助手。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

darin_wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值