2021-02-11 12:16 AM
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.
2021-02-11 01:28 AM
> 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.
Exactly.
Compare your scope images with the datasheet diagrams.
Things like pulse polarity should be obvious, but clock phase and Slave Select handling is not that much.
Cube code looks ugly.