cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407ZGT6 to LTC1859IG read issues

lebies
Associate II

Hi all,

First post here...

I'm fairly new to STM32, working on STM32CubeIDE and have running code on a very well designed and laid out PCB with above components being the main actors.. The project was setup with STM32CubeMX V6.4.0 using STM32Cube FW_F4 V1.26.2. I haven't upgrade it yet (as suggested) because I inherited the project.

Build Id Info: STM32CubeIDE

/*
Version: 1.15.0
Build: 20695_20240315_1429 (UTC)
OS: Windows 10, v.10.0, x86_64 / win32
Java vendor: Eclipse Adoptium
Java runtime version: 17.0.8.1+1
Java version: 17.0.8.1
/*

ADC hooked up to the CPU via SPI, and CPU running at 160MHz.

Here's my problem:

I'm trying to read 5 of the 7 ADC channels sequentially and working exactly according to the LTC1859IG datasheet. If I read 1 or 2 channels only I get very accurate good values back but the minute I add any combination of the other channels (1 or more) I get (typically but not always) garbage values for either the 1st channel (0) or the last channel (4) - or both - and good values for the other channels!

I've gone down various rabbit holes trying different config settings as well as adding delays, in vain ... I'm now stuck and hoping someone can point me to possible errors in my approach/code.

Here's the code I'm trying:

//GPIO_init:
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };

	/* GPIO Ports Clock Enable */
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();

	/*Configure GPIO pin Output Levels */
	HAL_GPIO_WritePin(GPIOA, SPI1_nCS1_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOA, SPI3_nCS1_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOC, ADC2_CONVST_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOB, ADC1_CONVST_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOB, SPI1_nCS2_Pin | SPI1_nCS3_Pin | SPI1_nCS4_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SPI2_nCS1_GPIO_Port, SPI2_nCS1_Pin, GPIO_PIN_SET);

	/*Configure GPIO pins : SPI1_nCS1_Pin */
	GPIO_InitStruct.Pin = SPI1_nCS1_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	/*Configure GPIO pin : ADC2_CONVST_Pin */
	GPIO_InitStruct.Pin = ADC2_CONVST_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

	/*Configure GPIO pins : ADC1_CONVST_Pin SPI2_nCS1_Pin SPI1_nCS2_Pin SPI1_nCS3_Pin SPI1_nCS4_Pin */
	GPIO_InitStruct.Pin = ADC1_CONVST_Pin | SPI2_nCS1_Pin | SPI1_nCS2_Pin | SPI1_nCS3_Pin | SPI1_nCS4_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	/*Configure GPIO pins : ADC1_BSY_Pin /
	GPIO_InitStruct.Pin = ADC1_BSY_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	/*Configure GPIO pins : ADC2_BSY_Pin */
	GPIO_InitStruct.Pin = ADC2_BSY_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	/* EXTI interrupt init*/
	HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
	HAL_NVIC_EnableIRQ(EXTI1_IRQn);


//SPI1_init:
	hspi1.Instance = SPI1;
	hspi1.Init.Mode = SPI_MODE_MASTER;
	hspi1.Init.Direction = SPI_DIRECTION_2LINES;
	hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
	hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
	hspi1.Init.NSS = SPI_NSS_SOFT;
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;	(RCC_OscInitStruct.PLL.PLLN = 160; ie 160MHx)
	hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
	hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
	hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspi1.Init.CRCPolynomial = 10;


//BUSY PIN Interrupt callback:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
	if(GPIO_Pin == ADC1_BSY_Pin) {
		haveADC1 = 1;
	}


void ADCM_ConvertStart()  {
	unsigned long st;

	// start conversion
//	while( hspi1.State != HAL_SPI_STATE_READY );  				// wait xmission complete
	HAL_GPIO_WritePin(GPIOB, ADC1_CONVST_Pin, GPIO_PIN_SET);	// ADC1_CONVST HI
	st = DWT->CYCCNT;											// 8 (+50ns)
	while(DWT->CYCCNT - st < ADC_CONV_CYCLE_COUNT);
//	delayC = (DWT->CYCCNT - st);
	HAL_GPIO_WritePin(GPIOB, ADC1_CONVST_Pin, GPIO_PIN_RESET);	// ADC1_CONVST LO
}


void ADCM_Start1()  {
	HAL_StatusTypeDef err;
	unsigned long st;
	uint16_t res = 0;

	chSelect = 0;
	HAL_GPIO_WritePin(GPIOA, SPI1_nCS1_Pin, GPIO_PIN_RESET);									// !SPI1_nCS1 (RD) = LO
	st = DWT->CYCCNT;
	while(DWT->CYCCNT - st < ADC_READ_CYCLE_COUNT);				// 3 cycles
	err = HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&RD_CH0, (uint8_t*)(&res), 2, 50);				// setup LA1_ADC1_IN1
	HAL_GPIO_WritePin(GPIOA, SPI1_nCS1_Pin, GPIO_PIN_SET);										// SPI1_nCS1 (RD) = HI
//	while( hspi1.State != HAL_SPI_STATE_READY );  												// wait xmission complete
	if( err != HAL_OK )
		doSPI_Error(err);

	chVals[0] = res;
	// start conversion
	ADCM_ConvertStart();
}


ADC_Read():
//	while( hspi1.State != HAL_SPI_STATE_READY );  				// wait xmission complete
	HAL_GPIO_WritePin(GPIOA, SPI1_nCS1_Pin, GPIO_PIN_RESET);	// nCS1 (RD) = LO
	st = DWT->CYCCNT;
	while(DWT->CYCCNT - st < ADC_READ_CYCLE_COUNT);				// 3 cycles
	err = HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&RD_CH1, (uint8_t*)(&res), 2, 50);
	HAL_GPIO_WritePin(GPIOA, SPI1_nCS1_Pin, GPIO_PIN_SET);
//	while( hspi1.State == HAL_SPI_STATE_READY );  				// wait xmission complete
	if( err != HAL_OK )
		doSPI_Error(err);
	chVals[0] = res;
//	st = DWT->CYCCNT;
//	while(DWT->CYCCNT - st < ADC_READ_CYCLE_COUNT);
	ADCM_ConvertStart();										// start next conversion


Algorithm:
	//call ADCM_Start1() before main.while( true )
	//onInturrupt (CONV_BSY HI+EDGE), set flag to read and save result of conversion (haveADC1)
	
	ADCM_Start1();
	while (loopcount < 100)
		{
			if( 1 == haveADC1 )		// wait for CONV_done
			{
				switch (chSelect) {
					case 0:
						chVals[0] = 0;
						ADCM_ReadChannel(0);							// gets result of previous conversion and sets up next channel
						TransmitDataPacket.M_HALL_LA1 = chVals[0];		// send packet
						TransmitDataPacket.time = timeSinceStartup_ms;
						dumpAsciiPacket_ToWIFI();
						chSelect = 1;									// select next channel to read
						haveADC1 = 0;									// set semaphore (used to wait for CONV done)
						ADCM_ConvertStart();							// start CONVersion (toggle CONV GPIO)
						break;
				...
					//for all channels

 

3 REPLIES 3
liaifat85
Senior III

Experiment with lowering the SPI clock speed by adjusting the BaudRatePrescaler value to see if a slower SPI speed improves reliability.

Thanks @liaifat85, I'll try again in the morning. I think I've tried that but will slow it down to a trickle and see what that does.

Appreciate the quick response, thanks.

 

@liaifat85

Tried right down to SPI_BAUDRATEPRESCALER_128, but no dice!

For context, here's what I'm reading:

time     CH_0 CH_1 CH_3 CH_4
============================
000033e9,0798,07d0,746d,76ea
000033eb,080f,0810,743e,771b
000033ed,0000,0000,742a,7760
000033ef,0000,0000,7456,7735
000033f2,0000,0000,743c,7762
000033f4,0000,0000,745d,770d
000033f6,0000,0000,7472,773f
000033f8,0000,0000,7440,7723
000033fa,0000,0000,7424,7716
000033fd,0000,0000,7447,7708
000033ff,0743,07bf,741a,775a
00003401,07fc,07ff,7459,7718
00003403,0000,0000,7481,7706
00003405,0000,0000,7434,772f
00003407,0000,0000,746f,7708
0000340a,0000,0000,744e,774b
0000340c,0000,0000,743a,772b
0000340e,0000,0000,745b,76fd
00003410,0000,0000,7433,7755
00003412,0000,0000,745f,76ec

where time = timeSinceStartup_ms

CH_0 and CH_1 are very accurate, CH_3 and CH_4 are thumbing their nose at me!

 

cheers///