Skip to main content
Graduate
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.

    This topic has been closed for replies.
    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

    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!

    fposserAuthor
    Graduate
    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?

    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...

    Graduate
    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.

    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?"

    Graduate
    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.

    fposserAuthorAnswer
    Graduate
    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'")

     

    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?

    fposserAuthor
    Graduate
    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