cancel
Showing results for 
Search instead for 
Did you mean: 

Not Correctly Read ADC Conversion Through SPI Interface

AE104
Senior

Hello,

On my custom designed PCB, there is a STM32F7 processor. With SPI DMA interface, I try to get the converting values of the external ADC. But everytime I get 3.1V in debug session. So how can I read the correct values based on the input signal?

while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
				
		spidata[0]=0x00;       // Set everything up  before you start the exchange
		spidata[1]=0x00;
		HAL_SPI_TransmitReceive_DMA(&hspi4,spidata,ADC_Buf,2);
		HAL_Delay(500);
  }
  /* USER CODE END 3 */
}
 
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
		Sample = (((uint16_t) ADC_Buf[1]) << 8 | ADC_Buf[0]) & 0x0FFF; 
		volt = (float)(Sample * (3.3 / 4096.0)); //
		testdata_in[i++]=volt;
		if (i>60)
		{
			i=0;
		}
}

0690X00000BuqL2QAJ.png0690X00000BuqKxQAJ.png

4 REPLIES 4

On F7 watch memory being used for DMA operations, and cache coherency issues.

Try using DTCM-RAM for these.

Check data on SPI with scope/analyzer, and try non-DMA operation.

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

How can I control as non-DMA? Such as with SPI interrupt? I want to drive the ADC with 1MSPS rate so I can only do with SPI DMA. I tried with enabling a timer interrupt and call SPI CS but the timer didn’t work with 1MSPS. I tried SPI global interrupt and call in main.c file. This doesn’t work too. Because of that I stick with the DMA. If you have an advice or clues SPI control without DMA and drive ADC 1MSPS, I will be more than happy to test it. I can share also my SPI interrupt code too.

Now I try non-DMA option. It means that control the sampling with TIM4 IRQ. I set the TIM IRQ as 1Mhz but I didn't measure any signal from ADC CS pin and other pins too (ADC SCK, ADC MOSI).

// This code in the ..it.c file,
 
void TIM4_IRQHandler(void)
{
  /* USER CODE BEGIN TIM4_IRQn 0 */
 
  /* USER CODE END TIM4_IRQn 0 */
  HAL_TIM_IRQHandler(&htim4);
  /* USER CODE BEGIN TIM4_IRQn 1 */
	
	spidata[0]=0x00;       // Set everything up  before you start the exchange
	spidata[1]=0x00;
	HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive(&hspi4, spidata,ADC_Buf,1,100);   // See below
	//HAL_Delay(500);
	
 
 
  /* USER CODE END TIM4_IRQn 1 */
}
 
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
		HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_SET);
		Sample = (((uint16_t) ADC_Buf[1]) << 8 | ADC_Buf[0]) & 0x0FFF; 
		volt = (float)(Sample * (3.3 / 4096.0)); //
		testdata_in[i++]=volt;
		i %= 60;
}
// This code is in main.c file
 
// SPI configuration
static void MX_SPI4_Init(void)
{
 
  /* USER CODE BEGIN SPI4_Init 0 */
 
  /* USER CODE END SPI4_Init 0 */
 
  /* USER CODE BEGIN SPI4_Init 1 */
 
  /* USER CODE END SPI4_Init 1 */
  /* SPI4 parameter configuration*/
  hspi4.Instance = SPI4;
  hspi4.Init.Mode = SPI_MODE_MASTER;
  hspi4.Init.Direction = SPI_DIRECTION_2LINES;
  hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi4.Init.NSS = SPI_NSS_SOFT;
  hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi4.Init.CRCPolynomial = 7;
  hspi4.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI4_Init 2 */
 
  /* USER CODE END SPI4_Init 2 */
 
}
 
 
 
 
// Timer configuration
 
static void MX_TIM4_Init(void)
{
 
  /* USER CODE BEGIN TIM4_Init 0 */
 
  /* USER CODE END TIM4_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM4_Init 1 */
 
  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 84;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */
 
  /* USER CODE END TIM4_Init 2 */
 
}

Perhaps the 1MHz IRQ is not sustainable.

You should focus on the signal on the wire, what the CS, DATA and CLOCK pins are doing, and if the data you can establish there is consistent, or not, with the data you're getting into memory. A logic analyzer may decode or display this.

Then review that in light of your SPI configurations, and the expectations of the external ADC.

HAL_SPI_TransmitReceive will block. Try validating things outside of the IRQ/TIM context.

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