【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
对于mcu usb而言,大部分情况下,它和上位机之间的关系都是device的关系。一般usb,可以分成host和device。如果mcu是host,那么意味着它可以主动访问别的usb设备,比如u盘、相机之类的设备。如果是device呢,这种情况下,mcu就是被别人访问,也就是说mcu会把自己伪装成一个u盘、camera或者串口这样的设备。
另外不知道大家注意没有,很多的usb模块,里面本身没有usb转232的芯片,但是照样被识别成了com设备,道理就在这。因为mcu固件里面把会usb虚拟成com设备。
1、usb cdc虚拟串口和传统usb转串口的区别
差别之处其实比较好分辨,前者是通过固件代码的形式实现的;而后者,一般都是需要添加一个usb转232的芯片实现。
2、usb cdc虚拟串口的好处
把mcu的usb虚拟成一个串口,不仅速度比较快,没有波特率的限制,使用上面也比较简单,也没有额外的成本困扰。
3、cdc的目录结构
stm32目前大部分mcu都支持cdc结构,大家只需要把对应的代码copy过来,会使用即可,不用过度追究里面的原理。
4、main函数的启动流程
这部分代码其实和之前其他mcu的代码没有区别。在进行了usb设备的初始化,即调用MX_USB_DEVICE_Init函数之后,就是打印数据和接收数据。当然,mcu启动之后,需要一个type c的线连接到电脑上面。这个时候电脑的设备管理器就会生成一个新的com节点。我们借助于上位机串口打印工具,open这个com点之后,就可以看到对应的发送内容,以及接收的内容。
int main(void)
{SCB_EnableICache(); SCB_EnableDCache(); HAL_Init(); SystemClock_Config(); LED_Init(); MX_USB_DEVICE_Init(); USB_printf("STM32H750 virtual usb test\r\n"); while (1){USB_printf("1234567abcdefg\r\n");LED1_Toggle;HAL_Delay(1000);USB_getf();}
}
5、usb发送
这里面发送的函数就是USB_printf,我们可以简单看下这个函数是怎么实现的。实现的文件来自于usbd_cdc_if.c,
void USB_printf(const char *format, ...)
{va_list args; uint32_t length; uint16_t USB_TimeOut; uint32_t Tickstart; va_start(args, format); length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);va_end(args); USB_TimeOut = 3; if( hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED ) {USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; Tickstart = HAL_GetTick(); while(hcdc->TxState !=0) {if((HAL_GetTick() - Tickstart) > USB_TimeOut){break;}}} CDC_Transmit_FS(UserTxBufferFS, length);
}
6、usb接收
大家如果留心一下就会发现,刚才usb发送的时候,都是把数据copy到UserTxBufferFS里面的。其实接收数据也一样,整个接收区的内容,都是放在UserRxBufferFS缓存里面。这就意味着,我们检查UserRxBufferFS空间就可以拿到里面的内容,有数据可以打印出来,没有就算了。
void USB_getf(void)
{int num= strlen((const char*)UserRxBufferFS);if(num > 0){USB_printf("%s", UserRxBufferFS);memset(UserRxBufferFS, 0, num+1);}
}
7、测试和验证
和前面几次打印、测试不一样,这一次的打印是通过usb线虚拟的串口实现的。这样的话就不需要实际的usb转串口工具。一个st-link v2烧录器,一个type c的线,就可以和pc电脑之间实现数据通信了。最后,还是建议大家可以把重点放在如何使用cdc、如何使用usb虚拟串口上面。等到用起来,比较熟练了,再去看usb cdc和usb协议的实现细节,这样更加稳妥。