Ejemplo Timer RTC y TPM de forma simultánea

De Wikitronica
Saltar a: navegación, buscar
Este artículo está incompleto. Necesita trabajo adicional. Revisar la discusión.

Antes de entrar de lleno con el ejemplo veremos con detalle cuáles son los registros que manipulamos para configurar y utilizar tanto el RTC como el TPM.

En este ejemplo lo primero que se configura es el GPIO, que es configurar como salida los LEDS que queremos utilizar para realizar la demostración del funcionamiento del RTC y el TPM. Se activan los LEDS como puertos de salida colocando un "1" en su registro respectivo de Dirección de Datos 'PTCDD' y 'PTEDD'(Recordamos que los primero 6 LEDS corresponden al bit 0,1,2,3,4 y 5 del puerto C 'PTC' y los últimos dos corresponden al bit 6 y 7 del puerto E 'PTE') aquí también se coloca un "1" en la data de los puertos para apagar los LEDS ya que estos tienen lógica negada ("1" encendido y "0" apagado). De esta manera se inicializan los LEDS como puertos de salida y están listos para ser usados.

RTC

Ahora llegamos a la configuración del RTC el primer registro que queremos modificar es el SCGC2

Registro SCGC2

Aquí colocamos un 1 en el bit número 2 que es el correspondiente al RTC para activarlo. Luego de activarlo se configurará como tal el RTC según lo que se desea.

Ahora vamos a manipular el registro RTCSC

Registro RTCSC

A este registro se le carga %00010110 donde activamos el bit 4 'RTIE' con el que se activan las interrupciones del RTC y se coloca 0110 en el RTCPS que es el prescalador que dicta cada cuanto tiempo aumentará el RTCCNT (que cuenta hasta llegar al valor dado a RTCMOD y ahí entra en la rutina de interrupción del RTC).

El prescalador viene definido de esta manera dependiendo del valor que se le ponga.

Prescalador del RTC


Se define el RTCMOD o el Modulo del RTC cargando (por ejemplo con la instrucción STA) algún número en él. Éste es el valor máximo hasta donde contará el RTC Counter 'RTCCNT' y que indica cuando ocurre la interrupción del RTC.

Recordemos que cada vez que se carga algo en el RTCMOD se reinician los registros RTCCNT y RTCSC lo que quiere decir que se desconfigura el RTC. Entonces, si queremos seguir usando el RTC debemos volver a configurarlos, es decir, cargar el registro RTCSC.

El valor del RTCMOD tendrá las unidades correspondiente al preescalador seleccionado el cual se escoge en el registro RTCSC. La tabla anterior de preescaladores definirá el valor máximo al que el RTCCNT llegará que es el del RTCMOD y las unidades de éste (para las distintas fuentes de reloj)

Con esto terminamos de configurar el RTC.

TPM

Ahora para configurar el TPM realizaremos un procedimiento muy parecido, primero configuramos el registro TPM1SC que es la configuración del sistema del sistema del TPM1. Cabe acotar que hay 3 contadores TPM independientes entre si, lo cual es de gran utilidad para tener distintas fuentes de reloj y distintos tiempos.


TPMxSC


Aquí cargamos %01001111 donde activamos las interrupciones activando el bit TOIE o Timer Overflow Interrupt Enable, elegimos la fuente del reloj


TPMClockSource.jpg


y también configuramos el prescalador con la siguiente tabla


Prescalador del TPM


Por último se carga $FFFF en el TMP1MOD a través de H:X.

La limitación principal de los TPM es que a diferencia del RTC que tiene 15 preescaladores, este tiene solo 8. La ventaja es que existe TPM1, TPM2 y TPM3 así que se tienen varias posibilidades para realizar varios "timers" con TPM a pesar de sus preescaladores.

Ahora nótese que en este ejemplo las interrupciones hacen exactamente lo mismo, apagan y prenden un LED cada una. La diferencia está en que la manera de bajar la bandera de cada interrupción es distinta ya que son registros distintos y también los tiempos en que ocurren cada interrupción son diferentes debido que así se configuraron los módulos y los prescaladores de cada reloj (TPM y RTC).


;*******************************************************************
;*Ejemplo de utilización de Timers por interrupciones              *
;*                                                                 *
;* Se utiliza el RTC para prender y apagar el led de PTC0 cada 2s. *
;* Se utiliza el TPM para prender y apgar el led de PTC1 cada 1s.  *
;*******************************************************************

; Include derivative-specific definitions
            INCLUDE 'derivative.inc'
;
; export symbols
;
            XDEF _Startup
            ABSENTRY _Startup
;
; variable/data section
;
            ORG    RAMStart         ; Insert your data definition here
ExampleVar: DS.B   1

;
; code section
;
            ORG    ROMStart

_Startup:
            LDHX   #RAMEnd+1        ; initialize the stack pointer
            TXS
            ;Configuración de los pines del Demoqe128
            BSR Configurar_GPIO
			;------------------------------------------
			;Configuración del RTC
            BSR Configurar_RTC
			;------------------------------------------
			;Configuración del TPM
            BSR Configurar_TPM1                       
            CLI                     ; enable interrupts           
           
mainLoop:           
            NOP 
            feed_watchdog
            BRA    mainLoop
            
            
;**************************************************************
;* .             Subrutinas de Configuración                  *
                                                              *
;**************************************************************
Configurar_GPIO:
			; Configuración de los leds del DEMOQE como salida
			; Los Leds tienen lógica negada
			;Parte inferior de Puerto C (0:5)
            LDA #$3F
            STA PTCDD
			STA PTCD
			;------------------------------------------
			;Parte superior de Puerto D (6:7)
            LDA #$C0
            STA PTEDD   
			STA PTED		 
            RTS
            
Configurar_RTC:           
			;------------------------------------------
            ;Habilitamos el Clock Gate para el RTC
            LDA SCGC2          
            ORA #%00000100
            STA SCGC2
            
			;------------------------------------------
            ;Definimos el valor del registro modulo del RTC
            LDA #$00
            STA RTCMOD
            
			;------------------------------------------
            ;Configuramos el RTCSC            
            ;Reloj configurado a 16ms. Fuente reloj interna 1khz.
            ;Interrupciones habilitadas                         
            LDA #%00010110
            ; RTIF=0, RTCLKS6=0 RTCLKS5=0, RTIE=1, RTCPS3=0, RTCPS2=1, RTCPS1=1, RTCPS0=0
            STA RTCSC
            RTS
            
Configurar_TPM1:
            ;Configuracion del timer TPM1 
            ;(Interrupcion en overflow del contador)
            LDA #%01001111
            ; TPM1SC: TOF=0,TOIE=1,CPWMS=0,CLKSB=0,CLKSA=1,PS2=1,PS1=1,PS0=1 
            ;Probar diferentes valores de PS2,PS1,PS0
            STA TPM1SC
            ;Valor maximo de conteo (Probar diferentes valores)
            LDHX    #$FFFF
            STHX    TPM1MOD                ; Compare 0 value setting 
            RTS
            
            
;**************************************************************
;* .             Rutinas de atencion a las interrupciones     *
                                                              *
;**************************************************************
            
Interrupcion_TPM1:
            ;Limpiamos las banderas de interrupcion
            ;Primero se lee el regristro TPMxSC
            LDA TPM1SC
            ;Luego se baja el bit 7 (TOF) escribiendo 0
            AND #%01111111
            STA TPM1SC           
            ;Negamos el pin0 de PTC (Led0)
            ;Revisamos si el PTC0 se encuentra encendido
            LDA PTCD
            BIT #%00000001
            BNE ApagarPTC0
            ;Si el PTC0 está apagado lo encendemos
PrenderPTC0:BSET 0,PTCD
            ;Regresamos de la interrupcion
            RTI

ApagarPTC0: BCLR 0,PTCD
            ;Regresamos de la interrupcion 
            RTI
            
            
Interrupcion_RTC:
            ;Limpiamos las banderas de interrupcion
            ;Se escribe un 1 en la bandera RTIF
            ;Diferente a TPM!!!
            LDA RTCSC
            ORA #%10000000
            STA RTCSC
          
            ;Negamos el pin1 de PTC (Led1)
            ;Revisamos si el PTC1 se encuentra encendido
            LDA PTCD
            BIT #%00000010
            BNE ApagarPTC1
            ;Si el PTC0 está apagado lo encendemos
PrenderPTC1:BSET 1,PTCD
            ;Regresamos de la interrupcion
            RTI

ApagarPTC1: BCLR 1,PTCD
            ;Regresamos de la interrupcion 
            RTI

;**************************************************************
;* spurious - Spurious Interrupt Service Routine.             *
;*             (unwanted interrupt)                           *
;**************************************************************
spurious:                           ; placed here so that security value
            NOP                     ; does not change all the time.
            RTI

;**************************************************************
;*                 Interrupt Vectors                          *
;**************************************************************
            ORG   Vtpm1ovf
            DC.W  Interrupcion_TPM1
            
            ORG   $FFCE
            DC.W  Interrupcion_RTC
            
            ORG   $FFFA
            DC.W  spurious          ;
            DC.W  spurious          ; SWI
            DC.W  _Startup          ; Reset