cancel
Showing results for 
Search instead for 
Did you mean: 

implement maximum speed adc to usb transfert

julien12657
Associate III

I am trying that :

sprintf((char*)buffer,"%d\r",HAL_ADC_GetValue(&hadc));

CDC_Transmit_FS(buffer,8);

but the speed is only 3 or 4kS/s

Someone has something better ?

53 REPLIES 53

Have a larger buffer(s), and leave in binary. ie uint16_t buffer[32];

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
julien12657
Associate III

with HAL_ADC_GetValue(&hadc)) and CDC_Transmit_FS(), I can't not transmit in binary

Do you have an example with HAL librairy ?

Bob S
Principal

What makes you think you cannot transmit binary data? I do this all the time (on an STMF407 using the older SPL (pre-Cube) library. Disclaimer: while a reasonable person would expect the same ability in the Cube libraries, I have no direct experience using USB CDC with the Cube libraries. The only issue I can see with binary data is if you have "text" mode somehow enabled and a driver is translating "newline/linefeed" (0x0a) into CR/LF (0x0d 0x0a).

julien12657
Associate III

should I transform HAL_ADC_GetValue(&hadc)) in binary ?

Bob S
Principal

HAL_ADC_GetValue() already *IS* binary. It returns a 32-bit value, of which only the 12 LSBs are significant (depending on which CPU you are using and whether you treat the A/D data as unsigned or signed, or for that matter left-justified or right justified). As @Community member​ said, fill a buffer with values from the ADC, then send that buffer.

S.Ma
Principal

The CDC class as Full Speed device probably has a maximum average bit rate. I think the host (PC) will poll the MCU each 1 msec (if the descriptor is correctly configured) with a max packet (64 bytes every 1 msec? = 64kbps).

As such, you should create an ADC SW FIFO to pack the 16 bit data. If you want to keep ASCII codes, you could simply use HEXA coding (4 bytes per value + space separator) so you can log and import as CSV file into excel for debugging. Use binary once all looks fine.

If you need higher bit rate, probably a High Speed USB is the way to go.

julien12657
Associate III

should I use "%b\r" instead of "%d\r" in the sprintf function ?

Bob S
Principal

WTF is "%b"??? binary??? No. Even IF this is a GCC printf extension, it is non-standard. If you are going to send binary data, don't use sprintf() at all. Just store directly from HAL_ADC_GetValue() into your array. If you are going to send a human-readable representation of the data, this gets a bit more complicated, but keep the existing format (though I would suggest changing the "\r" to "\n", unless you specifically need the "\r"). To make things easier I would use a fixed-length text field so that every time you sprintf() you get a known # of characters. For example "%6d\r" will always output 7 bytes PLUS A TRAILING NULL, with leading spaces when necessary. You need 5 bytes for the 16-bit value plus one for sign (if your data is sign-extended) plus one for the "carriage return". If you print into a 64-byte buffer, you can store 9 values (63 bytes) plus the final trailing NULL. Then send the buffer telling CDC_Transmit_FS() that the buffer length is 63 bytes (don't send the trailing null).

I'll leave it as an exercise to you to figure out how to fill the 64-byte buffer with 9 consecutive sprintf() calls.

In response to @S.Ma​ - While the USB buffer len is 64 bytes, CDC uses BULK transfers to send data (same as the mass storage [MSC] class), so it can send much more than 64 bytes during each 1ms frame. Throughput is limited only by how fast you can stuff data into the buffers, how fast the ST library can respond to IN requests, and how fast the host-side driver can handle the data.

julien12657
Associate III

So the only thing I understand is that HAL_ADC_GetValue() is a 32-bit value with only the 12 LSB which are significant

so for example it can be 0000 0000 0000 0000 0000 1011 0110 1110 which means that the decimal value is 2926.

so if the reference voltage is 3.300 V the voltage I read is 3.300*(2926/4096)=2.357 V

but what should I store in my array (or buffer), should I store the "0" and the "1" and how ?