Stm32 C: arranque del motor paso a paso después de 1 minuto

0

Escribí un controlador de motor paso a paso con el uso de DMA y TIM1. Acelero la señal utilizando las llamadas rampas. Calculo los tiempos, los cargo en la tabla DMA y los paso al valor TIM PERIOD. El programa funciona como debería (acelera y frena con el principio de la rampa), pero me preocupa por qué el temporizador comienza a funcionar solo después de 1 minuto. Sospecho que esto se debe a los cálculos porque si los valores aleatorios se cargan sin estos valores, funciona de inmediato. ¿Puedo hacer que este demonio de velocidad ejecute TIMER un poco más rápido? ¿No haré nada? Para aquellos interesados, pego el código.

#include "stm32f10x.h"
#include "stm32f1xx_nucleo.h"
#include "stm32f10x.h"

#include <math.h>

int i = 0;

//============Dane==========
float vMin = 1.0;
float vMax = 10.0;

int accelerationTime = 10;
int decelerationTime = 10;

volatile int totalSteps = 100;
volatile int currentStep = 0;
//============Szukane==========
float accelerationPerMs = 0;
float decelerationPerMs = 0;

int stepsAcceleration = 0;
int stepsDeceleration = 0;

//============================
float currentSpeed = 0.0;
int period = 0;
u16 PWM_Buf[100];

void TIMInit(void);
void GPIOInit(void);
void DMAInit(void);
void PWMInit(void);
void generateSignal(int totalSteps, float vMin, float vMax,int accelerationTime, int decelerationTime);

int main(void) {
        GPIOInit();
        TIMInit();
        DMAInit();
        PWMInit();
        generateSignal(totalSteps,vMin,vMax,accelerationTime,decelerationTime);

        while (1) {
        }
}
void generateSignal(int totalSteps, float vMin, float vMax,int accelerationTime, int decelerationTime) {

                accelerationPerMs = (vMax - vMin) / (accelerationTime);
                decelerationPerMs = (vMax - vMin) / (decelerationTime);

                stepsAcceleration = ceil(((vMin * accelerationTime) +
                                (accelerationPerMs * (accelerationTime * accelerationTime)) / 2));
                stepsDeceleration = ceil(((vMin * decelerationTime) +
                                (decelerationPerMs * (decelerationTime * decelerationTime)) / 2));

                if (totalSteps <= stepsAcceleration + stepsDeceleration)
                        totalSteps = stepsAcceleration + stepsDeceleration + 1;
                for (currentStep = 0; i < totalSteps; currentStep++){
                        if(currentStep == 0)
                                currentSpeed = vMin;
                        else if(currentStep < stepsAcceleration)
                                currentSpeed += accelerationPerMs;
                        else if(currentStep >= stepsAcceleration)
                                currentSpeed = vMax;
                        else if(currentStep >= totalSteps - stepsDeceleration)
                                currentSpeed -= decelerationPerMs - 1;
                        period = 1000/currentSpeed;
                        PWM_Buf[currentStep] = period;
                }
}
void TIMInit(void) {
        TIM_TimeBaseInitTypeDef TIMInit;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

        //TIMInit.TIM_Period = 1000 - 1;
        TIMInit.TIM_Prescaler = 64000 - 1;
        TIMInit.TIM_ClockDivision = TIM_CKD_DIV1;
        TIMInit.TIM_CounterMode = TIM_CounterMode_Up;
        TIMInit.TIM_RepetitionCounter = 0;

        TIM_TimeBaseInit(TIM1, &TIMInit);
}

void GPIOInit(void) {
        GPIO_InitTypeDef GPIOInit;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

        GPIOInit.GPIO_Pin = GPIO_Pin_8;
        GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;

        GPIO_Init(GPIOA, &GPIOInit);
}

void DMAInit(void) {

        DMA_InitTypeDef DMAInit;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        DMA_DeInit(DMA1_Channel5);
        DMAInit.DMA_PeripheralBaseAddr = (u32)&TIM1 -> ARR;
        DMAInit.DMA_MemoryBaseAddr = (u32) PWM_Buf;
        DMAInit.DMA_DIR = DMA_DIR_PeripheralDST;
        DMAInit.DMA_BufferSize = totalSteps;
        DMAInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMAInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMAInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
        DMAInit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMAInit.DMA_Mode = DMA_Mode_Circular;
        DMAInit.DMA_Priority = DMA_Priority_High;
        DMAInit.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel5, &DMAInit);

        DMA_Cmd(DMA1_Channel5, ENABLE);
}

void PWMInit(void) {
        TIM_OCInitTypeDef PWMInit;

        PWMInit.TIM_OCMode = TIM_OCMode_PWM1;
        PWMInit.TIM_OutputState = TIM_OutputState_Enable;
        PWMInit.TIM_Pulse = 30;
        PWMInit.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OC1Init(TIM1, &PWMInit);
        //TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
        //TIM_ARRPreloadConfig(TIM1, ENABLE);
        TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
        TIM_Cmd(TIM1, ENABLE);
        TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
    
pregunta Member Cicada

1 respuesta

0

Los registros se almacenan en búfer o están sombreados (y se actualizan en el evento UP), por lo que la primera actualización ocurre cuando el contador obtiene su valor máximo (y toma un minuto)

Necesita generar el evento UG usted mismo. Es fácil de archivar usando registros (solo escriba el bit UG en el registro EGR) pero tendrá que encontrar la forma de archivarlo en la HAL.

    
respondido por el P__J__

Lea otras preguntas en las etiquetas