cancel
Showing results for 
Search instead for 
Did you mean: 

Interface with external ADC via SPI at 1MS/s

CPurc.1
Associate II

Hi all,

I am using the NUCLEO-F446RE with the STM32F446RE. I am trying to interface with an external dual sampling differential ADC: ADS9224R.

ADC Timing Diagram

0693W00000KZlwCQAT.pngThe ADC can provide samples at up to 3M/s. I would be happy to achieve ~0.8M/s sampling.

I have been struggling to meet the timing that I require and can only reach ~180kHz with the STM32. My problem is that initiating separate SPI receive calls takes too long between commands.

Running the following code to initiate back to back SPI reads:

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //CS LOW
  HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buffer, 1,40);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); //CS high
 
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //CS LOW
  HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buffer, 1,40);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); //CS high

Produces the following timing:

0693W00000KZlxPQAT.png 

The STM32 is operating at 180MHz, and the SPI CLK is at ~30MHz. You can see that once the SPI initiates it is very fast, but the time to initiate the next SPI read is taking too long (~6us) which is limiting the rate at which I can read from the ADC.

I understand that this approach will only read ADC-0A, and not ADC-0B simultaneously. I have an implementation that uses QSPI but suffers from the same problem. I have simplified to single line SPI in hope that more people can provide help and I can transfer this to a dual line implementation.

Thank you all for your help!

27 REPLIES 27

Here are my settings and waveforms:

0693W00000Ka7OMQAZ.png0693W00000Ka7NxQAJ.png0693W00000Ka7OlQAJ.png

I've replicated this on my side now! The red and blue waveforms are the dual ADC outputs.

0693W00000Ka7zmQAB.jpgMay I ask if it is possible to increase the OC3REF TRGO pulse width by 1 more clock cycle to delay the sclk a little more, to relieve the timing a bit. I don't think it is a big problem if this is difficult to do (I already tried changing the pulse of TIM2, channel3 but it didn't help).

I'm going to try and implement the 2 slave SPI with DMA now! I'll let you know how I get on.

Thanks again.

Nice. If you set TIM2 CH3 Pulse to a larger value, say 9, the SPI clocks move right. I do that in the debugger with execution paused and setting the registers in the SFR View (STM32CubeIDE) until the waveforms fit. The 80 MHz clock is also arbitrary as it was max. on the L4.

hth

KnarfB

Thanks, I will give that a try tomorrow when I have access to the oscilloscope, although I thought I had already tried that...

My SPI DMA receive callback does not seem to run. I am configuring a single SPI currently as shown below:

0693W00000Ka94xQAB.png 

0693W00000Ka95RQAR.png0693W00000Ka95bQAB.png0693W00000Ka94ZQAR.png 

With the following code:

//before main:
uint16_t buffer[100];
__HAL_SPI_ENABLE(&hspi2);
HAL_SPI_Receive_DMA(&hspi2, (uint8_t *)&buffer, 1);
 
//after main:
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef * hspi)
{
    int a; //BREAKPOINT HERE
}

When running the code in debug mode with a breakpoint on line 9, I would expect the callback to run because data will be read by the slave SPI.

In hardware I have connected:

SPI2_SCLK -> Timer 1 pulse output

SPI2_INPUT -> ADC_output_A

Do I need to trigger the read of the SPI? Or should this happen automatically if it is fed the clock? Do I need to enable hardware NSS, and also connect the CS, I tried this but got the same result?

Thanks!

@KnarfB​ 

I moved up the line "MX_DMA_Init();" so it was above "MX_SPI2_Init();", and I am now receiving the callback interrupt. I believe this is a bug with the code generated by cubemx when it is integrated with the IDE. I will let you know if I can get valid data out :)

EDIT: DMA correctly writes data to the buffer. Second SPI slave can be enabled in the same way as the first to achieve dual data transfer.

Hello ,

I am using stm32h7 and needs to read data from ads8661, I followed the above and managed to get the following graph. what I noticed is I also get the data value in the MISO line as shown.

0693W00000KdguYQAR.jpgRED is the clock connected to TIM1_CH1

GREEN is the CS pin connected to TIM2_CH1

BLUE is the MISO pin

when I configure the SPI as and how it is done above i.e Recieve only slave mode with DMA I am reading garbage values.

I used the following code

__HAL_SPI_ENABLE(&hspi2);
 
 HAL_SPI_Receive_DMA(&hspi2, (uint8_t *)&buffer, 2);
 
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
 
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 
 while(1)
{
	  HAL_Delay(1000);
	  HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
 
	  HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
 
	  HAL_UART_Transmit(&huart3,"-------------------------------\n", 30, 10);
	   for(int i=0;i<100;i++)
	   {
		   	   sprintf(UART3_rxBuffer2,"=%05d\n",spibuffer[i]);
		   	   HAL_UART_Transmit(&huart3, UART3_rxBuffer2, 7, 10);
	   }
 
 
	   memset(buffer,0,99);
	  HAL_Delay(10);
 
	  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
 
	  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 
}

In hardware I have connected:

SPI2_SCLK -> Timer 1 ch 1

SPI2_INPUT -> MISO

screen shot of Garbage values printed on console

0693W00000Kdh0CQAR.pngstarts with 0's and followed by

0693W00000Kdh0HQAR.png 

why the value read are garbage values ? shouldnt it be a constant according to the MISO line in the scope?

P.S - https://community.st.com/s/question/0D53W00001QfLrQSAV/using-stm32h747-i-am-reading-adc-data-using-spi-on-ads8661-ic-the-sampling-rate-we-are-able-to-read-at-is-14us-using-for-looppfa-trying-to-reduce-the-sampling-rate-by-dma-receive-through-tim12-trigger-not-working-please-guide-me-how-to-in-cube-m...

Thanks!

charlescho64
Associate II

Hello, 

I am currently developing an MCU based radar. I tried to implement 4-channel ADC Sampling 1MSPS based on STM32H743, but the results were not good. There are many problems, but the biggest problem is the sampling rate, so to solve this, we plan to use an external high-speed ADC chip (AD7383-4). As you all know, the STM32H7 series supports QuadSPI. Of course, there are mainly examples related to Memory. Some engineers say that you can set it to indirect mode and do it. (https://stackoverflow.com/questions/73855861/qspi-connection-on-stm32-microcontrollers-with-other-peripherals-instead-of-flas). Another engineer said that STM32 Quad SPI is difficult to use because it is for memory and data is loaded alternately on the Quad SPI data line. This part seems to be somewhat limited to memory.

Do you know if there is a way to simultaneously receive 4 channel ADC data at 4MSPS using quad SPI on STM32H7?

 

Hello, CPurc.1 

I find your work very useful. Can you upload a project containing your work?

BR