单片机学习小组
登录
直播中
吴藩
10年用户
912经验值
擅长:可编程逻辑
私信
关注
怎样在STM32F407上移植rosserial并与ROS进行通信呢
开启该帖子的消息推送
ROS
STM32F407
怎样去建立一种基于
STM32
CubeMX的STM32F407USB虚拟串口基本工程呢?有哪些步骤?
回帖
(1)
安瑞娟
2022-2-24 14:21:54
一、基于STM32CubeMX建立STM32F407USB虚拟串口基本工程
配置STM32F407单片机的时钟源,时钟源选择为晶振
配置调试方式和时基,此处选择的为SW模式。时基选择为系统滴答定时器。
3. 配置USB为全速模式下的仅设备模式
这里使用ST官方提供的USB设备库,并使用CDC类
配置系统时钟,这里晶振频率为8M并将系统时钟配置为最高的168M,并注意USB的时钟为48M
这里要特别注意一点,下面红框中标示的,堆空间一定要改大,否则会在设备管理器中显示黄色的感叹号。
这些都配置完之后便可以点击右上角的生成代码按钮,来生成基本工程代码。
二、根据基本工程修改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上面的教程开始测试学习了。
一、基于STM32CubeMX建立STM32F407USB虚拟串口基本工程
配置STM32F407单片机的时钟源,时钟源选择为晶振
配置调试方式和时基,此处选择的为SW模式。时基选择为系统滴答定时器。
3. 配置USB为全速模式下的仅设备模式
这里使用ST官方提供的USB设备库,并使用CDC类
配置系统时钟,这里晶振频率为8M并将系统时钟配置为最高的168M,并注意USB的时钟为48M
这里要特别注意一点,下面红框中标示的,堆空间一定要改大,否则会在设备管理器中显示黄色的感叹号。
这些都配置完之后便可以点击右上角的生成代码按钮,来生成基本工程代码。
二、根据基本工程修改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上面的教程开始测试学习了。
举报
更多回帖
rotate(-90deg);
回复
相关问答
ROS
STM32F407
rosserial
、
ros
_lib如何
移植
到
STM32
2021-10-13
1073
怎样
去
移植
stm32f407
的uClinux内核
呢
2021-10-26
2729
怎样
在
stm32F407
上去
移植
cnc四轴联动的代码
2021-09-26
1787
怎样
去
移植
基于
STM32F407
的FATFS文件系统
呢
2021-10-18
2606
UCOS III是
怎样
移植
到
STM32F407
上去的
2021-10-20
1979
怎样
使用
STM32F407
的USART2 HC06蓝牙模块
进行
通信
呢
2021-10-26
2934
怎样
将LD3320语音芯片的程序
移植
到
STM32F407
上
2021-10-20
1951
怎样
在
STM32F407
上
做FFT的运算
2021-10-19
2324
STM32F
103到
STM32F407
的程序是如何
进行
移植
的
2021-10-20
3964
从
STM32F
103到
STM32F407
的程序是如何
进行
移植
的
2021-10-20
3650
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分