完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
一、基于STM32CubeMX建立STM32F407USB虚拟串口基本工程
二、根据基本工程修改USB部分的代码,提供rosserial会用到的串口收发接口。 这里主要修改u***d_cdc_if.c文件,首先我们要明确其中两个函数的功能。 static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 7 */ USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hU***DeviceFS.pClassData; if (hcdc->TxState != 0){ return USBD_BUSY; } USBD_CDC_SetTxBuffer(&hU***DeviceFS, Buf, Len); result = USBD_CDC_TransmitPacket(&hU***DeviceFS); /* USER CODE END 7 */ return result; } 单从这两个函数的名字上看也比较好理解,上面的时数据接收函数,下面的时数据发送函数。CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)是数据接收的回调函数,USB每次收到数据后都会调用该函数将接收到的数据存入Buf指向的缓冲区当中,Len是接收到数据的长度。USBD_CDC_ReceivePacket()函数的作用是复位OUT端点接收缓冲区,CDC_Itf_Receive()函数在接收完数据之后要调用该函数复位缓冲区。因此如果接收到的数据没有及时处理,就会被下次接收到的数据覆盖掉了。所以在此处要增加数据转存环节。 #define USB_RX_DATA_SIZE 2048 uint8_t u***_rxBuffer[USB_RX_DATA_SIZE]; uint32_t u***_rxBufPtrIn = 0; uint32_t u***_rxBufPtrOut = 0; static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ uint32_t i; uint16_t in; for(i = 0; i < *Len; ++i) { in = (u***_rxBufPtrIn + 1) % USB_RX_DATA_SIZE; if(in != u***_rxBufPtrOut) //USB接收缓冲区未满 { u***_rxBuffer[u***_rxBufPtrIn] = Buf; u***_rxBufPtrIn = in; } } USBD_CDC_SetRxBuffer(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } 这样处理最终实现的效果是将接收到的数据存入了一环形缓冲区。再将数据存好之后便可以为rosserial提供接口函数了 //接收缓冲区中的数据大小 int vcp_available(void) { return ((uint32_t)(USB_RX_DATA_SIZE + u***_rxBufPtrIn - u***_rxBufPtrOut)) % USB_RX_DATA_SIZE; } //从接收缓冲区中读取 int vcp_read(void) { // if the head isn't ahead of the tail, we don't have any characters if(u***_rxBufPtrIn == u***_rxBufPtrOut) { return -1; } else { unsigned char ch = u***_rxBuffer[u***_rxBufPtrOut]; u***_rxBufPtrOut = (uint16_t)(u***_rxBufPtrOut + 1) % USB_RX_DATA_SIZE; return ch; } } //通过u***_vcp向外发送 void vcp_write(uint8_t* Buf, uint16_t Len) { while(CDC_Transmit_FS(Buf, Len) != HAL_OK); } 三、将ros_lib增加到工程中,并修改STM32Hardware.h文件 ros_lib 可以根据rosserial wiki 的教程中执行产生。 ros_lib增加到工程中之后会报找不到round函数的错误,和一系列警告消息。 针对找不到round()函数的错误可以在增加__USE_C99_MATH的宏,针对大量警告的问题可以在Misc Controls 的位置增加如:–diag_suppress=num,(num,为警告信息#号后面的数字)。 接下来的重点便是修改STM32Hardware.h文件了。 这里试了一下不能直接粘贴太多代码,就介绍一下如何修改好了。 在开头的地方增加: extern __IO uint32_t uwTick; 将类内部的读写函数修改为: int read(){ if(vcp_available()){ return vcp_read(); }else{ return -1; } void write(uint8_t* data, int length){ vcp_write(data, length); } 将时间函数改为 unsigned long time(){return uwTick;} 到此整个移植工作便结束了,接下来可以按照rosserial wiki上面的教程开始测试学习了。 |
|
|
|
|
只有小组成员才能发言,加入小组>>
1599 浏览 0 评论
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
4738 浏览 0 评论
4229 浏览 9 评论
3822 浏览 16 评论
4398 浏览 1 评论
4212浏览 3评论
2381浏览 0评论
3394浏览 0评论
1159浏览 0评论
2844浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 08:50 , Processed in 2.589398 second(s), Total 76, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1068