Skip to main content
Associate III
October 16, 2024
Solved

Send 16bits buffer via USB Virtual COM Port.

  • October 16, 2024
  • 3 replies
  • 3927 views

Hi, I have a buffer with 65000 values in 16 bits from the ADC read that I need to provide to my computer running a python code.

Any suggestion how can I handle this in both sides?

I'm trying to use this function but I'm getting weird data when I'm listening the COM port with Putty.

 

// Generalized function to transmit any 16bits buffer over USB
void send_16b_buffer_over_usb(uint16_t *buffer, uint32_t buffer_size)
{
 uint32_t total_bytes = buffer_size * BYTES_PER_SAMPLE; // Total size of the buffer in bytes
 uint32_t bytes_sent = 0;
 uint8_t result = USBD_OK;

 // Send the buffer in chunks
 while (bytes_sent < total_bytes)
 {
 // Calculate the remaining bytes to be sent
 uint32_t bytes_to_send = (total_bytes - bytes_sent > CHUNK_SIZE) ? CHUNK_SIZE : (total_bytes - bytes_sent);

 // Send the current chunk of data
 result = CDC_Transmit_HS((uint8_t*)&buffer[bytes_sent / BYTES_PER_SAMPLE], bytes_to_send);

 // Wait for the USB transmission to complete
 while (result == USBD_BUSY)
 {
 result = CDC_Transmit_HS((uint8_t*)&buffer[bytes_sent / BYTES_PER_SAMPLE], bytes_to_send);
 }

 // If the transmission was successful, update the sent bytes counter
 if (result == USBD_OK)
 {
 bytes_sent += bytes_to_send;
 }
 else
 {
 // Handle transmission failure (optional)
 break;
 }
 }
}

 

If I do something simple like this it work fine:

 

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t *data = "Hello World from USB CDC\n";
/* USER CODE END 0 */

int main(void)
{
 HAL_Init();
 
 SystemClock_Config();

 MX_GPIO_Init();
 MX_USB_DEVICE_Init();

 while (1)
 {
	 CDC_Transmit_FS(data, strlen(data));
	 HAL_Delay (1000);
 }
}

 

Thank you.

Best answer by fposser

With this code I was able to read the correct values.

Thank you for the support.

 

 

 

def read_serial_data(buffer_size, output_file):
 # Buffer to store the received binary data
 buffer = bytearray()

 while len(buffer) < buffer_size:
 # Read binary data from UART
 data = ser.read(buffer_size - len(buffer)) # Read only the remaining bytes needed to fill the buffer

 if data:
 buffer.extend(data) # Append received data to the buffer
 print(f"Received {len(data)} bytes, total: {len(buffer)} bytes")

 if len(buffer) >= buffer_size:
 print("Buffer filled.")
 break

 # Convert the buffer to a hexadecimal string
 hex_data = buffer.hex()

 # Insert commas between every four hexadecimal characters
 formatted_hex_data = ','.join(hex_data[i:i + 4] for i in range(0, len(hex_data), 4))

 # Save the formatted hexadecimal string to a text file
 with open(output_file + "_hex.txt", "w") as f:
 f.write(formatted_hex_data)
 print(f"Saved {len(formatted_hex_data)} characters to '{output_file}_hex.txt'")

 # Convert groups of four hex values to 16-bit numbers and then to decimal
 decimal_values = []
 for i in range(0, len(hex_data), 4): # Process 8 hex characters (4 bytes) at a time
 if i + 4 <= len(hex_data):
 low_part = hex_data[i:i + 2]
 high_part = hex_data[i + 2:i + 4]
 combined_value = int(high_part + low_part, 16)
 decimal_values.append(combined_value)

 # Save the decimal values to a new file
 with open(output_file + "_decimal.txt", "w") as f:
 for value in decimal_values:
 f.write(f"{value}\n")
 print(f"Saved {len(decimal_values)} decimal values to '{output_file}_decimal.txt'")

 

3 replies

Andrew Neil
Super User
October 16, 2024

@fposser wrote:

I'm trying to use this function but I'm getting weird data when I'm listening the COM port with Putty.


Define "weird".

You're sending raw binary data - so that would not be expected to appear as readable text on a terminal!

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
fposserAuthor
Associate III
October 16, 2024

Yes, you are right. I will try to catch this with Python to see if I can read the values.

fposser_0-1729066671215.png

What is the highest speed I can communicate on the COM Port using this USB?

Andrew Neil
Super User
October 16, 2024

Or you could try RealTerm - it is able to display binary data.

No doubt there are also others ...

 


@fposser wrote:

What is the highest speed I can communicate on the COM Port using this USB?


No idea.

PS:

But the H7 family seems to have various USB options - so you'd probably need to say which part you're using...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
gbm
Principal
October 16, 2024

1. The baud rate setting is meaningless for VCP (unless you pass the traffic from/to a real UART) and does not influence the USB transfer speed.

2. Calling the function from main loop will sooner or later freeze the USB stack. The code must be rewritten so that Transmit call is made with interrupts locked or from an ISR of the same priority as USB interrupt.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Andrew Neil
Super User
October 16, 2024

@gbm wrote:

1. The baud rate setting is meaningless for VCP (unless you pass the traffic from/to a real UART) and does not influence the USB transfer speed.


True, but still leaves the question, "What is the USB transfer speed?"

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
gbm
Principal
October 21, 2024

Finally found some time to do VCOM benchmarks using my device stack and TeraTerm 5.3.

The results are the same for VCOM baud rate setting of 9600 and 921600. VCOM data endpoint size is 64 B.

STM32U575 (160 MHz, OTG FS peripheral in Full-Speed mode): receiving from PC: 507..530 kB/s, sending: 309..326 kB/s

STM32C071 (48 MHz, DRD peripheral, Full-Speed mode): receiving from PC: 230 kB/s, sending: 300..303 kB/s.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
fposserAuthorBest answer
Associate III
October 20, 2024

With this code I was able to read the correct values.

Thank you for the support.

 

 

 

def read_serial_data(buffer_size, output_file):
 # Buffer to store the received binary data
 buffer = bytearray()

 while len(buffer) < buffer_size:
 # Read binary data from UART
 data = ser.read(buffer_size - len(buffer)) # Read only the remaining bytes needed to fill the buffer

 if data:
 buffer.extend(data) # Append received data to the buffer
 print(f"Received {len(data)} bytes, total: {len(buffer)} bytes")

 if len(buffer) >= buffer_size:
 print("Buffer filled.")
 break

 # Convert the buffer to a hexadecimal string
 hex_data = buffer.hex()

 # Insert commas between every four hexadecimal characters
 formatted_hex_data = ','.join(hex_data[i:i + 4] for i in range(0, len(hex_data), 4))

 # Save the formatted hexadecimal string to a text file
 with open(output_file + "_hex.txt", "w") as f:
 f.write(formatted_hex_data)
 print(f"Saved {len(formatted_hex_data)} characters to '{output_file}_hex.txt'")

 # Convert groups of four hex values to 16-bit numbers and then to decimal
 decimal_values = []
 for i in range(0, len(hex_data), 4): # Process 8 hex characters (4 bytes) at a time
 if i + 4 <= len(hex_data):
 low_part = hex_data[i:i + 2]
 high_part = hex_data[i + 2:i + 4]
 combined_value = int(high_part + low_part, 16)
 decimal_values.append(combined_value)

 # Save the decimal values to a new file
 with open(output_file + "_decimal.txt", "w") as f:
 for value in decimal_values:
 f.write(f"{value}\n")
 print(f"Saved {len(decimal_values)} decimal values to '{output_file}_decimal.txt'")

 

Andrew Neil
Super User
October 21, 2024

@fposser wrote:

With this code I was able to read the correct values.


Excellent - please mark the solution:

https://community.st.com/t5/community-guidelines/help-others-to-solve-their-issues/ta-p/575256 

That's the PC-side code - yes?

So the STM32 code was working all along - the problem was the PC side interpreting it?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
fposserAuthor
Associate III
October 21, 2024

Yes, this is the PC code.

STM32 was fine.

Im having other troubles now with the ADC but it's not related with this.

https://community.st.com/t5/stm32-mcus-boards-and-hardware/ch2-on-adc1-does-not-work-while-ch15-or-ch2-ch15-works-fine/td-p/733584