0% encontró este documento útil (0 votos)
55 vistas13 páginas

Practica 5

Este documento describe un proyecto de un reloj-alarma-calendario con sensor de temperatura realizado por tres estudiantes. El proyecto utiliza un microcontrolador PIC16F877A, un módulo LCD 16x2, un sensor de temperatura LM35 y botones para medir la temperatura y mostrar la hora, fecha, alarma y temperatura. El código C programado controla las funciones del reloj, alarma, calendario y sensor de temperatura.

Cargado por

luiscolina384
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
55 vistas13 páginas

Practica 5

Este documento describe un proyecto de un reloj-alarma-calendario con sensor de temperatura realizado por tres estudiantes. El proyecto utiliza un microcontrolador PIC16F877A, un módulo LCD 16x2, un sensor de temperatura LM35 y botones para medir la temperatura y mostrar la hora, fecha, alarma y temperatura. El código C programado controla las funciones del reloj, alarma, calendario y sensor de temperatura.

Cargado por

luiscolina384
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

REPÚBLICA BOLIVARIANA DE VENEZUELA

UNIVERSIDAD RAFAEL BELLOSO CHACÍN

FACULTAD DE INGENIERÍA

ESCUELA DE COMPUTACIÓN

MICROCONTROLADORES

SECCIÓN C813

PRACTICA V

REALIZADO POR:

José Zabala, V29.691.806.

Yahineris Soto, V30.217.611.

Luis Colina, V31.050.548.


MARACAIBO, SEPTIEMBRE DE 2023

Introducción

Un reloj-alarma-calendario con módulo LCD 16x2 y sensor de


temperatura es un proyecto de electrónica que combina la
funcionalidad de un reloj, una alarma y un calendario en un solo
dispositivo, además de medir la temperatura ambiente. El módulo LCD
16x2 es una pantalla plana que utiliza una sustancia líquida atrapada
entre dos placas de vidrio para mostrar información. Este proyecto es
una excelente manera de aprender sobre la programación de
microcontroladores y la electrónica en general, así como de medir la
temperatura ambiente.
Componentes

• 1 pic16F877a
• Un cristal de cuarzo de 4MHz
• 2 capacitores de 22pF
• 2 capacitores de 100nF
• 4 resistencia de 1kohm
• 1 resistencias de 200ohm
• 1 pantalla LCD
• 2 potenciómetros de 5k
• Un lm358
• Un lm35
• 4 botones
Esquema
Código

#Include <16F877A.h> //completa los 5000uS


#DEVICE ADC = 10 SET_RTCC(108);
//CONFIGURAMOS EL #DEFINE SW_HOLD //prepara el RTCC para
ADC EN 10 BITS SWFLAGS,0 temporizar los proximos
#include<math.h> #DEFINE SW1 2500uS
#FUSES XT, SWFLAGS,1 DISPN++; //cambia a la
NOPROTECT, #DEFINE SW2 proxima posicion del
NOBROWNOUT, SWFLAGS,2 multiplexado
NOWDT, PUT, NOLVP, #DEFINE SW3
NOCPD SWFLAGS,3 }
#USE DELAY(CLOCK=4 #DEFINE SW4
000000) SWFLAGS,4 void DATECALC(){
#DEFINE SW_OK //Función para calcular la
#BYTE PORTB = 6 SWFLAGS,5 fecha. Es llamada por la
#BYTE PORTC = 7 #DEFINE SW_NOTREL función TIMECALC(),
#BYTE PORTD = 8 EASED SWFLAGS,6 cada vez que se
#BYTE PORTE = 9 incrementa el día.
#DEFINE AM FLAGS,0
BYTE CONST #DEFINE AMA FLAGS,1 if((YEAR % 4 == 0 &&
DISPLAY[10]= #DEFINE STOP_SECTI YEAR % 100 != 0)
{0x3f,0x06,0x5b,0x4f,0x6 MER FLAGS,2 (YEAR % 100 == 0 &&
6,0x6d,0x7d,0x07,0x7f,0 #DEFINE ALARM_ON YEAR % 400 == 0)) {
x67}; FLAGS,3 //Verificación de año
#DEFINE ALARM_MUT bisiesto, 100% precisa.
E FLAGS,4 MONTHARRAY[1] =
int DISPN, MODE, #DEFINE CHANGES_M 29; //Establecer el último
FLAGS, SWFLAGS, ADE FLAGS,5 día de Febrero (índice 1
BTNCNT; #DEFINE MODE_CHAN de MONTHARRAY[12])
int MIN, HOUR, SEC, GED FLAGS,6 en 29
AMIN, AHOUR; #DEFINE BUZZ_ACT }
int DAY, MONTH; FLAGS,7 else{
int YEAR; MONTHARRAY[1] =
int COUNTSEC; #INCLUDE <LCD.C> 28; //Si no es bisiesto,
int MONTHARRAY[12] = ponerlo en 28.
{31, 29, 31, 30, 31, 30, #INT_RTCC }
31, 31, 30, 31, 30, 31}; void TIMER_2500uS()
float tempC=0, tempF=0; { //rutima de interrupción if(DAY >
float a=0; del RTCC (TMR0) para MONTHARRAY[MONTH
#DEFINE BUZZER 2500uS -1]){ //Se compara el día
PORTE,0 actual con el último día
#DEFINE LED PORTE,1 DELAY_US(2); del índice [MONTH -1]
del arreglo BIT_TEST(AM))) && BIT_CLEAR(LED);
MONTHARRAY[12]; Si BIT_TEST(ALARM_ON)) BIT_CLEAR(BUZZER);
MONTH = 2, el { }
programa está en el 2do }
mes, febrero, y compara if(COUNTSEC % 15 ==
eso con el índice [2 - 1] = 0){ void TIMECALC(){
[1] de BIT_SET(BUZZER); //Rutina para calcular los
MONTHARRAY[12], que if(BIT_TEST(LED)){ minutos y los segundos.
corresponde BIT_CLEAR(LED); Es llamada cada vez que
//Al último día del mes de } se incrementan los
Febrero. else{ segundos.
BIT_SET(LED);
DAY = 1; //Se establece } if(MIN >= 60){
el día en 1 cuando la MIN = 0; //Resetear los
variable DAY sobrepasa if(! minutos cuando pasen
el índice [MONTH -1] de BIT_TEST(ALARM_MUT de 59, y aumentar la
MONTHARRAY, y se E)){ hora.
incrementa el mes. HOUR++;
MONTH++; if(BIT_TEST(BUZZ_ACT }
} )){
BIT_CLEAR(BUZZ_ACT if(HOUR >= 12){
if(MONTH >= 13){ );
MONTH = 1; //Se } if(BIT_TEST(AM)){ //Si la
resetea el mes si llega a else{ hora está en AM, y se
13, y se incrementa el BIT_SET(BUZZ_ACT); llega a las 12
año. } BIT_CLEAR(AM);
YEAR++; //Desactivar la bandera
} } de AM (indicando que
} sería PM ahora)
} HOUR = 0; //Y
void ALARMTONE(){ if(BIT_TEST(BUZZ_ACT establecer la hora en 0.
//Rutina para activar la )){ El programa maneja la
alarma. SET_PWM2_DUTY(500) hora de 0 a 11
if(! ; }
BIT_TEST(ALARM_ON) }
BIT_TEST(ALARM_MUT if(!BIT_TEST(AM)){ //Si
E)){ else{ la hora está en PM y se
SET_PWM2_DUTY(0); SET_PWM2_DUTY(0); llega a las 12, quiere
} > José Zabala: if(AMIN } decir que ha pasado un
== MIN && AHOUR == día.
HOUR && } BIT_SET(AM); //Se
((BIT_TEST(AMA) && vuelve a activar AM
BIT_TEST(AM)) (! else{ DAY++; //Se incrementa
BIT_TEST(AMA) && ! SET_PWM2_DUTY(0); el día
HOUR = 0; //Se resetea 200ms para detectar BIT_SET(SW_OK);
la hora correctamente una break;
DATECALC(); //Y se pulsación de botón, }
llama a la rutina que solamente si la bandera case(8):{
calcula la fecha. SW_NOTRELEASED BIT_SET(SW4);
} está desactivada. BIT_CLEAR(SW_HOLD)
BTNCNT++; ;
} } BIT_SET(SW_OK);
break;
} if(BTNCNT == 80){ }
BTNCNT = 0; //Una vez default:{
void DET_BTNS(){ pasados 200ms (80 * BIT_CLEAR(SW_HOLD)
//Rutina para detectar 2.5ms = 200), resetear ;
pulsaciones de botones BTNCNT. BIT_CLEAR(SW_OK);
}
if(PORTC != 0){ BIT_SET(SW_NOTREL
BIT_SET(SW_HOLD); // EASED); //Establecer la }
Si se detecta un valor bandera de que sigue }
distinto de 0 en PORTC, presionado el switch }
activar la bandera de }
que se presionó un switch(PORTC){ //Toma
switch el valor de PORTC, y void SAVE_EEPROM(){
} activa la bandera /* GUARDAR HORA */
else{ //Si no se detecta correspondiente al
nada, limpiar la bandera switch que fue /* if(BIT_TEST(AM)){
de que se presionó un presionado WRITE_EEPROM(0,
switch, y la bandera de case(1):{ HOUR);
que se presionó un BIT_SET(SW1); }
switch correctamente y BIT_CLEAR(SW_HOLD) else{
aún no se ha borrado ; WRITE_EEPROM(0,
BIT_CLEAR(SW_HOLD) BIT_SET(SW_OK); HOUR + 12);
; break; }
BIT_CLEAR(SW_NOTR } */
ELEASED); case(2):{ //Usando este if-else, se
} BIT_SET(SW2); ahorra un byte en la
BIT_CLEAR(SW_HOLD) EEPROM. En este
if(BIT_TEST(SW_HOLD) ; montaje no importa
){ BIT_SET(SW_OK); mucho, pero para un
break; montaje más complicado
if(! } sería muy razonable
BIT_TEST(SW_NOTREL case(4):{ aplicar este truco.
EASED)){ //Incrementar BIT_SET(SW3); Además, se desgasta
el contador BTNCNT, BIT_CLEAR(SW_HOLD) menos la EEPROM.
que da una ventana de ;
como MES resulta ser
// WRITE_EEPROM(1, MIN = mayor a 13, y se intenta
MIN); READ_EEPROM(1); acceder al arreglo
*/ MONTHARRAY (tamaño
/* GUARDAR FECHA */ /* CARGAR FECHA */ 12), cargará un valor
WRITE_EEPROM(2, DAY = inválido que podría
DAY); READ_EEPROM(2); //Permitir que se cargara
WRITE_EEPROM(3, MONTH = un día inválido
MONTH); READ_EEPROM(3);
WRITE_EEPROM(4, YEAR = HOUR = 0;
YEAR); READ_EEPROM(4); MIN = 0;
SEC = 0;
/* GUARDAR ALARMA */ if((YEAR % 4 == 0 && BIT_SET(AM);
YEAR % 100 != 0)
// WRITE_EEPROM(5, (YEAR % 100 == 0 && AHOUR = 0;
AMIN); YEAR % 400 == 0)) { AMIN = 0;
//Verificación 100% BIT_SET(AMA);
/* if(BIT_TEST(AMA)){ precisa para años
WRITE_EEPROM(6, bisiestos. DAY = 1;
AHOUR); MONTHARRAY[1] = 29; MONTH = 1;
} } YEAR = 0;
else{
WRITE_EEPROM(6, /* CARGAR ALARMA }
AHOUR + 12);
}*/ AMIN =
READ_EEPROM(5); if(DAY >
} MONTHARRAY[MONTH
AHOUR = ] YEAR > 99 HOUR > 23
void LOAD_EEPROM(){ READ_EEPROM(6); MIN > 59 SEC > 59
AHOUR > 23 AMIN > 59)
/* CARGAR HORA if(AHOUR >= 12){ { //Si alguno de los
HOUR = AHOUR -= 12; valores almacenados en
READ_EEPROM(0); BIT_SET(AMA); la EEPROM no tiene
} sentido, cargar unos
if(HOUR >= 12){ //En el */ predeterminados.
formato en el que se /* VERIFICAR VALIDEZ /* 1: Si el día
guarda la hora en la DE LOS DATOS almacenado es mayor al
EEPROM, 0 = 12 AM; 12 CARGADOS */ último día del mes actual
= 12 PM.
HOUR -= 12; //Si la hora if(MONTH > 13){ //Se 2: Si el año es mayor a
> José Zabala: es igual a verifica aparte el mes, (20)99 (El programa
12 o mayor, restar 12 primero que todo lo trabaja desde el
BIT_CLEAR(AM); // demás. Esto se hace ya 01/01/2000 hasta el
} que, si el valor cargado 31/12/2099
3: Si la hora (en formato modo 0. bandera
de 24H, que es como se MODE = 0; }
almacena en la
EEPROM) es mayor a if(BIT_TEST(CHANGES switch(MODE){
23 (y la de la alarma _MADE)){ //Si está /*
también) activada la bandera de MODOS:
4: Si los minutos (tanto que se han hecho 0: HORA - FECHA
de la hora como de la cambios (en los modos 1: HORA - ALARMA
alarma) son mayores a 2, 3 o 4), se procede a 2: CONFIGURAR HORA
59 guardar en la EEPROM, 3: CONFIGURAR
5: Si los segundos son y se borra la bandera. FECHA
mayores a 59 //Esta bandera impide 4: CONFIGURAR
Cualquiera de esas que el programa guarde ALARMA
condiciones indica que lo en la EEPROM si no se 5: TEMPERATURA
almacenado en la ha cambiado nada en la */
EEPROM es una fecha configuración.
incorrecta. BIT_CLEAR(CHANGES case(0):{
*/ _MADE); LCD_GOTOXY(1,1);
HOUR = 0; SAVE_EEPROM(); LCD_PUTC("HORA ");
MIN = 0; if(HOUR == 0){
SEC = 0; } PRINTF(LCD_PUTC,
BIT_SET(AM); } "12:%02d:%02d", MIN,
SEC);
AHOUR = 0; PORTB = }
AMIN = 0; DISPLAY[MODE]; else{
BIT_SET(AMA); //Mostrar el modo en la PRINTF(LCD_PUTC,
EEPROM "%02d:%02d:%02d",
DAY = 1; HOUR, MIN, SEC);
MONTH = 1; BIT_SET(MODE_CHAN }
YEAR = 0; GED); //Activar bandera if(BIT_TEST(AM)){
} de que se cambió el LCD_PUTC("AM");
modo }
} } else{
LCD_PUTC("PM");
void MODECYCLE(){ void DISPLCD(){ }
//Rutina para hacer el
ciclo entre los modos al if(BIT_TEST(MODE_CH LCD_GOTOXY(1,2);
presionar el botón SW1 ANGED)){ //Si está LCD_PUTC("FECHA ");
MODE++; activa la bandera de que PRINTF(LCD_PUTC,
se cambió el modo "%02d/%02d/20%02d",
if(MODE >=6){ //El LCD_PUTC("\f"); DAY, MONTH, YEAR);
programa trabaja los //Limpiar el LCD break;
modos del 0 al 5. Si se BIT_CLEAR(MODE_CH }
pasa de 5, devolver al ANGED); //Y limpiar la
case(1):{ LCD_GOTOXY(1,2);
LCD_GOTOXY(1,1); case(2):{ LCD_PUTC("ALARMA
LCD_PUTC("HORA "); ");
LCD_GOTOXY(1,1);
if(HOUR == 0){ LCD_PUTC("CONFIG. if(AHOUR == 0){
PRINTF(LCD_PUTC, HORA"); PRINTF(LCD_PUTC,
"12:%02d:%02d", MIN, LCD_GOTOXY(1,2); "12:%02d", AMIN);
SEC); if(HOUR == 0){ }
} PRINTF(LCD_PUTC,
else{ "12:%02d:%02d", MIN, else{
PRINTF(LCD_PUTC, SEC); PRINTF(LCD_PUTC,
"%02d:%02d:%02d", } "%02d:%02d", AHOUR,
HOUR, MIN, SEC); else{ AMIN);
} PRINTF(LCD_PUTC, }
if(BIT_TEST(AM)){ "%02d:%02d:%02d",
LCD_PUTC("AM"); HOUR, MIN, SEC); if(BIT_TEST(AMA)){
} } LCD_PUTC("AM");
else{ }
LCD_PUTC("PM"); if(BIT_TEST(AM)){ else{
} > José Zabala: LCD_PUTC("AM"); LCD_PUTC("PM");
LCD_GOTOXY(1,2); } }
LCD_PUTC("ALARMA else{ break;
"); LCD_PUTC("PM"); }
}
if(AHOUR == 0){ case(5):{
PRINTF(LCD_PUTC, break;
"12:%02d", AMIN); } lcd_gotoxy(1,1);
} printf(LCD_PUTC,
case(3):{ "TEMPERATURA");
else{ LCD_GOTOXY(1,1);
PRINTF(LCD_PUTC, LCD_PUTC("CONFIG. lcd_gotoxy(1,2);
"%02d:%02d", AHOUR, FECHA"); printf(LCD_PUTC,
AMIN); LCD_GOTOXY(1,2); "%0.1f\n", tempC);
} LCD_PUTC("FECHA "); lcd_gotoxy(7,2);
PRINTF(LCD_PUTC, printf(lcd_putc, "C\n");
if(BIT_TEST(AMA)){ "%02d/%02d/20%02d",
LCD_PUTC("AM"); DAY, MONTH, YEAR); lcd_gotoxy(10,2);
} break; printf(LCD_PUTC,
else{ } "%0.1f\n", tempF);
LCD_PUTC("PM"); lcd_gotoxy(16,2);
} case(4):{ printf(lcd_putc, "F\n");
break; LCD_GOTOXY(1,1);
LCD_PUTC("CONFIG. break;
} ALARMA"); }
void TEMP(){
} //Cargar los datos de la
} set_adc_channel(0); //SE EEPROM
CONFIGURA EL CANAL LOAD_EEPROM();
void TIMERCALC(){ 0 COMO ENTRADA DELAY_MS(1);
//Rutina para calcular a = read_adc(); // SE //Y un milisegundo
cuando pasa un LEE LA TENSION después de cargarlos,
segundo. //tempC = /10.0; // SE mostrar la información
if(DISPN == 8){ DIVIDE EL VALOR DE en la LCD.
ENTRADA ENTRE 10 DISPLCD();
COUNTSEC++; PARA OBTENER EL
ALARMTONE(); VALOR DE LA PORTB = DISPLAY[0];
DISPN = 0; TEMPERATURA DISPN = 0;
if(COUNTSEC == 50){ tempC = COUNTSEC = 0;
COUNTSEC = 0; ((a*500.0)/1023.0); BTNCNT = 0;
tempF = (tempC*1.8) + SWFLAGS = 0;
if(MODE < 2){ 32; //SE HACE SU FLAGS = 0;
SEC++; CONVERSION A SETUP_COUNTERS(RT
} GRADOS FARENHEIT CC_INTERNAL,
} RTCC_DIV_16);
BIT_CLEAR(ALARM_O
if(SEC >= 60){ void main(){ N); //Establecer la
SEC = 0; #ZERO_RAM alarma en APAGADA por
MIN++; defecto.
TIMECALC(); SET_TRIS_B(0); SET_RTCC(108);
} SET_TRIS_C(15); ENABLE_INTERRUPTS(
SET_TRIS_D(0); INT_RTCC);
DISPLCD(); //Se SET_TRIS_E(0); ENABLE_INTERRUPTS(
actualiza el LCD una vez PORTC = 0x00; GLOBAL);
por segundo, para no PORTE = 0x00; setup_ccp2(CCP_PWM);
sobrecargarlo (además //Configura el CCP2 para
de que como muestra los setup_adc_ports(AN0); trabajar en PWM
segundos de la hora, es setup_adc(ADC_CLOCK setup_timer_2(T2_DIV_
necesario actualizarlo _INTERNAL); //SE BY_4,0xF9,1);
una vez por segundo. CONFIGURA EL RELOJ //Prescalador del TMR2
} INTERNO DEL ADC en 16 y contador 249
} para f=1KHz
} //Inicializar el LCD SET_PWM2_DUTY(0);
LCD_INIT(); MODE = 0;
DIAGRMA DE FLUJO
Conclusión

En resumen, un reloj-alarma-calendario con módulo LCD 16x2 y sensor de temperatura es


un proyecto de electrónica emocionante y educativo que combina la funcionalidad de
cuatro dispositivos en uno. Este proyecto es una excelente manera de aprender sobre la
programación de microcontroladores y la electrónica en general, así como de medir la
temperatura ambiente.

También podría gustarte