Setting up SPI for AD7190 with STM32G474CE
- February 11, 2021
- 1 reply
- 3000 views
Hi all,
I am trying to setup SPI for the ADC AD7190. I am just attempting to reset the ADC after power up and then read the device ID register to check the communication. I have not been able to do that until now. I will summarize the code here and I use the HAL library. First, it runs the HAL_init function, and as it is user generated, I wont add it here.
Here is the clock configuration:
// System generated clock config file
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
RCC_OscInitStruct.PLL.PLLN = 60;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
// After this initialization the frequency at the different buses are 147.6 MHz
}2) I have given the GPIO initialization next
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
// The port F has the external clock to it. Port A has the hardware chip select pin for the ADC
// Port B has the SPI pins PB4, PB5, PB6, and PB7
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED3_Pin */
GPIO_InitStruct.Pin = LED3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED3_GPIO_Port, &GPIO_InitStruct);
}3) Here is the SPI initialization, which I assume is the main culprit.
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
HAL_SPI_MspInit(&hspi1); // I add this function here because HAL does not generate the pin configuration for the SPI GPIOs in the GPIO initializations. This function also enables the SPI clock
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
// From what I understanad of the datasheet. CPOL=1 and CPHA=0 is the right setup
// With the prescaler the frequency is 4.126 MHz for SPI, which is within the 5MHz maximum allowed for the ADC
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; // CPOL=1
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA=0
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
__HAL_RCC_SPI1_CLK_ENABLE(); // Enable the SPI1 peripheral here.
/* USER CODE END SPI1_Init 2 */
}The HAL_SPI_MspInit function enables the clock for the SPI and after enabling that, I enable the peripheral. I am not sure if the order matters.
4) Finally, I send two commands to the ADC. I pull the chip select o low before resetting the ADC. After that, I send 10 0xFF to reset the ADC. Then 0x40 to query the ID register. And then I send a dummy variable to get the result. But somehow, no matter what I try the result is 0xFF.
// pull low the chip select
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
// Delay 100 ms
HAL_Delay(100);
// Wait for SPI1 to not be busy
while(SPI1->SR & SPI_SR_BSY_Msk);
// Flush the Rx Fifo
HAL_SPIEx_FlushRxFifo(&hspi1);
// Transmit 10 0xFF (registerword). here I receive 0xFF on registerreceive
response=HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)registerWord, (uint8_t*)registerreceive, 10, 100);
if(response==HAL_OK)
{
//This is executed properly
}
HAL_Delay(100);
// Get register ID
ADC_send=0x40; // 0x40 to communicaiton register to read from ID register
while(SPI1->SR & SPI_SR_BSY_Msk);
// ADC_received is 0xFF
response=HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&ADC_send, (uint8_t*)&ADC_received, 1, 100);
if(response==HAL_OK)
{
// If status is OK. Do something.
}
HAL_Delay(100);
// Send dummy variable to receive data
ADC_send=0x00;
response=HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)&ADC_send,(uint8_t*)&ADC_received,1,100);
while(SPI1->SR & SPI_SR_BSY_Msk);
if(response==HAL_OK)
{
// Print device ID here. But it is just 0xFF
}I know, I should be going into the board now with a scope to measure the SCLK, MOSI and MISO pins. I am doing that now. But concurrently, if you can find any obvious errors in the code, let me know!
Thank you.