Actualmente estoy intentando adaptar el proyecto de ejemplo TIM_DMA de F769I_EVAL al tablero de descubrimiento STM32F746G. Soy bastante nuevo en STM32 y esto podría ser un error obvio.
El código crea un temporizador y lo configura con DMA.
Lo cambié para usar TIM2 en el pin PB_8 y para usar DMA2 (Transmisión 0) en lugar de DMA1 (he leído en algún lugar en la documentación que DMA1 es principalmente para memoria a memoria)
La generación de la señal PWM funciona, pero permanece en el primer valor (75% de ciclo de trabajo). No sé por qué ese es el caso.
Mi configuración es
#define TIMx TIM4
#define TIMx_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE
#define DMAx_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE
#define TIMx_CHANNEL3_GPIO_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
#define TIMx_GPIO_CHANNEL3_PORT GPIOB
#define GPIO_PIN_CHANNEL3 GPIO_PIN_8
#define GPIO_AF_TIMx GPIO_AF2_TIM4
#define TIMx_CC3_DMA_INST DMA2_Stream0
#define TIMx_DMA_IRQn DMA2_Stream0_IRQn
#define TIMx_DMA_IRQHandler DMA2_Stream0_IRQHandler
mi función principal
int main(void) {
CPU_CACHE_Enable();
HAL_Init();
SystemClock_Config();
BSP_LED_Init(LED1);
uwTimerPeriod = (uint32_t)(((SystemCoreClock/2) / 17570) - 1);
aCCValue_Buffer[0] = (uint32_t)(((uint32_t) 75 * (uwTimerPeriod - 1)) / 100);
aCCValue_Buffer[1] = (uint32_t)(((uint32_t) 50 * (uwTimerPeriod - 1)) / 100);
aCCValue_Buffer[2] = (uint32_t)(((uint32_t) 25 * (uwTimerPeriod - 1)) / 100);
/*-1- Configure the TIM peripheral */
TimHandle.Instance = TIMx;
TimHandle.Init.Period = uwTimerPeriod;
TimHandle.Init.RepetitionCounter = 3;
TimHandle.Init.Prescaler = 0;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
Error_Handler();
}
/*-2- Configure the PWM channel 3 */
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.Pulse = aCCValue_Buffer[0];
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK) {
Error_Handler();
}
/*-3- Start PWM signal generation in DMA mode */
if (HAL_TIM_PWM_Start_DMA(&TimHandle, TIM_CHANNEL_3, aCCValue_Buffer, 3) != HAL_OK) {
Error_Handler();
}
while (1) {
}
}
la función de interrupción
void TIMx_DMA_IRQHandler(void) {
HAL_DMA_IRQHandler(TimHandle.hdma[TIM_DMA_ID_CC3]);
}
y la función de inicialización PWM MSP
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) {
GPIO_InitTypeDef GPIO_InitStruct;
static DMA_HandleTypeDef hdma_tim;
/*-1- Enable peripherals and GPIO Clocks */
TIMx_CLK_ENABLE();
TIMx_CHANNEL3_GPIO_CLK_ENABLE();
DMAx_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_CHANNEL3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF_TIMx;
HAL_GPIO_Init(TIMx_GPIO_CHANNEL3_PORT, &GPIO_InitStruct);
hdma_tim.Init.Channel = DMA_CHANNEL_3;
hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;
hdma_tim.Init.Mode = DMA_CIRCULAR;
hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_tim.Instance = TIMx_CC3_DMA_INST;
__HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC3], hdma_tim);
/* Initialize TIMx DMA handle */
if(HAL_DMA_Init(htim->hdma[TIM_DMA_ID_CC3]) != HAL_OK) {
Error_Handler();
}
/*-2- Configure the NVIC for DMA */
HAL_NVIC_SetPriority(TIMx_DMA_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_DMA_IRQn);
}
La salida se ve así:
¿Qué es exactamente lo que me estoy perdiendo? ¿El TIM4 no funciona con el DMA2 o tengo que usar controladores específicos de Interrupción?