STM32 - [DMA] memoria de tabla sinusoidal a TIM-CCRx

0

Uso la placa STM32F031 y soy un principiante.

Quiero copiar los valores de la tabla sinusoidal directamente en el periférico TIM- > CCRx. Uso 2 temporizadores, uno para generar PWM y el otro como captura de salida para generar eventos. Para generar PWM para el control del motor, uso 3 punteros a una tabla sinusoidal (distancia constante entre ellos. 1/3 cada uno) y en cada evento del temporizador copio los valores de la tabla en la memoria en los registros CCR1 / 2/3 del temporizador . Este proceso lleva mucho tiempo debido a la interrupción generada y la entrada a la función TIMx_IRQHandler () (que copia los valores de la tabla a los registros). Quiero ahorrar tiempo a la CPU sin molestarme en copiar estos valores en cada evento del temporizador. Y lo más importante es no ingresar un IRQHandler () con la CPU (para ahorrar tiempo de "cambio de contexto", etc.) ¿Cómo puedo configurar el DMA y el TIMx (evento generador) para que el temporizador genere de forma independiente un evento para que el DMA copie el valor de uint32_t sine_table[LENGTH_OF_TABLE] al periférico TIMx->CCRy ?

Mi código en este momento es el siguiente:

void init_dma1_ch1(void){

DMA_InitTypeDef_USR DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);      // Enable DMA1 clock

DMA_DeInit(DMA1_Channel1);                              // Reset DMA1 channe1 to default values;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;            // M2M Disabled- Peripheral mode (requires timer trigger)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;         // Circular mode
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; // High priority
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;      // Memory to Peripheral

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16-bit Register
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            // Always write to same register
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR1;           // Output data for GPIO

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         // 16-bit array
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     // Increment through array
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&sine_wave;                 // 16-bit Source data

DMA_InitStructure.DMA_BufferSize = PWM_BUFFER_SIZE / 3;           // Size of source array

DMA_Init_USR(DMA1_Channel2, &DMA_InitStructure);            // Initialize DMA

//Enable DMA1 channel IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

// Enable DMA1 Channel Transfer Complete interrupt
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); }

(Para los otros dos valores, uso los mismos parámetros, excepto que uso otro canal de DMA , por ejemplo, DMA1_Channel2 DMA1_Channel3 en lugar de Channel1. ¿Es correcto?)

El temporizador se configura de la siguiente manera (temporizador de evento de generación):

void TIM14_Init(void) {

//Clock enable: TIM14
RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;

TIM14->CR1 |= TIM_CR1_ARPE;

TIM14->PSC = TIM14_PWM_PSC_VALUE; 

TIM14->RCR = TIM14_PWM_REPETITION_VALUE; 


///Update interrupt enable
TIM14->DIER |= TIM_DIER_UIE;

//TIM auto-reload register
TIM14->ARR = TIM1->ARR; 

//Counter enable
TIM14->CR1   |= TIM_CR1_CEN; 

NVIC_SetPriority(TIM14_IRQn, 3);
NVIC_EnableIRQ(TIM14_IRQn); }

Y el IRQHandler (lo que lleva tiempo de CPU en este momento):

void TIM14_IRQHandler (void){

update_motors_tim_ccr_from_table();
//Reset flag
TIM14->SR &= ~TIM14->SR; }
    
pregunta user135713

0 respuestas

Lea otras preguntas en las etiquetas