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,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