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.
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:
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
#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);
}
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);
}
}