Author Topic: I2S to SPI DAC with STM32F429  (Read 7050 times)

0 Members and 2 Guests are viewing this topic.

Offline matt09Topic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: gb
Re: I2S to SPI DAC with STM32F429
« Reply #25 on: August 25, 2020, 10:21:40 pm »
Quote
I have attached an image of my CubeMX configuration which produced the code to check parameters such as trigger source are correct?
Seems not. Based on reply #21, TIM1 supposed to be a master, though plain config w/o any:
 trigger - non,
 slave mode - non,
 clock - internal
Prescaller = 1000? If for testing, otherwise I don't think you need a prescaller, TIM1 16-bits, enough down to 180/ 65536 = 2.746 kHz.
 I'd set two PWM channels, one ( 1-st, if don't mind ? ) is for NSS ( or CS - Chip Select - SPI /DAC frame driver ), another PWM ( 2-nd ? ) specifically  for slave timer TIM2 gating. Doing so, you will have an option to adjust NSS pulse to set HIGH a few microseconds later than TIM2 stops SPI transfer, to give a DAC some time to finish.
In CUBEMX its means to set :
Channel 1 - PWM generation on channel1
Channel 2 - PWM generation no output
Trigger TRGO parameters / trigger events select: OC2REF
 
Now TIM2:
Slave Mode - Gated mode
Trigger source - page 632  / 1749  doc- RM0090 Rev 18 table 98 - ITR0, seens TIM1 should be a gate master.
Clock source - internal.

Next - Counter period, obviously TIM2 needs 3x speed compare to TIM1, so if Counter TIM1 = 17'999 ( 10 kHz sharp ) than Counter TIM2 = 5'999

One PWM channel.

Quote
I assume you did mean this?

Code: [Select]
void TIM2_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim2);

  HAL_SPI_Transmit_DMA(&hspi1, &data, 3);
  i+=3;
}

No, this is exactly what I'm advising not to use - interrupt driven transfer.
Should be:

Code: [Select]
  if (HAL_DMA_Start_IT(htim2.hdma[TIM_DMA_ID_UPDATE], (uint32_t) out, SPI2_Write, (2 *OUT_BUFF)) != HAL_OK)
  {
    Error_Handler();
  }


Hi Master T

Thank you again for the help with configuration. I have spent some time reading and trying to succeed with a test program based on your method but have not had success so far, there is no output on the SPI GPIO. The TIM1CH1 and TIM2CH1 GPIO pins show output on a scope.

I believe the program should send the test value over SPI on TIM2 match, then sit in

void DMATransferComplete(DMA_HandleTypeDef *hdma)   
{
}


When debugging inside HAL_DMA_Start_IT, I see that it never gets into the loop

if(HAL_DMA_STATE_READY == hdma->State)
{
...
}


even though HAL_DMA_Init contains the line

hdma->State = HAL_DMA_STATE_READY;

I assume this is causing problems but there may also be other areas where I have configured incorrectly. I have attached images of timer configuration based on your previous post, DMA and NVIC config. The code below is my test program, I've also included HAL_TIM_Base_MspInit containing DMA configuration.
Please let me know if there is something missing in the code or configured incorrectly, I think it should be close to working.

Many thanks

Matt

Code: [Select]
#include "main.h"

SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
DMA_HandleTypeDef hdma_tim2_ch1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM2_Init(void);

void DMATransferComplete(DMA_HandleTypeDef *hdma);

int main(void)
{
  HAL_Init();

  SystemClock_Config();
 
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
   
//  HAL_DMA_Init(&hdma_tim2_ch1); //already called in HAL_TIM_Base_MspInit

  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
 
  uint16_t test = 14700;

  HAL_DMA_RegisterCallback(&hdma_tim2_ch1, HAL_DMA_XFER_CPLT_CB_ID,&DMATransferComplete);
 
  __HAL_SPI_ENABLE(&hspi1);
//  __HAL_TIM_DISABLE (& htim2);                                     
//  __HAL_TIM_DISABLE_DMA (& htim2, TIM_DMA_UPDATE); 
   HAL_DMA_Start_IT (htim2.hdma [TIM_DMA_ID_UPDATE], (uint32_t)&test, (uint32_t)&hspi1.Instance->DR, 1);
 
 __HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_CC1);
 
  TIM_CCxChannelCmd(htim2.Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); // tried this and one below
//  __HAL_TIM_ENABLE_DMA (&htim2, TIM_DMA_UPDATE);
 
  __HAL_TIM_ENABLE (&htim2);
 

 while(1)
 {
 }

}


void DMATransferComplete(DMA_HandleTypeDef *hdma)
{
}


static void MX_DMA_Init(void)
{
  __HAL_RCC_DMA1_CLK_ENABLE();

  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);

}



Code: [Select]
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
  if(htim_base->Instance==TIM1)
  {
    __HAL_RCC_TIM1_CLK_ENABLE();
  }
  else if(htim_base->Instance==TIM2)
  {
    __HAL_RCC_TIM2_CLK_ENABLE();

    hdma_tim2_ch1.Instance = DMA1_Stream5;
    hdma_tim2_ch1.Init.Channel = DMA_CHANNEL_3;
    hdma_tim2_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim2_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim2_ch1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim2_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_tim2_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_tim2_ch1.Init.Mode = DMA_NORMAL;
    hdma_tim2_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_tim2_ch1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_tim2_ch1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_CC1],hdma_tim2_ch1);

    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  }

}
 

Offline matt09Topic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: gb
Re: I2S to SPI DAC with STM32F429
« Reply #26 on: September 03, 2020, 04:44:02 pm »
Is anyone else familiar with HAL_DMA_Start_IT able to see why the function call is failing in the IF statement?

if(HAL_DMA_STATE_READY == hdma->State)
{
...
}

Thanks
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf