GD32的虚拟串口CDC的一些注意事项

在移植GD32CDC的USB虚拟串口,即CDC设备时,需要注意一下几点。
我这里已GD32E503为例。
1、时钟要正确,GD32E503的时钟必须为168M才能用
2、硬件问题,GD32E503的USB必须要三个脚,除了DP DM外,还有DP一个上拉脚要配置。
3、不要忘了移植中断部分代码,USB是有中断函数的。
4、关于CDC的发送和接收问题:用官方的例程,发送和接收是没问题的。但是在我们代码里是不能直接用的,如果仔细移植代码还有可能会遇到64字节限制的问题。从官方例程来看,发送多少字节都没问题,我试过400字节一次的发送和接收都没问题。但是从官方例程移植到自己想要的函数里面就有可能遇到64字节限制,注意点有以下:
一、在发送函数直接使用即可:
uint16_t user_usb_send(uint8_t *buf, uint16_t length)
{
if(USBD_CONFIGURED != usbd_cdc.cur_status) return 0;
if(length == 0) return 0;
usb_cdc_handler *cdc = (usb_cdc_handler *)usbd_cdc.class_data[CDC_COM_INTERFACE];
while(cdc->packet_sent == 0);
cdc->packet_sent = 0U;
usbd_ep_send(&usbd_cdc, CDC_IN_EP, buf, length);
return length;
}
在调试中发现有的时候上面的发送不成功,USB卡死的情况,查了半天,原来是标志位cdc->packet_sent被keil编译器优化了,给这个变量加上volatile解决。
二、接收函数特别要小心,有些代码的前后顺序位置放错,就会出问题:
顺序如下:
1、判断接收状态:
if (0U == cdc_acm_check_ready(&usbd_cdc))
2、接收数据:
cdc_acm_data_receive(&usbd_cdc);
3、读取数据长度:
usb_cdc_handler *cdc = (usb_cdc_handler *)usbd_cdc.class_data[CDC_COM_INTERFACE];
uint32_t data_len = cdc->receive_length;
4、马上置零数据长度(这句代码可以不需要):
cdc->receive_length = 0;
5、拷贝数据出来即可。
memcpy(mybuff, cdc->data, data_len);
上面的顺序,特别是2、3、4的顺序不能搞乱,3放到2前面会出问题,把5放到3和4之间也会出问题。
上面的代码建议和读取缓存数据功能代码放在一起,这样每次我们读取缓存数据时,就会调用到上面的代码,把USB的数据更新到自己的缓存中,然后再从自己的缓存读取我们想要的数据。

你可能感兴趣的:(单片机,mcu)