Error al generar un retraso de 1 segundo usando temporizadores en PIC32

Tengo un PIC32MX795F512ly porque XC32no proporciona una función de retraso incorporada, estoy usando Timer1para generar un retraso de 1 segundo pero hay un problema porque está generando más de 1 segundo de retraso. ¿Alguien puede ayudar a obtener un retraso exacto de 1 segundo en PIC32?

CÓDIGO:

#define SYSTEM_FREQUENCY        72000000L
void Delayms(unsigned t)
{
    OpenTimer1(T1_ON | T1_PS_1_256, 0xFFFF);
    while(t--)
    {
        WriteTimer1(0);
        while(ReadTimer1() < SYSTEM_FREQUENCY/256/1000);
    }
    CloseTimer1();
}

y usarlo en while(1)

int main()
{
 SYSTEMConfigPerformance(SYSTEM_FREQUENCY);
while(1)
  {
    PORTDbits.RD0 = 1;
    Delayms(1000);
    PORTDbits.RD0 = 0;
    Delayms(1000);

  }
 }
No haga algo como SYSTEM_FREQUENCY/256/1000, use paréntesis para que sea más legible.
¿Cuánto más que un segundo? ¿Un milisegundo? ¿Dos segundos?
son más de 10 segundos
¿Estás seguro de que tu temporizador funciona a 72 MHz? Si funciona con los 8 MHz internos, esperará 9 veces más (cerca de los 10 segundos)
¿Cómo puedo verificar si está usando interno o ext. y si está usando interno, entonces cómo configurarlo para externo
Si no realiza ninguna inicialización del sistema de reloj en su código, se establecerá de forma predeterminada en el FRC de 8 MHz, que también se divide en 2, por lo que se ejecuta en 4 MHz. Tienes que mostrarnos más código.
Edité mi código e incluí SYSTEMConfigPerformance(SYSTEM_FREQUENCY); y este es el código que estoy usando.

Respuestas (5)

Finalmente diseñé una lógica usando temporizadores que me está dando un retraso de 1 ms:

#define FCY 72000000L
#define FPB 36000000L
#pragma config POSCMOD=XT, FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF

void Delayms( unsigned t)
{
   T1CON = 0x8000; 
   while (t--)
   { 
      TMR1 = 0;
       while (TMR1 < FPB/1000);
   }
}

No estoy familiarizado con los dispositivos PIC32 y la biblioteca proporcionada por microchip, pero por lo que leí en la guía de la biblioteca periférica, la llamada SYSTEMConfigPerformance(SYSTEM_FREQUENCY);no establece los relojes reales en 72 MHz, sino que solo selecciona todas las demás características importantes para brindar el máximo rendimiento para 72 MHz ( por ejemplo, estados de espera, cachés, reloj periférico antes del divisor).

Entonces, en su código, la MCU se ejecutará con la configuración de reinicio predeterminada que es (si entiendo correctamente) un reloj FRC interno de 8MHz con un divisor de 2, por lo tanto, 4MHz. Puede intentar verificar esto si lo define SYSTEM_FREQUENCYy 4000000Lver si obtiene un retraso de 1 segundo. (actualmente debería ser 18 segundos en lugar de 1)

Si no me equivoco, y realmente desea que su dispositivo funcione a 72 MHz, primero debe configurar sus osciladores:

OSCConfig(OSC_FRC_PLL, OSC_PLL_MULT_18, OSC_PLL_POST_1, OSC_FRC_DIV_2);

Tenga en cuenta que la frecuencia de entrada del PLL no debe exceder los 5 MHz (si lo hice bien), por lo que usará el FRC de 8 MHz, divídalo por 2 ( OSC_FRC_DIV_2), introdúzcalo en el PLL ( OSC_FRC_PLL) y multiplíquelo por 18 ( OSC_PLL_MULT_18) sin divisor posterior ( OSC_PLL_POST_1). Con un resultado de 72MHz +/- 2% a 25°C (ya que el FRC está calibrado de esa manera).

Como realmente no estoy familiarizado, verifique dos veces esas cosas y no me haga responsable si mata su chip, la primera sugerencia (definir la frecuencia del sistema más baja) debería ser segura.

Usted dijo lo PLL input frequency should not exceed 5 MHzque es correcto y la hoja de datos también describió que debería estar entre 4 MHz<FIN<5 MHz, así que digamos que si tengo un oscilador de 11 MHz, sumergirlo en 2 dará 5.5más de 5 MHz y si lo dividimos entre 3, dará 3.6lo que está debajo que 4MHZ. Entonces, según usted, será una buena configuración para esto. Lo estoy buceando a las 3 y funciona bien, pero solo quiero confirmarlo.
@CZAbhinav bueno, está fuera de especificación de cualquier manera, pero es menos probable que la reducción de la frecuencia rompa las cosas que el overclocking de los circuitos. Así que probablemente elegiría dividir por 3 también, si no hay otra fuente disponible. Otro enfoque es usar un reloj RC interno y recortarlo (si es posible) con un oscilador externo en intervalos regulares para mantener la frecuencia más o menos constante.

Espero que esto ayude.

#define CCLK (80000000L)        // system clock              
#define PBCLK (CCLK / 2)        // peripheral bus clock      
#define CCLK_MS (PBCLK / 1000)  // used for millisecond delay

void delay_ms(const int32_t& wait_ms) {            
  auto startTime  = ReadCoreTimer();               
  auto delayCount = wait_ms * CCLK_MS;             
  while (ReadCoreTimer() - startTime < delayCount) 
    ;                                              
} 

Si no puede pagar llamadas de función a ReadCoreTimer(), use _CP0_GET_COUNT() en su lugar. Es una macro dentro de las bibliotecas plib.

No soy un programador de PIC, pero estoy seguro de que la demora se debe a:

  1. 1000 bucles al generar 1 segundo de retraso (disminución de la variable t, comparación, salto, etc.)
  2. Tiempo para abrir y cerrar el temporizador.

Puedes hacer algunos experimentos (como hice en AVR o MCS-51):

  1. Cree una función para retrasar un segundo, llámela delay_s. Puede ser delay_ms(1000)
  2. Ejecute delay_s(1000). Usa tu cronómetro (muchos smartphones lo tienen) para medir la duración requerida en segundos. Registre esta duración como T. Para el primer experimento, T debe ser alrededor de 1000 (>1000) pero no exactamente 1000

  3. Reemplace SYSTEM_FREQUENCY/256/1000 en su código con SYSTEM_FREQUENCY/256/T

  4. Repita los pasos 2 y 3 con T variable (si es necesario) para obtener un cronómetro más exacto.
Me resulta difícil imaginar que una MCU que se ejecuta a 72MHz tomará 10 veces el tiempo previsto (10 segundos en lugar de 1) solo por la apertura/cierre de un módulo de temporizador y algunos pequeños cálculos.
@Arsenal, sí. Puede deberse a una configuración incorrecta del fusible del programador (utilizando accidentalmente el reloj interno) o un defecto en el hardware (resonador o condensador). Mi método funcionará si se han solucionado todos los problemas de reloj y hardware.

Si el retraso total es un poco más de 1 segundo, es simplemente que el tiempo adicional se toma realizando el ciclo calculado 1000 veces. ¿No podrías calcular el número exacto de tics de reloj durante 1 segundo y tener un solo ciclo?

Después de que su actualización indique que está demorando más de 10 segundos, le sugiero que verifique que el reloj esté funcionando a la velocidad que cree.

Está calculando los ticks del reloj (después del prescaler) para 1 ms - SYSTEM_FREQUENCY/256/1000, multiplíquelo por 1000 para dar ticks de 1 s, entonces SYSTEM_FREQUENCY/256