RTC (Real-timer counter) - MC9S08QE128

De Wikitronica
Revisión del 22:45 26 nov 2012 de Misato (Discusión | contribuciones) (Por Encuesta)

Saltar a: navegación, buscar

Un Real Timer Counter es un contador interno que mantiene la información del tiempo en unidades humanas, donde la unidad básica es el segundo. El RTC está presente en la mayoría de los dispositivos electrónicos que necesitan llevar un registro del tiempo exacto. El término Real Timer Counter es para diferenciar de los contadores del hardware que son señales electrónicas para controlar los circuitos digitales.

Configuración en el MC9S08QE128

El módulo MC9S08QE128 tiene integrado un Real Timer Counter, que consiste en un comparador uno a uno de 8 bits, un contador uno a uno de 8 bits, diversos divisores pre-escalados de base 2 y de base 10, 3 fuentes de reloj y un vector de interrupción programable.El funcionamiento del RTC se muestra en el diagrama de bloques, presentado en la imagen a continuación:

Diagrama de bloques del RTC
Se selecciona el reloj correspondiente, mediante el RTCLKS[1]. Siendo estos LPO, low power oscillator, el cual es un reloj interno de 1KHz , ERCLK, reloj externo, IRCLK, reloj interno de 32 KHz, si el BACKGROUND MODE esta activado el RTC no entra en funcionamiento, se divide por el divisor pre-escalado seleccionado, mediante el RTCPS y el bit 0 del RTCLKS, y esto es guardado en RTCCNT[2], el cual es comparado bit a bit con RTCMOD[3], si la comparación es exitosa, se escribe un 1 en RTIF[4], el cual es limpiado escribiendo un 1 en RTIF,y si, por último RTIE[5] está activo se realiza la solicitud de interrupción por RTC.

Modos de funcionamiento

Wait Mode

En el modo de espera, el RTC sigue contando si está activado antes de entrar en este modo. Por lo tanto el RTC puede configurarse para que el MCU salga del modo de espera y volver a su funcionamiento normal, esto es posible cuando la interrupción por RTC está activa. Para el menor consumo de corriente en el modo de espera, posible, y si no es requerida la interrupción, entonces se puede deshabilitar el RTC.

Stop Mode

En el modo de stop2 y stop3, el RTC sigue corriendo si esta activo antes de producirse la instrucción de STOP, así que por esta razón el RTC puede configurarse para devolver al MCU de un modo de stop, si la interrupción por RTC está activa. Entre los relojes fuentes, el LPO se puede seleccionar en los dos modos de stop, mientras que ERCLK y IRCLK solo se pueden seleccionar en el modo de stop3. De igual manera si se desea el menor consumo de corriente mientras ocurre el modo de stop, se tiene que deshabilitar el RTC, sabiendo que la interrupción por RTC no podrá regresar el MCU a su normal funcionamiento.

Active Background Mode

El RTC suspende cualquier conteo mientras el MCU se encuentra en Background Mode. El contador se reanuda en el valor que estaba antes suspender el conteo, esto se cumple mientras no se escriba en RTCMOD y los bits de RTCPS Y RTCLKS no sean alterados.

ADC Hardward Trigger

El RTC se puede configurar para que sea el trigger del Conversor Análogo Digital (ADC) y que se realice la conversión, esto se logra si se activa el ADCSC2[ADTRG]. Cuando esto se produce el ADC realiza la conversión cada vez que el RTCINT coincide con RTCMOD, es importante saber que la interrupción por RTC no es necesaria para que este funcione de esta forma.

Definición de los Registros

RTC Status and Control Register (RTCSC)

Este registro contiene: la bandera del status de interrupción (RTIF), el selector del reloj (RTCLKS), el habilitador de la interrupción por RTC (RTIE) y el selector de los divisores pre-escalados (RTCPS). Los bits de estos registros se distribuyen de la siguiente manera:

Bits del RTCSC
Bits Descripción
7

RTIF

Real-TImer Interruption Flag: esta bandera indica que el valor del contador del RTC ha llegado al valor esperado. Escribir un 0 no tiene efecto en este registro, pero si se escribe un 1 la bandera se limpia.

0 = el contador no ha llegado al valor esperado.

1 = el contador llegó al valor esperado.

6:5

RTCLKS

Real-Timer Clock Source Select: estos bits selecciona la fuente del reloj de entrada que utilizará el RTC para dividir entre los divisores pre-escalados. Cambiar la fuente del reloj limpia el divisor pre-escalado en RTCPS y el contador en RTCCNT. Es importante que cuando se selecciona un reloj se verifique si está habilitado, para el buen funcionamiento del RTC. Resetear RTCLKS produce que se vuelva 00.

00 = el reloj seleccionado es LPO, de un 1 KHz de frecuencia.

01 = el reloj seleccionado es el reloj externo (ERCLK).

1x = el reloj seleccionado es el reloj interno (IRCLCK), de 32 KHz de frecuencia.

4

RTIE

Real-Timer Interruption Enable: este bit habilita la interrupción por RTC. Si RTIE está habilitado entonces se realizará una interrupción cuando RTIF se vuelva 1. Resetear el bit produce que éste se vuelva 0.

0 = la interrupción no se habilita, se tiene que proceder por encuesta.

1 = la interrupción está habilitada, así que se realizará cuando RTIF sea 1.

3:0

RTCPS

Real-Timer Clock Prescaler Select: estos cuatros bits sirven para seleccionar el divisor de base 10 o de base 2 que dividirán la frecuencia del reloj seleccionado. Cambiar el divisor produce que RTCCNT se limpie. Si se resetea RTCPS, el valor se vuelve 0.

En la siguiente tabla se muestran los diferentes divisores que ofrece RTC:

Divisores que ofrece el RTC

En la siguiente tabla se muestran los diferentes períodos que puede lograr el RTC:

RTCPS 1 KHz reloj interno

(RTCLKS = 00)

1 MHz reloj externo

(RTCLKS = 01)

32 KHz reloj interno

(RTCLKS = 10)

32 KHz reloj interno

(RTCLKS = 11)

0000 Off Off Off Off
0001 8 ms 1 024 ms 250 us 32 ms
0010 32 ms 2 048 ms 1 ms 64 ms
0011 64 ms 4 096 ms 2 ms 128 ms
0100 128 ms 8 192 ms 4 ms 256 ms
0101 256 ms 16.4 ms 8 ms 512 ms
0110 512 ms 32.8 ms 16 ms 1.024 s
0111 1.024 s 65.5 ms 32 ms 2.048 s
1000 1 ms 1 ms 31.25 us 31.25 ms
1001 2 ms 2 ms 62.5 us 62.5 ms
1010 4 ms 5 ms 125 us 156.25 ms
1011 10 ms 10 ms 312.5 us 312.5ms
1100 16 s 20 ms 0.5 us 0.625 s
1101 0.1 s 50 ms 3.125 ms 1.5625 s
1110 0.5 s 0.1 ms 15.625 ms 3.125 s
1111 1 s 0.2 ms 31.25 ms 6.25 s

RTC Counter Register (RTCCNT)

Este registro es de solo lectura, el cual es el contador de 8 bits que tiene el RTC. Está distribuido de la siguiente manera:

Bits del RTCCNT
Bits Descripción
7:0

RTCCNT

RTC COUNT: estos ochos bits contienen la información del contador de RTC. Escribir en ellos no produce ningún efecto. Resetear, escribir en RTCMOD, o cambiar los valores de RTCLKS y RTCPS limpian el contador y lo vuelve 0x00.

RTC Modulo Register (RTCMOD)

Bits del RTCMOD
Bits Descripcion
7:0

RTCMOD

RTC modulo: estos 8 bits muestran el valor del modulo que servirá para resetear el contador a 0x00 y poner un 1 en RTIF. Un valor de 0x00 permite que RTIF se vuelva 1 cada vez que se alcanza el valor del período escogido. Escribir en estos bits produce que el contador y el RTCCNT se limpien. Resetear el modulo convierte RTCMOD a 0x00.

Modo de Utilización

Por interrupción

Para utilizar la interrupción por RTC se tiene que habilitar el RTIE, como se mostró anteriormente. De esta manera cada vez que el RTIF sea 1 entra en la interrupción y para poder salir se tiene que limpiar esta bandera escribiendole 1. El vector de interrupción de RTC, está contenido en la dirección 0xFFCE:0xFFCF y es nombrado como Vrtc. Este vector se puede configurar a conveniencia del programador. A continuación se mostrará un código simple que configura el RTC en modo de interrupción, y el programa simplemente cuenta el tiempo en segundos,minutos, horas y días.

 #include "derivative.h"  //se incluye la librería con toda la circuitería del [[Freescale Codewarrior 6.3|MC9S08QE128]] 
                          //para más facilidad
 /* Inicializo los contadores del tiempo */
 int Seconds = 0;
 int Minutes = 0;
 int Hours = 0;
 int Days=0;
 int control=0;
 int main(){
 /*Configuro el RTC para que interrumpa cada 1 seg con el reloj fuente LPO de 1 KHz de frecuencia*/
 	 RTCMOD = 0x00;           //el modulo será 00 así que cada vez que pase el período 
                                  //elegido se hará una interrupción
         RTCSC = 0x1F;            //se habilita la interrupción por RTC (RTIE=1), se elige el
                                  //LPO como reloj fuente (RTCLKS = 00), el divisor es de 10^3
                                  // (RTCPS = 0xF), así que el período es de 1 seg
 	  for(;;){               //ciclo infinito
            while(control == 0){
            }                    //ciclo infinito mientras no se entre a la interrupción por RTC
            control = 0;          //vuelvo a poner el control en su estado inicial para que
                                  //el ciclo anterior sirva nuevamenta
            Seconds++;
            /* 60 segundos es un minuto*/
            if (Seconds > 59){
               Minutes++;
               Seconds = 0;
            }
            /* 60 minutos es una hora*/
            if (Minutes > 59){
               Hours++;
               Minutes = 0;
            }
            /* 24 hours es un dia */
            if (Hours > 23){
               Days ++;
               Hours = 0;
            }
          }
  }
  //vector de interrupción por RTC
  void VectorNumber_Vrtc Interrupt(void){
         RTCSC_RTIF = 1;                          //limpio la bandera para volver a entrar a 
                                                  //la interrupción
         control = 1;                             //cambio el control para salir del ciclo
                                                  //infinito del main
  }

Ahora veamos un codigo para utilizar el RTC por interrupción, pero en assembler, donde solo vamos a inicializar el RTC y mostrar el vector de interrupción:

Incluyo toda la circuitería del circuitería del MC9S08QE128

 INCLUDE 'derivative.inc'
inicializo el RTC
 LDA #$00       
 STA RTCMOD           ;RTCMOD esta en 00, así que cada vez que se cumpla el período elegido se
                      ;hará la interrupción
 LDA #$1f
 STA RTCSC             ;el reloj escogido es el LPO a 1KHz, y el período de 1 seg, 
                       ;la interrupción está habilitada
Defino el vector de interrupción en la dirección donde está contenido:
 ORG   $FFCE
 DC.W  Interrupción   ;vector de interrupción por RTC, el cual es programable a la conveniencia
                      ;del usuario
Un ejemplo del vector de interrupción, sería:
 Interrupción:   LDA #$80
                 ORA RTCSC                  ;limpio la bandera RTIF para volver a entrar a la
                                            ;interrupción, con el OR entre 0x80 y RTCSC (donde
                                            ; el octavo bit es RTIF)
                 PSHX                       ;instrucción de ejemplo de como se puede programar
                                            ;a conveniencia el vector de interrupción.
                 RTI                        ;el programa se sale de la interrupción.

Por Encuesta

Si, por el contrario, no se quiere utilizar la interrupción por RTC no se activa el bit RTIE, y el usuario tiene que codificar de tal manera que el programa verifique el estado de RTIF, para saber que el período elegido se ha cumplido. Con el código anterior se modificará para utilizar el RTC como encuesta.


 #include "derivative.h"   //se incluye la librería con toda la circuitería del [[Freescale Codewarrior 6.3|MC9S08QE128]] para más facilidad
 /* Inicializo los contadores del tiempo */
 int Seconds = 0;
 int Minutes = 0;
 int Hours = 0;
 int Days=0;
 int main(){
 /* Configuro el RTC para que interrumpa cada 1 seg con el reloj fuente LPO de 1 KHz de frecuencia*/
 	 RTCMOD = 0x00;           //el modulo será 00 así que cada vez que pase el perído elegido se hará una interrupción
         RTCSC = 0x0F;            //se deshabilita la interrupción por RTC (RTIE=0), se elige el LPO como reloj
 fuente (RTCLKS = 00), el divisor es de 10^3 (RTCPS = 0xF), así que el período es de 1 seg
 	  for(;;){               //ciclo infinito
            while(RTIF == 0){
            }                    //ciclo infinito mientras no se cumpla el perído elegido
            RTIF = 1;           //limpio la bandera
            Seconds++;
            /* 60 segundos es un minuto*/
            if (Seconds > 59){
               Minutes++;
               Seconds = 0;
            }
            /* 60 minutos es una hora*/
            if (Minutes > 59){
               Hours++;
               Minutes = 0;
            }
            /* 24 hours es un dia */
            if (Hours > 23){
               Days ++;
               Hours = 0;
            }
          }
  }

Veamos un ejemplo de assembler por encuesta:

Incluyo toda la circuitería del circuitería del MC9S08QE128

 INCLUDE 'derivative.inc'
inicializo el RTC
 LDA #$00       
 STA RTCMOD           ;RTCMOD esta en 00, así que cada vez que se cumpla el período elegido se hará la interrupción
 LDA #$0f
 STA RTCSC             ;el reloj escogido es el LPO a 1KHz, y el período de 1 seg, la interrupción esta deshabilitada
Después de que se habilita el RTC, el programador tendrá que adecuar su código para verificar la bandera RTIF,como por ejemplo:
 ciclo: BRSET RTCSC_RTIF,RTCSC, ciclo    ;ciclo infinito mientras no se realiza el período indicado
 LDA #$80
 ORA RTCSC              ; limpio la bandera, para verificar en un instante posterior.
 PSHX                   ;codigo de ejemplo

Si bien utilizar interrupción o no, en estos códigos simples, parece ser lo mismo, en un codigo más complicado es recomendable utilizar siempre interrupciones, porque el mismo módulo verifica si ha ocurrido la condición para la interrupción, mientras que por encuesta el programador tiene que tener mucho cuidado en la verificación de la bandera para que su código trabaje como se desee. Además, los ciclos infinitos, mientras no se haga 1 RTIF, hacen que el código por encuesta sea menos eficientes; porque, por lo general, se necesitan más de uno de esos ciclos para verificar la condición, mientras que por interrupción el programa sigue corriendo, hasta que la interrupción es creada, gracias al prendido de la bandera correspondiente.

Referencia