2023-08-23 03:33 AM
Hello All,
I'm using STM32F405 with a 24 BIT ADC (ADS1298) . The ADC Sampling rate is 16Khz per channel and I want to send two channel data of the ADC i.e. 16000 samples x 2 channel x 3 bytes per sample =96000 bytes to my PC application. I have used this ADC before but at a very low sampling rate (500 SPS) which worked pretty fine.
The ADC gives an interrupt of DRDY Pin when the data is ready to read and I read the Data via SPI from the A/D.
The A/D data occurs after every 62.4 micro seconds( checked on oscilloscope).
I have used UART to send the A/D data before without any issues. But since the number of bytes is large in this situation I have to shift to USB CDC communication .
I'm new to USB CDC and I tried sending data to the PC but I could not send complete data of 1 sec to the PC within the time limit.
I'm also using Free RTOS in my stm32 code.
I studied lot of USB CDC stuff on the internet and got to know that the data should be send in packet of 64 bytes(default endpoint size) in case of USB CDC plus I need to send a ZLP in the end of 64 bytes so that the PC application knows the complete data packet has arrived. what I have tried till now is shown in the below code.
uint32_t adsdata[9]= {1,2,3,0,0,0,0,0,0};
void StartDefaultTask(void const * argument)
{
/* init code for USB_DEVICE */
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 5 */
ADS_Init();
HAL_UART_Receive_IT(&huart1, startrec, 1);
/* Infinite loop */
for(;;)
{
// CDC_Transmit_FS((uint8_t *)data,strlen(data));
// HAL_Delay(1000);
if(datatype == 't')
{
// dataready = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_6);
if(dataready == 1)
{
ADS_RDATA();
dataready = 0;
// senddat = 1;
}
}
osDelay(1);
}
/* USER CODE END 5 */
}
/* USER CODE BEGIN Header_sendata */
/**
* @brief Function implementing the myTask02 thread.
* @PAram argument: Not used
* @retval None
*/
/* USER CODE END Header_sendata */
void sendata(void const * argument)
{
/* USER CODE BEGIN sendata */
/* Infinite loop */
for(;;)
{
if(senddat == 1)
{
adsdata[3] = ((channelData[0] & 0xFF0000)>>16);
adsdata[4] = ((channelData[0] & 0xFF00)>>8);
adsdata[5] = channelData[0] & 0xFF;
adsdata[6] = ((channelData[1] & 0xFF0000)>>16);
adsdata[7] = ((channelData[1] & 0xFF00)>>8);
adsdata[8] = channelData[1] & 0xFF;
CDC_Transmit_FS((uint8_t *)adsdata,sizeof(adsdata));
//HAL_UART_Transmit_IT(&huart1, (uint8_t *)&adsdata, 15);
}
senddat = 0;
osDelay(1);
}
/* USER CODE END sendata */
}
//read data
void ADS_RDATA() { // use in Stop Read Continuous mode when DRDY goes low
uint8_t inByte,inByte1,inByte2,inByte3;
int i;
int nchan = 2; //assume 8 channel. If needed, it automatically changes to 16 automatically in a later block.
stat_1 = 0; // clear the status registers
//stat_2 = 0;
for(i = 0; i < nchan; i++){
channelData[i] = 0;
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12,GPIO_PIN_RESET); // open SPI
transferSPI( _RDATA);
// READ CHANNEL DATA FROM FIRST ADS IN DAISY LINE
for(i = 0; i < 3; i++){ // read 3 byte status register (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
inByte = transferSPI( 0x00);
stat_1 = (stat_1<<8) | inByte;
}
//HAL_UART_Transmit_IT(&huart1, (uint8_t *)&syncbyte, 3);
for(i = 0; i < 2; i++)
{
inByte1 = transferSPI( 0x00);
inByte2 = transferSPI( 0x00);
inByte3 = transferSPI( 0x00);
//bytestosend = bytestosend +3;
//if (bytestosend <= 38400)
//{
channelData[i] = (inByte1 << 16) | (inByte2 << 8) | inByte3;
//HAL_UART_Transmit_IT(&huart1, (uint8_t *)&sendchanneldata, 3);
//}
}
senddat=1;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12,GPIO_PIN_SET); // open SPI
}
I have not yet tried sending the data in packet of 64 bytes. I'm just sending the data as it is read from the A/D.
How to send the required amount of data every second to the PC ?
2023-08-23 06:02 AM
100kB/sec is very doable over USB with STM32, but you'll need to buffer the data as USB has random delays of up to ~50ms or so. Could be much longer if your PC isn't responsive.
Note that CDC_Transmit_FS can only succeed after the previous call is complete. Check the return value. Send lots of bytes at once for higher throughput, say 4kB or so at a time.