Microcontrolador serie STM32 - Cálculos de variables de temporizador

6

Este es un tema que parece tener mucha confusión (no entiendo completamente). Cómo calcular las variables:

  • período
  • Prescaler
  • Duración

si solo se conocen algunas otras variables. A frecuencias más altas, por ejemplo, funcionan reglas simples de 1000000Hz. A frecuencias más bajas, como 1281Hz, las cosas se complican un poco más.

Como ejemplo: si buscamos una frecuencia de salida de 1281Hz, debemos configurar el Registro ARR en: 32785. Necesitamos configurar el Registro PSC en: 3 y si queremos un Ciclo de Duty del 50%, necesitamos establezca el Registro CCRx en: 16393. Donde la x en CCRx es el canal especificado que se va a usar. 1, 2, 3 o 4.

Los registros necesitan ver valores de 16 BIT, valores enteros (65535 o menos).

Las ecuaciones existen para que se puedan hacer cálculos, por ejemplo:

\ $ TIM_ {Frecuencia de actualización (Hz)} = \ frac {Reloj} {(PSC - 1) * (Periodo - 1)} \ $

\ $ 1281.11273792094 = \ frac {84000000} {3 * 32785} \ $

ahora, el problema se vuelve más complicado, para una frecuencia deseada de 840Hz:

\ $ 425.946209078739 = \ frac {84000000} {167 * 1189} \ $

Aquí está el problema, ¿cómo se encuentra el valor de PSC cuando se conocen solo los valores de "Reloj" y "Período"? El valor "TIM_Update_Frequency (Hz)" no siempre es la frecuencia deseada real.

Deben existir otras ecuaciones para calcular el valor de "PSC", o para calcular la "frecuencia de frecuencia de TIM (Up) (Hz)" para deducir los otros valores.

El trabajo de adivinar no es un enfoque lógico aquí.

¿Puede alguien ayudar con más ecuaciones para resolver las otras variables?

Gracias

Chris

    
pregunta Rusty Nail

2 respuestas

1

He eliminado mi última respuesta porque no era correcta todo el tiempo. He logrado usar esta ecuación para obtener resultados correctos:

Prescaler = ((((ClockSpeed) / ((period) / (1 / frequency))) + 0.5) - 1);

Los números de factoraje no fueron la respuesta.

Este es un método simple que ahora estoy usando para calcular las otras variables, Período y Duración.

private void CalculateVariables()
    {
        // Set the Bus Speed (APB1 or APB2), all timers are APB1 except TIM1 and TIM8...
        if (PWMPin == CPU.Pin.Pin7_X3 || PWMPin == CPU.Pin.Pin9_X3 || PWMPin == CPU.Pin.Pin7_X4)
        {
            ClockSpeed = CPU.Clock.APB2;
        }
        else
        {
            ClockSpeed = CPU.Clock.APB1;
        }

        #region Fields...

        uint ONE_MHZ = 1000000;

        uint prescaler = 0;
        uint period = m_period;
        uint duration = m_duration;
        uint scale = ((uint)m_scale);

        // Scale in MHz... 
        uint scaleMHz = scale / ONE_MHZ;

        uint clk = ((uint)ClockSpeed / ONE_MHZ);

        if (duration > period) duration = period;

        #endregion

        #region Calculate Variables (This is a C# implimentation of GHI Source ("PWM_ApplyConfiguration"))...

        prescaler = clk / scale;

        if (prescaler == 0)
        {
            if (period > (0xFFFFFFFF / clk))
            {
                // Avoid Overflow... 
                prescaler = clk;
                period /= scaleMHz;
                duration /= scaleMHz;
            }
            else
            {
                prescaler = 1;
                period = period * clk / scaleMHz;
                duration = duration * clk / scaleMHz;
            }
        }
        else
        {
            while (prescaler > 0x10000)
            {
                // Prescaler too Large... 
                if (period >= 0x80000000) break;
                prescaler >>= 1;
                period <<= 1;
                duration <<= 1;
            }
        }

        bool TimerIs16Bit = true;

        // Were not using Timer 2 of Timer 5...
        if (TimerIs16Bit)
        {
            // All Timers are 16 bit Timer's except 2 and 5... 
            while (period >= 0x10000)
            {
                // period too large 
                if (prescaler > 0x8000) break;
                prescaler <<= 1;
                period >>= 1;
                duration >>= 1;
            }
        }

        #endregion

        if (debug)
        {
            Debug.Print("*** Scale *******");
            // Print to Debug window new config...
            Debug.Print("Period = " + period);
            Debug.Print("Prescaler = " + PrescalerFromPeriodFrequencyAndClock(period, this.Frequency));
            Debug.Print("Duration = " + duration);
        }

        ARRValue = (period - 1);
        PSCValue = PrescalerFromPeriodFrequencyAndClock(period, this.Frequency);
        CCRxValue = duration;
    }

una CPU de clase estática simple y he agregado:

public enum Pin : int
    {
        Pin7_X3 = 1,
        Pin8_X3 = 2,
        Pin9_X3 = 3,
        Pin7_X4 = 4,
        Pin8_X4 = 5,
        Pin9_X4 = 6
    }
    
respondido por el Rusty Nail
2

Según el reloj, el prescaler y la recarga automática, los parámetros del contador de repetición (si están presentes), el temporizador de 16 bits puede generar un evento de actualización de un nanosegundo a unos pocos minutos.

Por ejemplo, para generar un evento dos veces por segundo, elija Frecuencia de reloj (TIM_CLK) = 168 Mhz, Prescalar (PSC) = 16799, Periodo (ARR) = 4999, contador de repetición (RCR) = 0,

entonces el temporizador de 16 bits generará un evento dos veces por segundo.

Paramásinformación;

Descripción general del temporizador STM32

    
respondido por el Purgoufr

Lea otras preguntas en las etiquetas