cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 QSPI in normal SPI mode for interface external DAC

Vero
Associate II

My only need is to use QSPI (dual mode bank1) as a simple/normal SPI to drive external DAC (AD5066).  I should only use the Data phase, I don't need the Instruction, Address, Alt and Dummy phases of the QSPI.

I have to use:

QUADSPI_CLK---> DAC_CLK

QUADSPI_BK1_NCS---> DAC__CS

QUADSPI_BK1_I00/SO(MOSI)---> DAC_MISO

QUADSPI_BK1_I01/SI (MISO)---> DAC_MOSI ( no need for DAC because is only slave)

 

I would like to use only the Data phase of the QSPI to send the 4 Bytes for the ADC (command, channel, data bits ...)

It is possible to use the QSPI as a SPI normal with a ADC and not with a flash memory?

 

I've tried using the example QSPI/QSPI_ReadWrite_IT but I can't see anything coming out to the CLK and SI (MOSI). There are other examples not for memory?

 

6 REPLIES 6
Vero
Associate II

 

Vero_1-1712242834754.pngVero_2-1712242854731.png

 

Vero
Associate II

In main the two functions HAL_QSPI_Command(....) are working, I see clock and output data with oscilloscope, the

HAL_QSPI_Trasmit_IT (...) is made but I don't see the data and clock in output. My goal is to use only the HAL_QSPI_Trasmit_IT (...) for send 4byte to external DAC.

 

static void MX_QUADSPI_Init(void)

{/* QUADSPI parameter configuration*/

hqspi.Instance = QUADSPI;

hqspi.Init.ClockPrescaler = 2;

hqspi.Init.FifoThreshold = 4;

hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;

hqspi.Init.FlashSize = 31;

hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;

hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;

hqspi.Init.FlashID = QSPI_FLASH_ID_1;

hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;

if (HAL_QSPI_Init(&hqspi) != HAL_OK)

{

Error_Handler();

}

}

 

 

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 

HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

 

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

 

while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

 

__HAL_RCC_SYSCFG_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

 

while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_CSI;

RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;

RCC_OscInitStruct.CSIState = RCC_CSI_ON;

RCC_OscInitStruct.CSICalibrationValue = RCC_CSICALIBRATION_DEFAULT;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_CSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 240;

RCC_OscInitStruct.PLL.PLLP = 4;

RCC_OscInitStruct.PLL.PLLQ = 6;

RCC_OscInitStruct.PLL.PLLR = 2;

RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;

RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;

RCC_OscInitStruct.PLL.PLLFRACN = 0;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2

|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;

RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;

RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;

RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;

RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)

{

Error_Handler();

}

}

 

 

int main(void)

{

/* USER CODE BEGIN 1 */

 

QSPI_CommandTypeDef sCommand;

 

uint8_t step = 0;

 

 

/* USER CODE END 1 */

 

/* MCU Configuration--------------------------------------------------------*/

 

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

 

SystemClock_Config();

HAL_QSPI_DeInit(&hqspi);

MX_GPIO_Init();

MX_ETH_Init();

MX_USART3_UART_Init();

MX_USB_OTG_FS_PCD_Init();

MX_QUADSPI_Init();

MX_SPI1_Init();

/* USER CODE BEGIN 2 */

/* sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;

sCommand.AddressSize = QSPI_ADDRESS_24_BITS;

sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;

sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;*/

while (1)

{

 

 

switch(step)

{

case 0:

 

/* Enable write operations ------------------------------------------ */

sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = WRITE_ENABLE_CMD;

sCommand.AddressMode = QSPI_ADDRESS_NONE;

sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = QSPI_DATA_NONE;

sCommand.DummyCycles = 0;

sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;

sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;

 

if (HAL_QSPI_Command(&hqspi, &sCommand, 2000) != HAL_OK)

{

Error_Handler();

}//IT IS WORK!

 

/* Writing Sequence ------------------------------------------------ */

sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;

sCommand.AddressMode = QSPI_ADDRESS_NONE;//QSPI_ADDRESS_1_LINE;

sCommand.DataMode = QSPI_DATA_NONE;//QSPI_DATA_4_LINES;

sCommand.NbData = BUFFERSIZE;

 

if (HAL_QSPI_Command(&hqspi, &sCommand,2000) != HAL_OK)

{

Error_Handler();

}//IT IS WORK!

 

step++;

break;

case 1:

 

if (HAL_QSPI_Transmit_IT(&hqspi, aTxBuffer) != HAL_OK)

{

HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, SET);

Error_Handler();

} //IT IS NOT WORK!

step=1;

break;

}

}

}

 

 

Use the </> code pasting tool when in-lining code in your posts. You can also edit posts to clean up formatting issues.

I'm not sure the QSPI can be used in the mode you desire, ie data-only phase. You'd need to perhaps look more deeply at the peripheral implementation and at a register level. You'll likely need to implement your own driver code to do that.

The regular SPI peripheral might be more immediately suitable.

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

Thank is my first post.😀

The datasheet provides the SPI mode for QSPI, but I can't find any examples of using it in this way.

In my card I have only QSPI available the other SPIs are already occupied.

 I wanted to avoid writing the driver😉.....I was wondering if anyone has already been there or if there are documented examples.

 

On a hardware level, it seems possible:

 

Vero_0-1712299432921.pngVero_1-1712299553082.png

 

 

 

 

 

Vero
Associate II

Any idea by the community?

 

Is a strange request... But hasn't anyone already tried?

KDJEM.1
ST Employee

Hello @Vero ,

Could you please check the sequences shared in AN4760 section "QUADSPI indirect write: programming Quad-SPI memory using interrupts " and the errata sheet precisely 2.8 QUADSPI section.

Is the QUADSPI peripheral hanged and the BUSY flag of the QUADSPI_SR register remained high?

I hope this help you!

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.