cancel
Showing results for 
Search instead for 
Did you mean: 

Send 16bits buffer via USB Virtual COM Port.

fposser
Associate III

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.

1 ACCEPTED SOLUTION

Accepted Solutions
fposser
Associate III

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

 

View solution in original post

10 REPLIES 10
Andrew Neil
Evangelist III

@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!

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?

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

Im using the NUCLEO-H723ZG

gbm
Lead III

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

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

fposser
Associate III

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

 

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

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