cancel
Showing results for 
Search instead for 
Did you mean: 

how to send 4096 int32_t by USB CDC

leogarberoglio
Associate III
Posted on August 28, 2015 at 02:22

Hi, I'm working on a project that use an audiocodec, connected to a stm32f411 uC by I2S and I2C. I use

HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);

to send 2 tone sound and receive the ''echo'' on the microfone. SAMPLES=4 Then I process the incoming data to transform on 32 bit int:

for(i=0;i<
2
*SAMPLES;i+=2)
{
tmp
= 
InputBuffer
[i];
tmp = ((tmp&0x0000FFFF)<<16) | ((tmp&0xFFFF0000)>>16);
tmp >>= 8;
InputBuffer2[i/2] = tmp;
}

and obtain a 4096 array of int I would like to send that by USB to my terminal program. I've never work with USB before, I've just could send a string by USB CDC and receive it on my terminal. Now I write this:

while(1)
{
if (u8_cdc_initialized)
{
CDC_Transmit_FS(&InputBuffer2[i], 512);
i+=512;
if(i==4608){
CDC_Transmit_FS((uint8_t *)''start'', 5);
i=0;
}
}
HAL_Delay(100);
}

I receive the data on my terminal, but I can't synchronize and recover 4096 * 4 bytes becouse if I configure the terminal to receive ASCII I can see ''start'', but data is unreadable and if I configure the terminal for HEX I can't finde ''start''. I know that the correct way is wait on the uC for a character sending by the terminal, and, as an answer to that incoming character, send 4096*4 bytes. But, I don't know how to do that..... where do I can detect character send by the terminal program? waht is the best way to send all of the data? I'm not sure how many bytes should I send on each

CDC_Transmit_FS

can some one point me on the right direction? Thank!
4 REPLIES 4
Mikk Leini
Senior
Posted on August 28, 2015 at 08:36

Hi,

First of all i must ask why would you want to use CDC for audio at all? CDC uses USB bulk transfer, it has unpredictable delay. For audio you would probably want to use isochronous transfer. Read this:

http://www.beyondlogic.org/usbnutshell/usb4.shtml#Isochronous

ST has example for that in HAL library:

STM32Cube_FW_F4_V1.7.0\Projects\STM32446E_EVAL\Applications\USB_Device\AUDIO_Standalone

If you still want to use CDC then ok, i can say that if you display data in Hex and then look for ''start'' in hex as well. ''start'' is formed of ASCII characters and just decode it by the table:

http://www.asciitable.com/

start = 0x73 0x74 0x61 0x72 0x74

However, what would you do next? Is the goal of your application to just see raw 4KB of data? I don't think so. So you probably need to create some PC application which finds the ''start'' automatically and does the processing of the data. One option is to use Microsoft Visual Studio and C++ / C# for that.

To give better answer please describe the purpose of your application.

leogarberoglio
Associate III
Posted on August 28, 2015 at 16:36

Thank you very much for your answer!

Let me try yo explain my project. I have an audio codec conected to uC by I2S. The purpose is to run some test on internal ear. I play 2 tones and expect a response from the choclea (DPOAE). DPOAE signal is very very noise signal, so I have to proccess that signal. In thenear future I will have to run a FFT over that signal, but, right now I would like to proccess on my PC with Matlab. So, I'm not sure about transfering data as AUDIO data. I will read about it. I think that I will need to develop a litle program on PC side (as you suggest) to decode the data, becouse I send one byte after the other byte and they are inverted, for example if I have 0x89ABCDEF I receive EF then CD, AB and last 89 (becouse I can send bytes, not word's). My be a can make a function that send's words, byte by byte... or I just decode on PC side. But my real problem is that I don't know what is the flow diagram to make a good communicatin and data transfer to the PC. I mean, I have to init usb and wait for a char (from the host) that indicate that uC can start to transfer data... uC start transfer data with

CDC_Transmit_FS

function? how many byte should I send on each CDC_Transmit calling? as soon as uC start to send data, PC side program receive it? or there is a buffer some there to fill after PC program receive data? where do I have to put the code that wait for a char from the PC? how about PC side program? I have visual c 2010, any sample code? as you can see I just need to extract 4096byte from the uC memory and put ir on a CSV file... I try with memory explorer and export utility from eclipse, but I can't configure how to data being exported. I don't have speed requirement.... Can you help me ? Tjank a lot!
Mikk Leini
Senior
Posted on September 04, 2015 at 21:57

Okay, I didn't fully understood the application, but it seems you need to learn and try couple of things. There's no short answer.

First of all, download STM32CubeF4 and look at the USB CDC example inside the zip file:   Projects\STM324x9I_EVAL\Applications\USB_Device\CDC_Standalone

It demonstrates how to make a USB - UART converter. You need to cut out the UART part and process the USB data buffer as you want (wait for some command and respond with your audio data). I couldn't find any ready-made example with quick searching so you probably need to search the forum and try things out on your own.

On PC side, create the serial port application. Here's a short tutorial:

http://csharp.simpleserial.com/

This example handles serial data as string. You need to handle bytes. For help around this you better need to use Microsoft forums. But C# has lot of material and information on web so use Google.

One interesting effect with USB CDC is that on PC side you can choose whatever baudrate you want because all the data goes to MCU through the USB at it's own speed anyway.

leogarberoglio
Associate III
Posted on September 05, 2015 at 19:22

Ok, I make some progress.

I understand that receive thata is manage by interrupt, and ISR end calling CDC_Receive. So I put my code there to process command from the PC aplication:

extern char msg[4];
extern char fUSB_rcv;
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
char i = 0;
fUSB_rcv=1;
for (i = 0; i < *Len; i++)
msg[i] = *(Buf + i);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
}

In main.c I have:

char msg[4];
char fUSB_rcv;
....
while(1)
{
if(fUSB_rcv)
{
// CDC_Transmit_FS((uint8_t *)''Mensaje Recibido

'', 18);
// HAL_Delay(10);
if (msg[0]=='L' )
{
CDC_Transmit_FS((uint8_t *)''1'', 1);
}
else
{
CDC_Transmit_FS((uint8_t *)''0'', 1);
}
fUSB_rcv=0;
}
}

So I wait for a comand, character L, and response with 1 or 0. On my PC side I have a litle program writen in vb.net that open the serial comm and send the L character and show a message if received a 1. Right now I'm working on 16Kbyte transfer and 1024 float32_t transfer and reconstruct on PC side. I'm looking how to send a uint32_t and a float32_t byte after byte and reconstruc them on the PC. Thank!