Mi primer aporte, estaba trabajando en intentar mejorar el código de un semáforo que había hecho hace un año empleando un MSP430, en esa ocasión lo programé con Energia usando el delay(), ahora quería hacerlo un poco más eficiente empleando el temporizador, aquí está el código.
Espero que a alguien le sea útil, he visto muchos con PICs aquí pero pocos proyectos con los MSP430 y a mi me agradan mucho las posibilidades de estas cositas a 3V.
Código:
//******************************************************************************
// Pequeño semaforo con MSP430 asistido por reloj auxiliar de 32.768kHz
//
// Descripción: Empleando el ACLK se realiza el conteo para la secuencia
// de un semáforo simple, el MCU permanece en LPM3 durante el resto del
// tiempo para ahorrar energia.
// //* Un cristal de reloj externo en XIN XOUT es necesario para ACLK *//
//
// MSP430G2
// ---------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | P2.0|-->LED Rojo --
// | P2.1|-->LED Amarillo | <- Un lado
// | P2.2|-->LED Verde --
// | P2.3|-->LED Rojo --
// | P2.4|-->LED Amarillo | <- Otro lado
// | P2.5|-->LED Verde --
//
// Nuyel Solorzano Ruano
// Nuyel Electronics
// Noviembre 2013
//******************************************************************************
#include <msp430.h>
#define Rojo_1 BIT0
#define Amarillo_1 BIT1
#define Verde_1 BIT2
#define Rojo_2 BIT3
#define Amarillo_2 BIT4
#define Verde_2 BIT5
#define Luces P2OUT
volatile int Contador = 0; //El Contador es una variable global para contar el tiempo cada 500ms
/*************************************************
* Rutina de interrupcion del temporizador *
* Esta es la accion que ocurre cada ves que el *
* temporizador genera una interrupcción *
*************************************************/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void){
Contador--; //Disminuir el Contador en 1
P1OUT ^= BIT0; //Invertir el valor de P1.0; esta acción solo la uso para mostrar un destello cada segundo en el LED rojo del LaunchPad
LPM3_EXIT; //Salir del modo de bajo poder 3
}
/* Rutina para esperar */
void esperar(int segundos){
Contador = segundos * 2; //Multiplicar el numero de segundos por 2 y colocarlos en el Contador
while(Contador){ //Esperar hasta que el contador sea 0
LPM3; //Entrar en modo de bajo poder 3
}
}
/* Rutina para destellar */
void destellar(int luz){
Contador = 8; //Veces que debe repetir el ciclo
while(Contador){
LPM3; //Suspender y esperar
Luces ^= luz; //Invertir la luz (encender o apagar)
}
}
void main(void) {
/* Configuración de relojes */
WDTCTL = WDTPW | WDTHOLD; // Detener temporizador vigilante
BCSCTL1 = 0; //Lipiar registro de control del oscilador antes de asignar
BCSCTL3 = 0;
BCSCTL1 = CALBC1_1MHZ; //Reloj principal en 1MHz
DCOCTL = CALDCO_1MHZ; // SMCLK = DCO = 1MHz
/**************************************************
* Se usa el reloj auxilar con cristal de 32768Hz *
* para tener un tiempo preciso sin que se afecte *
* por las variaciones del reloj principal que *
* pueden causarse por variaciones de voltaje. *
* El cristal se conecta en los pines P2.6 y P2.7 *
* ************************************************/
BCSCTL3 = XCAP_3; //Activa la capacitancia interna de 12.5pf para el cristal
/* Configuración de puertos */
P1DIR = 0xFF; //Puerto 1 todos como salidas
P1OUT = 0x00; //Borrar puerto 1
P2DIR = 0x3F; //Puerto 2, 0-5 como salidas, 6 y 7 son del cristal del temporizador
P2OUT = 0x00; //Borrar puerto 2
P3DIR = 0xFF; //Puerto 3 todos como salidas
P3OUT = 0x00; //Borrar puerto 3
/* Configuracion temporizador */
CCTL0 = CCIE; //Habilitar interrupción del temporizador cuando llege a TACCR0
TACCR0 = 16384 - 1; //Valor a contar del temporizador para 500ms
TACTL = TASSEL_1 | MC_1; //Seleccionar conteo ascendente del reloj auxiliar
P1OUT |= BIT0;
__enable_interrupt(); //Habilitar interrupciones globales
/* Lazo del semáforo */
while(1){
Luces = Verde_1 | Rojo_2;
esperar(10);
destellar(Verde_1);
Luces = Amarillo_1 | Rojo_2;
esperar(3);
Luces = Rojo_1 | Verde_2;
esperar(10);
destellar(Verde_2);
Luces = Rojo_1 | Amarillo_2;
esperar(3);
}
}