2022-07-21 11:13 PM
I try to use TIM_DMABurst to generate exact number of pwm pulses.
But I found after call HAL_TIM_DMABurst_WriteStart and HAL_TIM_PWM_Start, it enter HAL_TIM_PeriodElapsedCallback. And then if I call HAL_TIM_PWM_Stop it will stop and generate no pwm. If I call HAL_TIM_DMABurst_WriteStop and HAL_TIM_DMABurst_WriteStart it will continue generate PWM but the wave is wrong
2022-07-21 11:17 PM
TIM_HandleTypeDef htim1;
DMA_HandleTypeDef hdma_tim1_up;
static uint32_t g_irq_cnt = 0;
static uint32_t aSRC_Buffer[3];
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
aSRC_Buffer[0] = 7200 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
HAL_TIM_DMABurst_WriteStart(&htim1, TIM_DMABASE_ARR, TIM_DMA_UPDATE, aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// HAL_TIM_GenerateEvent(&htim1, TIM_EVENTSOURCE_UPDATE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM7 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
if (htim->Instance == TIM1) {
++g_irq_cnt;
if (g_irq_cnt == 1) {
aSRC_Buffer[0] = 3600 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
} else if (g_irq_cnt == 2) {
aSRC_Buffer[0] = 1800 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.4; /* CCR1 */
} else if (g_irq_cnt == 3) {
aSRC_Buffer[0] = 900 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.6; /* CCR1 */
}
HAL_TIM_DMABurst_WriteStop(&htim1, TIM_DMA_UPDATE);
// htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
HAL_TIM_DMABurst_WriteStart(&htim1, TIM_DMABASE_ARR, TIM_DMA_UPDATE, aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
if (g_irq_cnt >= 6) {
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
}
}
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 100 - 1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
/**
* @brief TIM_Base MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 DMA Init */
/* TIM1_UP Init */
hdma_tim1_up.Instance = DMA1_Channel5;
hdma_tim1_up.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim1_up.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_up.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_tim1_up.Init.Mode = DMA_NORMAL;
hdma_tim1_up.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);
/* TIM1 interrupt Init */
HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM1_MspPostInit 1 */
}
}
2022-07-21 11:23 PM
The core like this
First start TIM_DMABrust with
aSRC_Buffer[0] = 7200 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
and then in the HAL_TIM_PeriodElapsedCallback change aSRC_Buffer
if (g_irq_cnt == 1) {
aSRC_Buffer[0] = 3600 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
} else if (g_irq_cnt == 2) {
aSRC_Buffer[0] = 1800 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.4; /* CCR1 */
} else if (g_irq_cnt == 3) {
aSRC_Buffer[0] = 900 - 1; /* ARR */
aSRC_Buffer[1] = 7 - 1; /* RCR */
aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.6; /* CCR1 */
}
but i get pluss like that
and in the end it will generate a very small pluse
2022-07-22 01:11 AM
Which STM32?
> and then in the HAL_TIM_PeriodElapsedCallback change aSRC_Buffer
But why?
The point of DMA is, that it works without your intervention. So just define a long enough buffer to hold all the changes, and run the DMA and you're done. A nice trick to stop is to add one more set at the end, where ARR=0.
JW
2022-07-22 02:36 AM
stm32f103
I use this timer to driver a step motor so it must be stop at the target point. Amd the problem is the wave generate by mcu is wrong. Use dmamultiwrite do not fix.
2022-07-22 02:40 AM
Once you call 'dma write start' you will find the pwm will not stop and you can ' dma write start' again before use 'dma write stop'.