reloj de tiempo real. - Departamento de Electrónica

Anuncio
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Diseño con Microcontroladores
Implementación de un reloj de tiempo real en el MSP430F149
Los relojes de tiempo real (Real Time Clocks) son utilizados en diversas
aplicaciones: eventos generadores de marcas de tiempo, generación de eventos
periódicos, etc.
El implementar un RTC con el microcontrolador MSP430 simplifica el diseño
de sistemas y reduce costos, ya que no es necesario contar con un dispositivo dedicado
que realice esta función.
En esta implementación, se utiliza el Timer A del MSP430 para implementar un
reloj de tiempo real. Este timer cuenta con 3 registros de comparación/captura, y utiliza
como señal de reloj al ACLK del microcontrolador.
Generación de la señal de reloj
Todos los microcontroladores de la familia MSP430 contienen un oscilador tipo
RC controlado digitalmente (DCO) y un oscilador de cristal. En el caso de la tarjeta de
desarrollo Easyweb se cuenta con un oscilador de cristal de 8 MHz.
El DCO es utilizado usualmente como reloj de la CPU, y el oscilador de cristal
es usado frecuentemente como reloj para los periféricos; en este caso como la fuente de
reloj para el Timer A, que entrega a su vez la base de tiempo requerida para la
implementación. De este modo, los problemas de inestabilidad del oscilador tipo RC no
afectan la precisión de la implementación.
Implementación del RTC
La implementación consiste en la configuración del Timer A como fuente de
interrupciones periódicas (cada 1 segundo) y una pequeña rutina de CPU que cuenta las
interrupciones actualizando y desplegando en la LCD la cuenta del RTC. La CPU puede
dormir o realizar otras funciones entre las interrupciones (ver código anexo).
La inicialización de los osciladores permite configurar el DCO como reloj de la
CPU (8 MHz) y el oscilador de cristal como señal de reloj del ACLK, a una frecuencia
de 1 MHz (8 MHz dividido por 8, según configuración del módulo básico de reloj).
La inicialización del Timer A realiza la selección del ACLK como fuente de reloj
(dividida nuevamente por 8 queda en 125 kHz), para lograr finalmente una frecuencia
de generación de interrupciones de 1 Hz mediante el uso del modo ‘up-down’ del Timer
A: en el modo comparación, el timer cuenta hasta el valor del registro TACCR0,
previamente seteado en 62.500.
La rutina de servicio de interrupciones manipula los bits del status register que
fueron colocados en el stack justo antes de ingresar a ella. En assembler, esto puede ser
realizado mediante el código:
BIC #LPM3,0(SP) ;
RETI
Pablo Naveas Farías
Clear SR LPM3 Bits, on top of stack
16-01-2004
5
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Diseño con Microcontroladores
En C no es posible acceder al stack de una forma directa, por lo que se incorpora
un llamado a una rutina externa, escrita en assembler y que permite cambiar entre los
distintos modos de operación que tiene el MSP430 (en este caso, cambiar entre el estado
activo y el estado LPM3, de bajo consumo).
Para realizar esto, en el código C, se incluye el prototipo de la función escrita en
assembler.
extern void modus(int mod, int offset);
La rutina en assembler (modus.s43) debe ser incorporada al proyecto y es la
siguiente:
NAME MODUS
RSEG CODE(1)
PUBLIC modus
RSEG CODE
modus:
PUSH
MOV.W
ADD.W
MOV.W
BIC.W
BIS.W
MOV.W
POP
RET
R6
SP,R6
R14,R6
@R6,R14
#0xF0,R14
R12,R14
R14,0(R6)
R6
; save R6
; load SP to R6
; add offset
; load SR en R14
; clear modus bits.
; set modus bits
; save SR to old location
; restore R6
END
El llamado a modus se realiza con 2 parámetros: el valor actual (mod) para ser
escrito en el SR (Status Register) y el offset para el valor del SR almacenado en el
stack.
El argumento mod se pasa en R12 y el offset en R14. La función modus emplea
el registro R6 para efectuar cálculos temporales, (es decir, se escribe en R6, dentro de
modus) por esta razón es salvado el valor de R6 en el frame de modus y restaurado
antes de salir.(El compilador IAR usa el convenio: “La rutina llamada tiene la
responsabilidad de salvar lo que use”. De tal modo que el valor de R6 es el mismo antes
y después de llamar a modus.
Para calcular este offset puede generarse un listado mixto de C y assembler de la
rutina de servicio de interrupciones y luego contar los registros que se colocan en el
stack al comienzo del cuerpo de la función. Luego se suma 1 al número de instrucciones
que salvan registros y se multiplica por dos, obteniendo el offset en bytes del SR.
Pablo Naveas Farías
16-01-2004
5
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Diseño con Microcontroladores
Las rutinas de servicio de interrupciones crean su frame: almacenando PC y
luego el registro de estado SR. Luego salvan los registros que usen, en el caso de
ClockHandler se empujan 4 registros en el frame. La función modus salva R6. Luego
de ejecutada la primera instrucción de modus, el stack puede visualizarse según:
sp
offset
R6
PC
R
R
R
R
SR
PC
Fondo del frame de modus
Tope del frame de ClockHandler
Fondo del frame de ClockHandler
En el diagrama las direcciones de memoria aumentan hacia abajo. Se ilustra el frame de
modus apilado con el frame de ClockHandler.
Notar que el número de registros colocados en el stack puede depender de la
versión del compilador y de las opciones de éste (optimization level).
Por lo tanto, lo que realiza la función modus es el cambio desde el modo LPM3
(bajo consumo) al estado activo: toma los bits del SR desde el stack, resetea los bits del
modo LPM3 de acuerdo al parámetro pasado y guarda nuevamente el SR en el stack, de
tal manera que al volver de la rutina de servicio de la interrupción .
ANEXO: Código para implementación del RTC
#include <msp430x14x.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "MSP430lib.c"
extern void modus(int mod, int offset);
void InitTimer_A (void);
void InitOsc_TA (void);
void Clock (void);
int ii, jj;
unsigned int SEC;
unsigned int MIN;
Pablo Naveas Farías
16-01-2004
5
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Diseño con Microcontroladores
unsigned int HR;
unsigned char LCDtime[32];
void main (void) {
ii = 0;
SEC = 0;
MIN = 7;
HR = 12;
InitOsc_TA();
InitPorts();
InitTimer_A();
InitLCD();
while (1) {
LPM3;
Clock();
}
}
// inicialización osciladores
// inicialización puertos
// inicialización Timer A
// inicialización LCD
// enter low power mode 3
// update clock
void InitTimer_A (void) {
P1SEL = 0x80;
P1DIR |= BIT7;
// enable Dallas output (P1.7)
/* Config. Timer_A*/
TACTL = ID1 | ID0 | TASSEL0 | TAIE; // use ACLK = 1 M / 8 = 125 kHz
TACCTL2 |= OUTMOD1 | OUTMOD0 | CCIS0; // output mode 3, por P1.7 (Dallas)
TACCTL2 &= ~CAP;
// compare mode
TACCR0 = 0xF424;
// 62500
TACCR2 = 0x7A12;
// 31250
TACTL |= MC1 | MC0;
// start timer in up/down-mode
_EINT();
}
void Clock (void) {
SEC++;
if (SEC == 60)
{
SEC = 0;
MIN++;
if (MIN == 60)
{
MIN = 0;
HR++;
if (HR == 24)
Pablo Naveas Farías
16-01-2004
5
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Diseño con Microcontroladores
{
HR = 0;
}
}
}
sprintf (LCDtime, "Hora Chile Cont: %d:%d:%d
for (jj=0; jj != sizeof(LCDtime) - 1; jj++)
{
SEND_CHAR(LCDtime[jj]);
if (jj==15) SEND_CMD (DD_RAM_ADDR2);
}
SEND_CMD (CUR_HOME);
}
", HR, MIN, SEC);
void InitOsc_TA (void) {
WDTCTL = WDTPW | WDTHOLD;
BCSCTL1 |= XTS;
_BIC_SR(OSCOFF);
do
IFG1 &= ~OFIFG;
while (IFG1 & OFIFG);
// XT1 as high-frequency
// turn on XT1 oscillator
// wait in loop until crystal is stable
BCSCTL1 |= DIVA1 | DIVA0;
IE1 &= ~WDTIE;
IFG1 &= ~WDTIFG;
// stop watchdog timer
// ACLK = XT1 / 8 = 1 MHz
// disable WDT int.
// clear WDT int. flag
WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL | WDTIS1;
// use WDT as timer, flag each. 512 pulses from ACLK
while (!(IFG1 & WDTIFG)); // count 1024 pulses from XT1 (until XT1's
// amplitude is OK)
IFG1 &= ~OFIFG;
// clear osc. fault int. flag
DCOCTL |= DCO2 | DCO1 | DCO0;
BCSCTL1 |= RSEL2 | RSEL1 | RSEL0;
// MCLK = DCO, 8 MHz
}
#pragma vector=TIMERA1_VECTOR
__interrupt void ClockHandler (void)
{
if (TAIV == 10)
// check for timer overflow
modus(0x00,12);
// exit low power mode 3
}
Pablo Naveas Farías
16-01-2004
5
Descargar