¿Cómo calcular el período Timer1?

4

Estoy tratando de configurar el Temporizador 1 de una pic24h a 1 ms por cada tictac del temporizador pero parece que no soy capaz de obtener los cálculos para coincidir con mis resultados.

Tengo un oscilador externo de 20MHz (con una resistencia de 1M en paralelo para estabilidad) y creo que lo tengo habilitado con los siguientes bits de configuración establecidos en el código:

#pragma config FNOSC = PRIPLL           // Oscillator Mode (Primary Oscillator (XT, HS, EC) w/ PLL)
#pragma config IESO = ON                // Internal External Switch Over Mode (Start-up device with FRC, then automatically switch to user-selected oscillator source when ready)

Estoy alternando un pin y mirándolo en el visor para verificar mis cálculos. Pensé que el cálculo es el siguiente:

//  ms_per_tick = ((F_OSC / 2)/prescaler)^-1 * PR1
//                    = ((20MHz / 2) / 8)^-1 * 4200
//          NO= 1ms

bit un valor de PR1 = 4200 es lo más cercano que puedo llegar a un tick de 1 ms.

¿Qué me estoy perdiendo? ¿Cambia el PLL el valor de lo que creo que es F_OSC? ¿Hay alguna forma de validar F_OSC?

El ISR solo incrementa una variable y borra el indicador de interrupción. Aquí está el código de inicialización:

T1CONbits.TCKPS = 0b01;   // configure the timer prescaler to divide-by-8
T1CONbits.TCS = 0;        // do NOT use the external clock
PR1 = 4200;               // configure the timer period

// configure the Timer1 interrupt
_T1IF = 0;             // begin with the interrupt flag cleared
_T1IE = 1;             // enable the interrupt
T1CONbits.TON = 1;         // turn on timer1

Estoy empezando a aprender más sobre el PLL a través de algunos SFR:

CLKDIV is: 0x3040 (PLLPOST = 1, PLLPRE = 0)
PLLFBD is: 0x0030 (PLLDIV = 48)

También encontré esto en la página 16 de la hoja de datos:

  

"Si el PLL del dispositivo de destino está habilitado y configurado para el   dispositivo de arranque del oscilador, la frecuencia máxima de la fuente del oscilador   debe estar limitado a ≤8 MHz para el inicio con el PLL habilitado para cumplir   Con condiciones de arranque del dispositivo PLL. Esto significa que si el externo   La frecuencia del oscilador está fuera de este rango, la aplicación debe   Arranque primero en el modo FRC. La configuración predeterminada de PLL después de un POR   con una frecuencia de oscilador fuera de este rango violará la   Velocidad de funcionamiento del dispositivo. Una vez que el dispositivo se enciende, la aplicación   El firmware puede inicializar los SFRs PLL, CLKDIV y PLLDBF a un adecuado   y luego realice un cambio de reloj al reloj Oscillator + PLL   fuente. Tenga en cuenta que el cambio de reloj debe estar habilitado en el dispositivo   Palabra de configuración. "

Ahora, lo primero que ejecuto después de main es este código de ejemplo:

void ConfigureOscillator(void) {
  // Disable the Watch Dog Timer
  RCONbits.SWDTEN = 0;

  // When clock switch occurs switch to Prim Osc (HS, XT, EC)with PLL
  __builtin_write_OSCCONH(0x03);  // Set OSCCONH for clock switch
  __builtin_write_OSCCONL(0x01);  // Start clock switching

  // Wait for Clock switch to occur
  while(OSCCONbits.COSC != 0b011);

  // Wait for PLL to lock, if PLL is used
  while (OSCCONbits.LOCK != 1);
}
    
pregunta tarabyte

2 respuestas

1

Dos cosas para reconocer:

  1. el temporizador es un contador ascendente que interrumpe los desbordamientos en los cuales punto en el que debe volver a cargar el inicio del contador.
  2. la frecuencia es la salida del PLL si tiene uno configurado
= (f_osc / 4)^-1 * prescaler * (65535 - TMR1)
= (16MHz / 4)^-1 * 1 * (1000)
= 250us

Donde el temporizador se usa como un temporizador de 16 bits y TMR1 es el valor escrito en TMR1. Me gusta especificar la precarga como un número negativo porque es más intuitivo que ver algo como menos de UINT16_MAX:

#define TIMER1_TIME  (-1000)

void InitTimer1(void) {
  T1CONbits.T1CKPS = 0b00;              // Prescaler is divide-by-1
  T1CONbits.TMR1CS = 0b00;              // Clock source is (f_osc / 4)
  TMR1H = TIMER1_TIME >> 8;             // Load the start of the upcounter
  TMR1L = TIMER1_TIME & 0xFF;
  IPR1bits.TMR1IP = 1;                  // Set to high priority
  PIR1bits.TMR1IF = 0;                  // Clear interrupt flag
  PIE1bits.TMR1IE = 1;                  // Enable interrupt
  T1CONbits.TMR1ON = 1;                 // Turn on the the timer
}

void MyIsr(void) {
  // Reload the start of the upcounter
  TMR1H = TIMER1_TIME >> 8;
  TMR1L = TIMER1_TIME & 0xFF;
}
    
respondido por el tarabyte
0

El timer0 es un temporizador de 16bits, así que puedes configurar para interrumpir cada 1 segundo que necesitas configurar:

- Prescaler @ 128

- TMR0 Precarga @ 26474

La ecuación:

\ $ T = \ left (\ left ({1 \ over Fosc} \ right) \ times4 \ right) \ times Presc \ times \ left (Resolución - Precarga \ right) \ $

Donde:

  • T = Periodo = 1s
  • Fosc = Frecuencia del oscilador = 20Mhz
  • Presc = Prescaler = 128
  • Resolución = 2 ^ 16 = 65535
  • Precarga = 26474

El resultado será: 0.9999872s, será el más cercano a 1s al que pueda llegar.

Código de muestra:

// Timer1 Registers: Prescaler=1:1; TMR1 Preset=60536; Freq=1.000,00Hz; Period=1,00 ms
T1CON.T1CKPS1 = 0;  // bits 5-4  Prescaler Rate Select bits
T1CON.T1CKPS0 = 0;  // bit 4
T1CON.T1OSCEN = 1;  // bit 3 Timer1 Oscillator Enable Control: bit 1=on
T1CON.T1SYNC  = 1;  // bit 2 Timer1 External Clock Input Synchronization Control bit:1=Do not synchronize external clock input
T1CON.TMR1CS  = 0;  // bit 1 Timer1 Clock Source Select bit:0=Internal clock (FOSC/4) / 1 = External clock from pin T1CKI (on the rising edge)
T1CON.TMR1ON  = 1;  // bit 0 enables timer
TMR1H = $EC;         // preset for timer1 MSB register
TMR1L = $78;         // preset for timer1 LSB register

Usando el compilador CCS en MPALB 8:

// Timer 1 declaration
setup_timer_1(T1_INTERNAL|T1_DIV_BY_128);  
set_timer1(26474);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL); 

// Timer 1 Method
#INT_TIMER1 
void timer1Method()
{
    //your timer1 code here
}
    
respondido por el Butzke

Lea otras preguntas en las etiquetas

Comentarios Recientes

Esto está usando el método logarítmico mientras se usan datos de multiplicación de primer y último / primer y segundo orden Ejemplo 1: el momento 1 representa el último0 segundo / 1m2 = 1m1 el momento 2 representa el segundo0 primerúltimo / segundo último es 10 segundos De http://dovefast.tumblr.com/post/3744433868/factorio-structuredtiming 1/10 (@ 55%) 2 Ejemplo 2: el momento 1 representa first0 firstlast / secondlast = 10Seconds From http://dovefast.tumblr.com/post / 3808505594 / factorio-estructurado temporal... Lees verder