In this example let's configure the DMA to configure transactions between RAM memory to PWM peripheral. This application must transfer a buffer that contains different duty cycles to change the intensity of an LED. DMA is configured to manage data of 32 bits in circular mode, the DMA request is configured and linked to the DMA.
#include "bsp.h"
#include <stdio.h>
extern void initialise_monitor_handles(void);
#define PWM_DATA 27 /* Size of the buffer */
DMA_HandleTypeDef DMAH; /* Handler to config DMA */
TIM_HandleTypeDef TimHandle; /* Handler to config timer of PWM */
TIM_OC_InitTypeDef sConfig; /* Handler to control PWM Channel */
TIM_MasterConfigTypeDef sMasterConfig; /* Handler to configure trigger to activate DMA */
/* Buffer that contain duty cycle of the PWM signal */
uint32_t PWMdata[ PWM_DATA ] =
{
20, 20, 20,
100, 100, 100,
300, 300, 300,
500, 500, 500,
800, 800, 800,
500, 500, 500,
300, 300, 300,
100, 100, 100,
20, 20, 20
};
int main( void )
{
HAL_Init(); /* Initilize HAL library */
initialise_monitor_handles();
printf("Hola semihosting\n\r");
DMAH.Instance = DMA1_Channel1; /* Configure DMA1 and channel 1 */
DMAH.Init.Request = DMA_REQUEST_TIM2_CH4; /* Configure request of the PWM signal */
DMAH.Init.Direction = DMA_MEMORY_TO_PERIPH; /* DMA direction from memory to peripheral (RAM to PWM)*/
DMAH.Init.MemInc = DMA_MINC_ENABLE; /* Increment mem address enable */
DMAH.Init.PeriphInc = DMA_PINC_DISABLE; /* Increment perph address disable */
DMAH.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; /* Word size configured to transmit data */
DMAH.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; /* Word size configured to transmit data */
DMAH.Init.Mode = DMA_CIRCULAR; /* DMA in circular mode to repeat the process */
DMAH.Init.Priority = DMA_PRIORITY_LOW; /* LOW priority selected */
HAL_DMA_Init( &DMAH );
__HAL_LINKDMA( &TimHandle, hdma[TIM_DMA_ID_CC4], DMAH ); /* Set the link between signal of timer and DMA to the request */
/* Time = 1 / (Tfrec / Preescaler / Period) */
/* Time = 1 / (16MHz / 1600 / 350 ) = 35ms */
TimHandle.Instance = TIM2; /* Tim 2 selected to use as PWM signal generator */
TimHandle.Init.Prescaler = 1600; /* Selection of prescaler */
TimHandle.Init.Period = 350; /* Selection of Period */
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; /* Counter Up mode */
HAL_TIM_PWM_Init( &TimHandle );
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; /* Set trigger event */
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; /* Master / Slave mode disable */
HAL_TIMEx_MasterConfigSynchronization( &TimHandle, &sMasterConfig );
sConfig.OCMode = TIM_OCMODE_PWM1; /* Specifies Tim2 mode as PWM1 */
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH; /* Set Output polarity in high */
sConfig.OCFastMode = TIM_OCFAST_DISABLE; /* Output compare disabled */
sConfig.Pulse = 0; /* Duty cycle by default set as 0% */
HAL_TIM_PWM_ConfigChannel( &TimHandle, &sConfig, TIM_CHANNEL_4 ); /* Initialize PWM channel on timer 2 */
HAL_TIM_PWM_Start_DMA( &TimHandle, TIM_CHANNEL_4, (uint32_t*)&PWMdata, PWM_DATA ); /* Init transaction to periph */
while(1)
{
}
}
msps.c
/*function called by HAL_TIM_PWM_Init to configure the slected pins as PWM outputs*/
void HAL_TIM_PWM_MspInit( TIM_HandleTypeDef *htim )
{
GPIO_InitTypeDef GPIO_InitStruct; /* Handle to configure GPIO pin */
__HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1 clock enable */
__TIM2_CLK_ENABLE(); /* TIM2 clock enable */
__GPIOC_CLK_ENABLE(); /* PortC clock enable */
GPIO_InitStruct.Pin = GPIO_PIN_7; /* pin C7 selection */
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /* configure Alternate function of pin */
GPIO_InitStruct.Pull = GPIO_PULLUP; /* configured as Pull up */
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO speed high */
GPIO_InitStruct.Alternate = GPIO_AF2_TIM2; /* Tim2 connected to pin */
HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );
}