Breve descripción:
El temporizador activa DMA con la velocidad deseada, DMA escribe datos en el registro de salida GPIO.
Descripción larga:
- Prepare el estado de salida del puerto GPIO seleccionado al estado predeterminado bajo / alto
- Configure el puerto GPIO seleccionado PX para que salga push-pull / drenaje abierto
- Configure cualquier temporizador para el período deseado de actualización del puerto GPIO
- Configurar DMA seleccionado y vincularlo a TIM seleccionado
- Configure las devoluciones de llamada para las IRQ de DMA: HT, TC, ERR
- Habilite DMA para escribir su búfer de datos, la longitud del búfer a PX- > ODR seleccionado
- Habilite TIM para generar eventos DMA
- Ejecutar TIM
- Maneje el estado DMA en las devoluciones de llamada y controle el TIM según lo necesite
Código en blanco:
Todo el código escrito aquí y no probado, puede contener contenido simple
errores como el uso de variables en lugar de punteros en macros HAL o
funciones llamadas.
GPIO_InitTypeDef GPIO_InitStruct;
TIM_HandleTypeDef htim1;
DMA_HandleTypeDef hdma_tim1_uev;
/* 1 (Port GPIOA) */
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_All, GPIO_PIN_RESET);
/* 2 (Port GPIOA) */
GPIO_InitStruct.Pin = GPIO_PIN_All;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* 3 (Timer TIM1) */
__HAL_RCC_TIM1_CLK_ENABLE();
htim1.Instance = TIM1;
htim1.Init.Prescaler = DESIRED_PRESCALER;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = DESIRED_PERIOD;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim1)
/* 4 (DMA1 Channel2) */
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_tim1_uev.Instance = DMA1_Channel2;
hdma_tim1_uev.Init.Direction = DMA_MEMORY_TO_PERIF;
hdma_tim1_uev.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_uev.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_uev.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 16 bits
hdma_tim1_uev.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_tim1_uev.Init.Mode = DMA_NORMAL;
hdma_tim1_uev.Init.Priority = DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_tim1_uev);
__HAL_DMA1_REMAP(HAL_DMA1_CH2_TIM1_UP);
__HAL_LINKDMA(&htim1,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_uev);
HAL_NVIC_SetPriority(DMA1_Ch2_3_DMA2_Ch1_2_IRQn, 0, 0); // enable DMA IRQ
HAL_NVIC_EnableIRQ(DMA1_Ch2_3_DMA2_Ch1_2_IRQn);
/* 5 (Callbacks for DMA IRQs) */
htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = data_tramsmitted_handler;
htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = transmit_error_handler;
/* 6 (Enable DMA) */
HAL_DMA_Start_IT(htim1.hdma[TIM_DMA_ID_UPDATE],(uint32_t)&my_data_buf,
(uint32_t)&GPIOA->ODR, my_data_buf_length);
/* 7 (Enable TIM for DMA events) */
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
/* 8 (Run TIM) */
__HAL_TIM_ENABLE(&htim1);
/* 9 (DMA IRQ callbacks) */
void data_tramsmitted_handler(DMA_HandleTypeDef *hdma)
{
/* Stop timer */
__HAL_TIM_DISABLE(&htim1);
/* Reconfigure DMA */
HAL_DMA_Start_IT(htim1.hdma[TIM_DMA_ID_UPDATE],(uint32_t)&my_data_buf,
(uint32_t)&GPIOA, my_data_buf_length);
/* Start timer for new data transmit */
__HAL_TIM_ENABLE(&htim1);
}
void transmit_error_handler(DMA_HandleTypeDef *hdma)
{
/* Stop timer */
__HAL_TIM_DISABLE(&htim1);
/* Some error handle ? */
}