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);
}