domingo, 9 de marzo de 2014

RELOJ CON MICROCONTROLADOR AVR

                          El siguiente programa a realizar se trata sobre la implementación de un reloj mostrado en displays de siete segmentos de cátodo común donde ademas de mostrar hora, minutos y segundos se agrego la capacidad de cambiar horas y minutos con ayuda de las interrupciones INT0 e INT1. Ademas de todo esto se agrego un botón el cual dependiendo su estado (HIGH o LOW), incrementa o decrementa  las horas y minutos cada vez que se cambien con las interrupciones correspondientes.

DESCRIPCIÓN:

                            Se comenzara ha explicar el programa en el orden en el que se encuentra dando a mencionar primero lo que realizan las interrupciones y después se explicará lo que realizan las funciones y el programa principal.


ISR(INT0_vect):

                           Cada vez que se genera una interrupción esta rutina realiza el incremento/decremento de horas dependiendo del estado del pin PB7 el cual determina lo que realizará la función, ademas identifica si el valor de la variable horas es igual a cero no decrementa su valor.

if (bit_is_clear(PINB,PINB7))
{
if (horas>0){ horas--; }
else
{
    horas++;
if (horas==24){ horas=0; }
}

ISR(INT1_vect):

                           Cada vez que se genera una interrupción esta rutina realiza el incremento/decremento de minutos dependiendo del estado del pin PB7 el cual determina lo que realizará la función, ademas identifica si el valor de la variable minutos es igual a cero no decrementa su valor.

ISR(INT1_vect){
if (bit_is_clear(PINB,PINB7))
{
if (minutos>0){ minutos--; }
}
else
{
minutos++;
if (minutos==60){ minutos=0; horas++; }
}
}

ISR(TIMER1_COMPA_vect):

                            En la siguiente sección del programa se realiza el incremento de las variables segundos, minutos y horas cada vez que surge una interrupción debido a la comparación del registro OCRIA y el registro TCNT1 lo cual sucede cada 1 segundo.

TCNT1=0; 
segundos++;

                             Cada vez que la interrupción sucede se reinicia el registro TCNT1 para que vuelva a contar. En seguida se incrementa la variable segundos y se pregunta con las funciones if el valor de dicha variable, si su valor es de 60 entonces se incrementa la variable minutos y se limpia segundos.

if (segundos==60)
{
minutos++;
segundos=0;
}

                             Cuando el valor de la variable minutos es igual a 60 se incrementa el valor de horas y se limpia el contenido de minutos.

if (minutos==60)
{
    horas++;
minutos=0;
 
}

                           Para finalizar se pregunta si la variable horas es igual a 24 de ser así se le asigna el valor 0.

if (horas==24)
{
horas=0;
}

INTERRUPCIÓN_CAMBIO:

                           Esta función habilita las interrupciones INT0 e INT1 del registro EIMSK, configurando la interrupción en flanco de bajada con los bits ISC11 e ISC01 del registro EICRA, ademas habilita las resistencias de pull-up y limpia las banderas de interrupción para que no se disparen de forma aleatoria.

setbit(PORTD,PD3);
setbit(PORTD,PD2);

//FLANCO DE BAJADA DE LA INTERRUPCION
setbit(EICRA,ISC01); 
setbit(EICRA,ISC11);
//PINES DE CAMBIO HORA Y MINUTO
setbit(EIMSK,INT1);
setbit(EIMSK,INT0);
setbit(EIFR,INTF0);
setbit(EIFR,INTF1);

TEMPORIZADOR:

                            Esta función configura el TIMER1 en modo CTC en particular el modo 4 con los bits WGM13:10, del registro TCCR1A. Se selecciono un preescalamiento de 256 con los bits CS12:10 del registro TCCR1B y se le asigno el valor 31249 al registro OCR1A para que la interrupción surja cada 1 segundo. Para finalizar se habilito la interrupción por comparación.

//MODO CTC WGM13:0 = 4
clearbit(TCCR1A,WGM13);
setbit(TCCR1A,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);
//PREESCALER
setbit(TCCR1B,CS12);
clearbit(TCCR1B,CS11);
clearbit(TCCR1B,CS10);
//COMPARACION CADA 1 SEGUNDO
OCR1A=31249;
    setbit(TIMSK1,OCIE1A);

UNIDADES_DECENAS:

                                En esta sección se separan las unidades y decenas correspondientes de las variables segundos, minutos y horas. Son guardadas en nuevas variables que serán utilizadas para presentar los datos en los displays de siete segmentos.

dec_seg=segundos/10;
uni_seg=segundos-10*dec_seg;
dec_min=minutos/10;
uni_min=minutos-10*dec_min;
dec_hor=horas/10;
uni_hor=horas-10*dec_hor;

MAIN:

                                    Se declara el pin PB7 como entrada y se habilita su resistencia del pull-up, se realiza la configuración de INT0 e INT1 y del TIMER1 y las salidas que serán conectadas a los dispalys y se habilita la interrupción global.                        

clearbit(DDRB,DDB7);
setbit(PORTB,PB7);
INTERRUPCION_CAMBIO();
initDisplay();
temporizador();
sei();

WHILE(1):

                                    Este bucle realiza la presentación de las horas, minutos y segundos mediante lo siguiente:


  • Se determina el valor de las unidades y decenas de los segundo, minutos y horas con la función UNIDADES_DECENAS();                        
  • Primero coloca en HIGH el bit que se encontraba en LOW para no ser presentado en el display conectado en ese pin.
  • Se determina el valor que se presentara en el display correspondiente.
  • Se pone en LOW el pin conectado a ese display para visualizar su contenido.
  • Espera 2 milisegundos.
  • realiza lo mismo hasta presentar las dec_hor donde volverá a inicio del bucle.



UNIDADES_DECENAS();
//UNIDADES SEGUNDOS
setbit(Pdisp_6,disp_6);
salida_7seg(uni_seg);
clearbit(Pdisp_1,disp_1);
_delay_ms(retencion);
//DECENAS SEGUNDOS
setbit(Pdisp_1,disp_1);
salida_7seg(dec_seg);
clearbit(Pdisp_2,disp_2);
_delay_ms(retencion);
//UNIDADES MINUTOS
setbit(Pdisp_2,disp_2);
salida_7seg(uni_min);
clearbit(Pdisp_3,disp_3);
_delay_ms(retencion);
//DECENAS MINUTOS
setbit(Pdisp_3,disp_3);
salida_7seg(dec_min);
clearbit(Pdisp_4,disp_4);
_delay_ms(retencion);
//UNIDADES HORAS
setbit(Pdisp_4,disp_4);
salida_7seg(uni_hor);
clearbit(Pdisp_5,disp_5);
_delay_ms(retencion);
//DECENAS HORAS
setbit(Pdisp_5,disp_5);
salida_7seg(dec_hor);
clearbit(Pdisp_6,disp_6);
_delay_ms(retencion);

NOTA: 

                         Al final se colocara el link del programa y su simulación en proteus para que puedan descargarlo. Alguna duda o sugerencia puede ingresarla en los comentarios para que podamos realizar programas de su interés.

PROGRAMA:

/*
 * RELOJ.c
 *
 * Created: 09/03/2014 17:40:37
 *  Author: TERRAFORMARS
 */ 


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <avr/interrupt.h>
#include "7_segmentos.h"
#include <util/delay.h>

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))
#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bittoggle(sfr,bit)(_SFR_BYTE(sfr)^=_BV(bit))
#define retencion 2

unsigned char segundos=0,minutos=0,horas=0,uni_seg,uni_min,uni_hor,dec_seg,dec_min,dec_hor;

ISR(INT0_vect){
if (bit_is_clear(PINB,PINB7))
{
if (horas>0){ horas--; }

else
{
   horas++;
if (horas==24){ horas=0; }
}

}
ISR(INT1_vect){
if (bit_is_clear(PINB,PINB7))
{
if (minutos>0){ minutos--; }
}
else
{
minutos++;
if (minutos==60){ minutos=0; horas++; }
}
}


ISR(TIMER1_COMPA_vect){
TCNT1=0; 
segundos++;
if (segundos==60)
{
minutos++;
segundos=0;
}

if (minutos==60)
{
   horas++;
minutos=0;
 
}

if (horas==24)
{
horas=0;

}

}

void INTERRUPCION_CAMBIO(){
setbit(PORTD,PD3);
setbit(PORTD,PD2);

//FLANCO DE BAJADA DE LA INTERRUPCION
setbit(EICRA,ISC01); 
setbit(EICRA,ISC11);
//PINES DE CAMBIO HORA Y MINUTO
setbit(EIMSK,INT1);
setbit(EIMSK,INT0);
setbit(EIFR,INTF0);
setbit(EIFR,INTF1);

}
//CONFIGURACION DE TIMER1
void temporizador(){
//MODO CTC WGM13:0 = 4
clearbit(TCCR1A,WGM13);
setbit(TCCR1A,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);

//PREESCALER
setbit(TCCR1B,CS12);
clearbit(TCCR1B,CS11);
clearbit(TCCR1B,CS10);
//COMPARACION CADA 1 SEGUNDO
OCR1A=31249;
    setbit(TIMSK1,OCIE1A);
};

void UNIDADES_DECENAS(){
dec_seg=segundos/10;
uni_seg=segundos-10*dec_seg;

dec_min=minutos/10;
uni_min=minutos-10*dec_min;

dec_hor=horas/10;
uni_hor=horas-10*dec_hor;

}

int main(void)
{
clearbit(DDRB,DDB7);
setbit(PORTB,PB7);
INTERRUPCION_CAMBIO();
initDisplay();
temporizador();
sei();

    while(1)
    {
        //TODO:: Please write your application code 
UNIDADES_DECENAS();
//UNIDADES SEGUNDOS
setbit(Pdisp_6,disp_6);
salida_7seg(uni_seg);
clearbit(Pdisp_1,disp_1);
_delay_ms(retencion);
//DECENAS SEGUNDOS
setbit(Pdisp_1,disp_1);
salida_7seg(dec_seg);
clearbit(Pdisp_2,disp_2);
_delay_ms(retencion);
//UNIDADES MINUTOS
setbit(Pdisp_2,disp_2);
salida_7seg(uni_min);
clearbit(Pdisp_3,disp_3);
_delay_ms(retencion);
//DECENAS MINUTOS
setbit(Pdisp_3,disp_3);
salida_7seg(dec_min);
clearbit(Pdisp_4,disp_4);
_delay_ms(retencion);
//UNIDADES HORAS
setbit(Pdisp_4,disp_4);
salida_7seg(uni_hor);
clearbit(Pdisp_5,disp_5);
_delay_ms(retencion);
//DECENAS HORAS
setbit(Pdisp_5,disp_5);
salida_7seg(dec_hor);
clearbit(Pdisp_6,disp_6);
_delay_ms(retencion);

    }
}


VÍDEO:




IMÁGENES:

SIMULACIÓN EN ISIS PROTEUS:


PROGRAMA EN ATMEL STUDIO:


LINK:

https://mega.co.nz/#!V4kClC5Q!B5Q-CudJuH_Qr-dFyc-kOLpBPidvTYJimHP4SINOcIE



No hay comentarios:

Publicar un comentario