Diferencia entre revisiones de «RTC (Real-timer counter) - MC9S08QE128»

De Wikitronica
Saltar a: navegación, buscar
(Ejemplo acomodado para eclipse V10)
 
(No se muestran 93 ediciones intermedias de 16 usuarios)
Línea 1: Línea 1:
'''Real-Timer Counter'''
+
<div style="top:+0.3em; text-align: center;font-size:100%; border:1px solid #C7D0F8; background:#F2F5FD;width:80%">
 +
'''Este artículo está incompleto. Necesita trabajo adicional. Revisar la discusión.'''</div>
  
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 en los contadores del hardware que son señales electrónicas para controlar los circuitos digitales.
+
 
 +
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.
 +
 
 +
BSET ICSC1_IRCLKEN,ICSC1 para reloj interno de RTC
  
 
==Configuración en el MC9S08QE128==
 
==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:
 +
 +
[[Archivo:Diagrama.jpg|500px|right|thumb|Diagrama de bloques del RTC]]
 +
 +
'''Selección de Reloj:'''
 +
El RTC necesita una base de tiempo la cual definirá la velocidad con la que se producirá el conteo. Para esto se utiliza un reloj. Existen 3 fuentes posibles de reloj que se pueden seleccionar utilizando el Registro [[RTC (Real-timer counter) - MC9S08QE128#Definición_de_los_Registros|RTCLKS]]. Se tienen 3 posibilidades: LPO (Low Power Oscillator), el cual es un reloj interno de 1KHz. ERCLK para seleccionar un reloj externo y el IRCLK el cual es un reloj interno de 32 KHz. '''Generalmente es conveniente utilizar el LPO (el reloj de 1khz).'''
 +
 +
Si se quieren configurar las fuentes de reloj IRCLK como el ERCLK  se deben modificar los registros  ICSIRCLK y ICSERCLK pertenecientes al Módulo de configuración de Clock interno [[ICS (Configuración Reloj Interno) - MC9S08QE128|ICS]].
 +
 +
Si el [[Modos de operación del MC9S08QE128|BACKGROUND MODE]] esta activado el RTC no entra en funcionamiento.
 +
 +
El funcionamiento del RTC es el siguiente. El reloj seleccionado se divide por el divisor pre-escalado seleccionado, mediante el RTCPS y el bit 0 del RTCLKS, y esto es guardado en [[RTC (Real-timer counter) - MC9S08QE128#Definición_de_los_Registros|RTCCNT]], el cual es comparado bit a bit con [[RTC (Real-timer counter) - MC9S08QE128#Definición_de_los_Registros|RTCMOD]], si la comparación es exitosa, se escribe un 1 en [[RTC (Real-timer counter) - MC9S08QE128#Definición_de_los_Registros|RTIF]], el cual es limpiado  escribiendo un 1 en RTIF,y si, por último [[RTC (Real-timer counter) - MC9S08QE128#Definición_de_los_Registros|RTIE]] está activo se realiza la solicitud de interrupción por RTC.
 +
 +
Es importante destacar que si se desea usar el ICSIRCLK como fuente para el módulo RTC es necesario habilitar esta salida hacia el bus clock mediante la configuración del bit "RTC" en el registro  de compuertas de control para el sistema de reloj "SCGC2" por sus siglas en ingles (System Clock Gating Control 2 Register). para mayor información  ver la sección 5.8 del manual del microprocesador. [http://www.freescale.com/files/microcontrollers/doc/ref_manual/MC9S08QE128RM.pdf Manual de Referencia]
 +
 +
==Modos de funcionamiento==
 +
 +
===Wait Mode===
 +
 +
En el [[Modos de operación del MC9S08QE128| 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 [[Modos de operación del MC9S08QE128|stop2]] y [[Modos de operación del MC9S08QE128|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 [[Modos de operación del MC9S08QE128|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 (Conversor Analógico-Digital) - MC9S08QE128|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:
 +
 +
[[Archivo:RTCSC.jpg|700px|center|thumb|Bits del RTCSC.]]
 +
 +
{| border="2" style="padding: 0.5em; border: 1px #aaa solid; border-collapse: collapse;background:#F9F9F9" cellpadding="4"
 +
|- valign="bottom" style="background:#F2F2F2"
 +
!Bits
 +
!Descripción
 +
|-
 +
|align="center"|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.
 +
|-
 +
|align="center"|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.
 +
|-
 +
|align="center"|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.
 +
|-
 +
|align="center"|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:
 +
[[Archivo:tabla1.jpg|700px|center|thumb|Divisores que ofrece el RTC.]]
 +
 +
En la siguiente tabla se muestran los diferentes períodos que puede lograr el RTC:
 +
 +
{| border="2" style="padding: 0.5em; border: 1px #aaa solid; border-collapse: collapse;background:#F9F9F9" cellpadding="4"
 +
|- valign="bottom" style="background:#F2F2F2"
 +
!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:
 +
 +
[[Archivo:RTCCNT.jpg|700px|center|thumb|Bits del RTCCNT.]]
 +
 +
{| border="2" style="padding: 0.5em; border: 1px #aaa solid; border-collapse: collapse;background:#F9F9F9" cellpadding="4"
 +
|- valign="bottom" style="background:#F2F2F2"
 +
!Bits
 +
!Descripción
 +
|-
 +
|align="center"|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)===
 +
 +
[[Archivo:RTCMOD.jpg|700px|center|thumb|Bits del RTCMOD.]]
 +
 +
 +
 +
{| border="2" style="padding: 0.5em; border: 1px #aaa solid; border-collapse: collapse;background:#F9F9F9" cellpadding="4"
 +
|- valign="bottom" style="background:#F2F2F2"
 +
!Bits
 +
!Descripcion
 +
|-
 +
|align="center"|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.
 +
 +
<syntaxhighlight lang="c">
 +
// EJEMPLO PARA ECLIPSE V10
 +
#include <hidef.h> /* for EnableInterrupts macro */
 +
#include "derivative.h" /* include peripheral declarations */
 +
 +
byte Seconds = 0;
 +
byte Minutes = 0;
 +
byte Hours = 0;
 +
int Days=0;
 +
 +
void rtc_init()
 +
{
 +
    /*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 (kilo)
 +
}
 +
 +
 +
void main(void)
 +
{
 +
    rtc_init();
 +
    EnableInterrupts;
 +
    /* include your code here */
 +
 +
    for(;;)
 +
    {
 +
        __RESET_WATCHDOG(); /* feeds the dog */
 +
    } /* loop forever */
 +
}
 +
 +
//vector de interrupción por RTC
 +
interrupt VectorNumber_Vrtc void Mi_Interrupcion(void)
 +
{
 +
    RTCSC_RTIF = 1; // Limpio la Bandera para volver a entrar a la Interrupción.
 +
 +
    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;
 +
    }
 +
}
 +
 +
// La definicion del vector de interrupcion para CodeWarrior 6.3 seria
 +
// interrupt void VectorNumber_Vrtc Mi_Interrupcion(void)
 +
</syntaxhighlight>
 +
 +
Ahora veamos un código 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 [[Freescale Codewarrior 6.3|MC9S08QE128]]
 +
 +
<syntaxhighlight lang="asm">
 +
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 segundo,
 +
                      ; 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.
 +
</syntaxhighlight>
 +
 +
===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.
 +
 +
 +
<syntaxhighlight lang="c">
 +
#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 segundo con el reloj fuente LPO de 1 KHz de frecuencia*/
 +
RTCMOD = 0x00;          // El Módulo 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 segundo.
 +
  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;
 +
            }
 +
          }
 +
  }
 +
</syntaxhighlight>
 +
 +
Veamos un ejemplo de Assembler por encuesta:
 +
 +
Incluyo toda la circuitería del circuitería del [[Freescale Codewarrior 6.3|MC9S08QE128]]
 +
 +
<syntaxhighlight lang="asm">
 +
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                  ; Código de ejemplo.
 +
</syntaxhighlight>
 +
 +
; Si : bien utilizar interrupción o no, en estos códigos simples, parece ser lo mismo, en un código 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.
 +
 +
==Ejemplo==
 +
 +
 +
A continuación se muestra un ejemplo de operación del RTC:
 +
 +
[[Archivo:Ejemplo_RTC.jpg|700px|center|thumb|Ejemplo del funcionamiento básico del RTC.]]
 +
 +
En este ejemplo se seleccionó la fuente de reloj de 1-kHz y se pre-escalo en pulsos de 32ms.
  
 +
Se observa que después del valor 0x55 en el RTCCNT, este se resetea y se coloca en uno (1) RTIF, esto indica que el RTCCNT llego al valor máximo impuesto por el RTCMOD y dio lugar a una interrupción.
  
 +
;
  
 +
;Nota: Es importante destacar que para un buen funcionamiento de la rutina de interrupción del RTC, se debe configurar de forma adecuada el vector de interrupción asociado al RTC. Este vector se ubica en la posición de memoria 0xFFCE.
  
 +
==Referencia==
  
 +
*[http://www.freescale.com/files/microcontrollers/doc/ref_manual/MC9S08QE128RM.pdf '''Reference Manual.''' ''Freescale'']
  
 +
*[http://www.freescale.com/files/microcontrollers/doc/user_guide/DEMOQE128UM.pdf ''DEMOQE128 User Manual'' DEMOQE rev A]
  
  
 
[[Categoría: MC9S08QE128]]
 
[[Categoría: MC9S08QE128]]

Revisión actual del 12:07 18 nov 2013

Este artículo está incompleto. Necesita trabajo adicional. Revisar la discusión.


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.

BSET ICSC1_IRCLKEN,ICSC1 para reloj interno de RTC

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

Selección de Reloj: El RTC necesita una base de tiempo la cual definirá la velocidad con la que se producirá el conteo. Para esto se utiliza un reloj. Existen 3 fuentes posibles de reloj que se pueden seleccionar utilizando el Registro RTCLKS. Se tienen 3 posibilidades: LPO (Low Power Oscillator), el cual es un reloj interno de 1KHz. ERCLK para seleccionar un reloj externo y el IRCLK el cual es un reloj interno de 32 KHz. Generalmente es conveniente utilizar el LPO (el reloj de 1khz).

Si se quieren configurar las fuentes de reloj IRCLK como el ERCLK se deben modificar los registros ICSIRCLK y ICSERCLK pertenecientes al Módulo de configuración de Clock interno ICS.

Si el BACKGROUND MODE esta activado el RTC no entra en funcionamiento.

El funcionamiento del RTC es el siguiente. El reloj seleccionado se divide por el divisor pre-escalado seleccionado, mediante el RTCPS y el bit 0 del RTCLKS, y esto es guardado en RTCCNT, el cual es comparado bit a bit con RTCMOD, si la comparación es exitosa, se escribe un 1 en RTIF, el cual es limpiado escribiendo un 1 en RTIF,y si, por último RTIE está activo se realiza la solicitud de interrupción por RTC.

Es importante destacar que si se desea usar el ICSIRCLK como fuente para el módulo RTC es necesario habilitar esta salida hacia el bus clock mediante la configuración del bit "RTC" en el registro de compuertas de control para el sistema de reloj "SCGC2" por sus siglas en ingles (System Clock Gating Control 2 Register). para mayor información ver la sección 5.8 del manual del microprocesador. Manual de Referencia

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.

// EJEMPLO PARA ECLIPSE V10
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

byte Seconds = 0;
byte Minutes = 0;
byte Hours = 0;
int Days=0;

void rtc_init()
{
    /*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 (kilo)
}


void main(void)
{
    rtc_init();
    EnableInterrupts;
    /* include your code here */

    for(;;)
    {
        __RESET_WATCHDOG(); /* feeds the dog */
    } /* loop forever */
}

//vector de interrupción por RTC
interrupt VectorNumber_Vrtc void Mi_Interrupcion(void)
{
    RTCSC_RTIF = 1; // Limpio la Bandera para volver a entrar a la Interrupción.

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

// La definicion del vector de interrupcion para CodeWarrior 6.3 seria
// interrupt void VectorNumber_Vrtc Mi_Interrupcion(void)

Ahora veamos un código 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 segundo, 
                       ; 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 segundo con el reloj fuente LPO de 1 KHz de frecuencia*/
 	 RTCMOD = 0x00;           // El Módulo 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 segundo.
 	  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                   ; Código de ejemplo.
Si 
bien utilizar interrupción o no, en estos códigos simples, parece ser lo mismo, en un código 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.

Ejemplo

A continuación se muestra un ejemplo de operación del RTC:

Ejemplo del funcionamiento básico del RTC.

En este ejemplo se seleccionó la fuente de reloj de 1-kHz y se pre-escalo en pulsos de 32ms.

Se observa que después del valor 0x55 en el RTCCNT, este se resetea y se coloca en uno (1) RTIF, esto indica que el RTCCNT llego al valor máximo impuesto por el RTCMOD y dio lugar a una interrupción.

Nota
Es importante destacar que para un buen funcionamiento de la rutina de interrupción del RTC, se debe configurar de forma adecuada el vector de interrupción asociado al RTC. Este vector se ubica en la posición de memoria 0xFFCE.

Referencia