2026-02-02 11:48 PM - last edited on 2026-02-12 11:43 PM by mƎALLEm
Hi, I use the stm32f103 to read the IMU(BNO055) via I2C to get the Quaternion data,
I use this library from ivyknob, https://github.com/ivyknob/bno055_stm32
The AR Anchors result is well (Head Mount Display application), I use the USB VCP to Transmit the BNO055 Quaternion data to PC or SBC, using the function CDC_Transmit_FS. But I face a problem immediately, the transmit speed is 100Hz, it will caused the USB_BUSY(race condition), I try some methods, such as add delay in the while loop, using timer interrupt and flag to limit the transmit speed, avoid using sprintf function, it could not solve this problem. As the picture shown below, Tx could write the data from STM32 to PC, but Rx could not write the data from PC to STM32
Files include the main.c and usbd_cdc_if.c
Could you give me some advices to resolve this problem.
Thank you
Best Regard Steve
2026-02-03 4:39 AM
Welcome to the forum.
Please give some more details about your setup - see:
How to write your question to maximize your chances to find a solution
2026-02-03 10:35 PM
2026-02-04 2:39 AM
It would be better to describe it here in a post
2026-02-04 10:03 PM - edited 2026-02-04 10:06 PM
Hi, I try to explain the problem on the website, could you pls give me any advices to solve this problem.
Thank you
BR Steve
//Include “bno055_stm32.h”
//In user code begin 2
bno055_assignI2C(&hi2c1);
bno055_setup();
bno055_setOperationModeNDOF();
//In user code begin 3
bno055_vector_t v = bno055_getVectorQuaternion();
int32_t iw = (int32_t)(v.w * 1000000);
int32_t ix = (int32_t)(v.x * 1000000);
int32_t iy = (int32_t)(v.y * 1000000);
int32_t iz = (int32_t)(v.z * 1000000);
printf("@%d,%d,%d,%d&",iw , ix, iy, iz);
HAL_Delay(10);//main.c
//Include “bno055_stm32.h”,”bno055_stm32.h”,”usbd_cdc_if.h”,”stdio.h”,”stdlib.h”,
//In user code begin PV
char msg[128];
//In user code begin 2
HAL_Delay(1000);//important, make sure usb configuration finish.
bno055_assignI2C(&hi2c1);
bno055_setup();
bno055_setOperationModeNDOF();
//In user code begin 3
bno055_vector_t v = bno055_getVectorQuaternion();
int32_t iw = (int32_t)(v.w * 1000000);
int32_t ix = (int32_t)(v.x * 1000000);
int32_t iy = (int32_t)(v.y * 1000000);
int32_t iz = (int32_t)(v.z * 1000000);
sprintf(msg,"@%d,%d,%d,%d&",iw,ix,iy,iz);
CDC_Transmit_FS((uint8_t*)msg, strlen(msg))
HAL_Delay(10);//usbd_cdc_if.c
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
Buf[*Len] = '\0';
if(strcmp((char*)Buf,"RESTARTBNO055")==0)
{
FLAG_BNO_RST = 1;
char dta[]="RESTARK IMU\r\n";
CDC_Transmit_FS((uint8_t*)dta,strlen(dta));
}
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
/* USER CODE END 6 */
}
//main.c while loop
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (FLAG_BNO_RST)
{
FLAG_BNO_RST = 0;
bno055_setup();
bno055_setOperationModeNDOF();
reset_timer =HAL_GetTick();
//HAL_Delay(3000);
}
bno055_vector_t v = bno055_getVectorQuaternion();
int32_t iw = (int32_t)(v.w * 1000000);
int32_t ix = (int32_t)(v.x * 1000000);
int32_t iy = (int32_t)(v.y * 1000000);
int32_t iz = (int32_t)(v.z * 1000000);
sprintf(msg,"@%d,%d,%d,%d&",iw,ix,iy,iz);
CDC_Transmit_FS((uint8_t*)msg, strlen(msg));
}
/* USER CODE END 3 */ /* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
bno055_vector_t v = bno055_getVectorQuaternion();
if(timer_10ms_flag==1)
{
timer_10ms_flag=0;
pkt.header = '@';
pkt.w = v.w;
pkt.x = v.x;
pkt.y = v.y;
pkt.z = v.z;
pkt.tail = '&';
CDC_Transmit_FS((uint8_t*)&pkt,sizeof(pkt));
char dta[]="RESTARK IMU\r\n";
CDC_Transmit_FS((uint8_t*)dta,strlen(dta));
}
if(FLAG_BNO_RST==1)
{
FLAG_BNO_RST=0;
bno055_assignI2C(&hi2c1);
bno055_setup();
bno055_setOperationModeNDOF();
char dta[]="while1 restart\r\n";
CDC_Transmit_FS((uint8_t*)dta,strlen(dta));
HAL_Delay(2000);
}
}
/* USER CODE END 3 */
2026-02-12 11:28 PM
Hi, members, There have some kind people give me some advice and I try it
Update this column. 2026.02.13
-------------------------------------------------------------------------------------------------------------------------
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
Buf[*Len] = '\0';
if(strcmp((char*)Buf,"RESTARTBNO055")==0)
{
FLAG_BNO_RST = 1;
char dta[]="RESTARK IMU\r\n";
CDC_Transmit_FS((uint8_t*)dta,strlen(dta));
}
//USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
//USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
/* USER CODE END 6 */
}
-------------------------------------------------------------------------------------------------------------------------
//in the usbd_cdc_if.c
#define CDC_RX_BUF_SIZE 256
volatile uint8_t cdc_rx_buf[CDC_RX_BUF_SIZE];
volatile uint16_t cdc_rx_head = 0;
volatile uint16_t cdc_rx_tail = 0;
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
for(uint32_t i = 0; i < *Len; i++)
{
ringbuffer_put(Buf[i]);
}
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, Buf);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return USBD_OK;
}
//add this function
void ringbuffer_put(uint8_t data)
{
uint16_t next = (cdc_rx_head + 1) % CDC_RX_BUF_SIZE;
if(next != cdc_rx_tail) // buffer not full
{
cdc_rx_buf[cdc_rx_head] = data;
cdc_rx_head = next;
}
else
{
}
}
//in the main.c
//add this funciton
void CDC_Process(void)
{
static char cmd[64];
static uint8_t idx = 0;
while(cdc_rx_tail != cdc_rx_head)
{
char c = cdc_rx_buf[cdc_rx_tail];
cdc_rx_tail = (cdc_rx_tail + 1) % CDC_RX_BUF_SIZE;
if(c == '\n')
{
cmd[idx] = 0;
idx = 0;
if(strcmp(cmd, "RESTARTBNO055\r") == 0)
{
FLAG_BNO_RST = 1;
CDC_Transmit_FS((uint8_t*)"RESTART IMU\r\n", 13);
}
}
else
{
if(idx < sizeof(cmd)-1)
cmd[idx++] = c;
}
}
}
// in the while loop
while(1)
{
CDC_Process();
bno055_vector_t v = bno055_getVectorQuaternion();
int32_t iw = (int32_t)(v.w * 1000000);
int32_t ix = (int32_t)(v.x * 1000000);
int32_t iy = (int32_t)(v.y * 1000000);
int32_t iz = (int32_t)(v.z * 1000000);
sprintf(msg, "@%d,%d,%d,%d&\r\n", iw, ix, iy, iz);
if (CDC_Transmit_FS((uint8_t*)msg, strlen(msg)) == USBD_OK) {
} else {}
HAL_Delay(10);
}
//in the usbd_cdc_if.c
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) {
/* USER CODE BEGIN 6 */
if (*Len < CDC_RX_BUF_SIZE) {
memcpy(rx_buffer, Buf, *Len);
rx_buffer[*Len] = '\0';
rx_len = *Len;
rx_flag = 1;
}
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
}
//in the main.c
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(rx_flag)
{
rx_flag = 0;
if(strcmp((char*)rx_buffer,"RESTARTBNO055")==0)
{
char dta[] = "restart imu\r\n";
CDC_Transmit_FS((uint8_t*)dta,strlen(dta));
FLAG_BNO_RST=1;
}
}
if (FLAG_BNO_RST)
{
bno055_setup();
bno055_setOperationModeNDOF();
FLAG_BNO_RST = 0;
}
bno055_vector_t v = bno055_getVectorQuaternion();
int32_t iw = (int32_t)(v.w * 1000000);
int32_t ix = (int32_t)(v.x * 1000000);
int32_t iy = (int32_t)(v.y * 1000000);
int32_t iz = (int32_t)(v.z * 1000000);
sprintf(msg,"@%d,%d,%d,%d&\r\n",iw,ix,iy,iz);
if(CDC_Transmit_FS((uint8_t*)msg, strlen(msg))==USBD_BUSY)
{}
else{}
HAL_Delay(10);
}
/* USER CODE END 3 */-------------------------------------------------------------------------------------------------------------------------
ref:
1. https://community.st.com/t5/stm32-mcus-embedded-software/receive-via-usb-cdc-a-k-a-virtual-com-port/td-p/759154
2. https://mcu.eetrend.com/content/2017/100008322.html
-------------------------------------------------------------------------------------------------------------------------
remark: I try to slow down the frequency from100hz to 20hz, the data could send and receive via USB VCP. Conditions where using the Kalman filter is unfavorable.