Re: interrupt timer ccs
#include <16F877A.h> // inclui especificações do microcontrolador em questão
#use delay(clock=4000000) //define o uso de um cristal de 4Mhz
#use I2C(MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW) // define o protocolo que vai ser usado para comunicar com o RTC e define os pinos do PIC a serem utilizados para linha de clock e dados, sendo forçados por hardware
#use fast_io(C) //define rápida comutação de estado nos pinos para input/output
#define use_portd_lcd TRUE //define para porta a usar para comunicar com o LCD, porta D
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD // XT -CRISTAL <=4Mhz, NOPROTECT -SEM PROTECÇÃO CONTRA LEITURA, NOPUT -SEM TEMPORIZAÇÃO DE POWER UP, NOWTD -SEM WATCHDOG, NOBROWNOUT -SEM REST DE BROWNOUT, NOLVP -SEM PROGRAMAÇÃO DE BAIXA VOLTAGEM,PINO RB3 PARA i/o, NOCPD -SEM PROTECÇÃO DA MEMÓRIA EE
#include <lcd.c> //inclui a livraria do LCD - comum a muitos LCD´s - livraria geral
#include <pcf8583.c> // inclui livraria criada para comunicar com o RTC
#byte port_b=240 // estabelece pinos 4,5,6 e 7 do porto B como entradas de alta impedância 11110000
static int tecla; // valor que a varável tecla toma quando se prime um dos interruptores
int y=1; // x/y - coordenadas para escrita no LCD
int x=1;
int tempo; // varável usada para fazer a mensagem de alarme no LCD durar cerca de 10 seg
int ahora=0,amin=0,aaseg=0,adia=1,ames=1; // varáveis usadas para definir quando queremos activar o alarme
int aset=0; // flag de alarme - 1-activo / 0-desactivado
void menus(void);
void menus_2(void);
void menus_3(void);
void menus_4(void);
///////////////////////////////////////////////////////////////////////////////
// ROTINA DE INTERRUPCAO POR TECLADO NOS PINOS RB4 A RB7
// DETECTAMOS TECLA PULSADA
///////////////////////////////////////////////////////////////////////////////
#INT_RB
void tecla_pulsada(void)
{
if(!(port_b^0xF0))
return; //saida ao soltar a tecla da interrupcão
if((!input(PIN_B7)))
{
tecla=1; //enter/acertar alarme de horas
return;
}
if((!input(PIN_B6)))
{
tecla=2; //set down / acertar data
return;
}
if((!input(PIN_B5)))
{
tecla=3; //set up / acertar alarme de data
return;
}
if((!input(PIN_B4)))
{
tecla=4; //tecla para acertar relógio
return;
}
}
void ini ()
{
lcd_init();
delay_ms(2);
x=1;y=1; // Carregar Posicao
lcd_gotoxy(x,y); // Mandar lcd Posicao
printf(lcd_putc," Programador "); // Escreve Lcd
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc," Semanal ");
delay_ms(2000);
printf(lcd_putc,"\f" ) ;
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Ave_Rapina " ) ;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc," LAB-SIS" ) ;
delay_ms(2000);
printf(lcd_putc,"\f" ) ; // Limpa
x=1;y=1;
lcd_gotoxy(x,y);
}
void led () // função para testar se o Led funciona mal o programa arranca
{
tempo=0;
while (tempo!=2)
{
tempo++;
output_high(Pin_c0);
delay_ms(65);
output_low(Pin_C0);
delay_ms (65);
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//MAIN
//
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
//habilita interrupções
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
port_b_pullups(TRUE);
lcd_init();
h.horas=23; h.minutos=59; h.segundos=00; //coloca-se uma hora H:M:S
h.dia=1; h.mes=1; //coloca-se uma data D/M
escrever_no_relogio(&h); //rotina para escrever PCF8583 em I2C
set_tris_c (0xFE); // Porta C0 como saida
output_low (Pin_C0);
ini();
led();
while(true)
{
lcd_gotoxy(1,1);
ler_todo_o_relogio(&h);
lcd_putc("\f");
if(h.mes==21) // ao passar de 23:59:00 -> 00:00:00 de Jan->Fev , Fev->Mar, Mar->Abr, etc ,etc
h.mes=1; // ao valor dO mês o RTC soma +20 até Setembro e +30 de Outubro a Dezembro
if(h.mes==22) // daí ser preciso corrigir o valor da varável mês para que apareça o valor correcto.
h.mes=2; // no datasheet, não faz referência a este fenómeno, nem foi encontrada qualquer explicação
if(h.mes==23) // mas solucionou-se assim.
h.mes=3; // Ao passar de ano soma +40 ao valor do dia, passando o dia 1 de Jan a se o dia 41!!
if(h.mes==24) // Resolveu-se da mesma forma.
h.mes=4;
if(h.mes==25)
h.mes=5;
if(h.mes==26)
h.mes=6;
if(h.mes==27)
h.mes=7;
if(h.mes==28)
h.mes=8;
if(h.mes==29)
h.mes=9;
if(h.mes==30)
h.mes=10;
if(h.mes==31)
h.mes=11;
if(h.mes==32)
h.mes=12;
if(h.dia==41)
h.dia=1;
lcd_gotoxy(1,1);
printf(lcd_putc,"%i/%i - %i:%i:%i" ,h.dia,h.mes,h.horas,h.minutos,h.segundos);
lcd_gotoxy(1,2);
if(aset==1) // verifica se o alarme foi activado
printf(lcd_putc,"AL %i/%i - %i:%i" ,adia,ames,ahora,amin);// mostra a hora e data para que o alarme foi activado
else
printf(lcd_putc,"Alarme OFF"); // se o alarme não foi activado
if (aset==1) // verifica se o alarme foi activado
{
if ((h.horas==ahora) & (h.minutos==amin) & (h.dia==adia) & (h.mes==ames)) //verifica se as variáveis de alarme são iguais às definidas por nós
{
printf(lcd_putc,"\f") ;
x=1;x=2; lcd_gotoxy(x,y); printf(lcd_putc," ***ALARME*** ");
tempo=0;
while (tempo!=375)
{
aaseg++;
tempo++;
output_high(Pin_c0); // acende intermitentemente o led durante 10 seg
delay_ms(40);
output_low(Pin_C0);
delay_ms (40);
}
if (aaseg==375)
{
aaseg=0;
x=1;x=2;
lcd_gotoxy(x,y);
lcd_putc("\f");
lcd_putc("Alarme OFF"); //avisa que o alarme está OFF
delay_ms (2000);
}
aset=0; //coloca a variável de alarme a 0-desactivada
}
}
switch(tecla) //verifica se foi premido qualquer interruptor
{
case 1: //carregando tecla enter acerta o alarme de horas
tecla=0;
aset=1;
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc,"Alarme horas ON ");
delay_ms (2000);
menus_3();
break;
case 2: //carregando tecla INC acerta o alarme de data
tecla=0;
aset=1;
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc,"Alarme data ON ");
delay_ms (2000);
menus_4();
break;
case 3: //ajusta data
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc,"Acerto dia/mes ");
delay_ms (2000);
menus_2();
break;
case 4: //ajusta relógio
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc,"Acerto da hora ");
delay_ms (2000);
menus(); break;
default:
} //fim do swicth
delay_ms(900);
} //fim while
} //fim do main
void menus(void) //função para acertar horas e minutos no RTC
{
tecla=0; //coloca o valor da variável que corresponde à tecla premida a 0
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte minutos ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",h.minutos);
h.segundos=0;
if(tecla==3) // se for premida a tecla para decrementar
{
tecla=0;
h.minutos--; //decrementa valor
if( h.minutos == -1) // ao chegar a 0 desce para 59 minutos
h.minutos=59;
escrever_no_relogio(&h); // função para escrever no relógio em I2C
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",h.minutos); // actualiza no LCD os minutos
}
if(tecla==2) //se for premida a tecla incrementar
{
tecla=0;
h.minutos++; // incrementa o valor dos minutos
if(h.minutos>=60) // ao chegar ao valor 59 passa para 0
h.minutos=0;
escrever_no_relogio(&h); // escreve no RTC em I2C
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",h.minutos); // actualiza no LCD os minutos
}
if(tecla==1) // ao carregar enter acerta-se as horas da mesma maneira
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte horas ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",h.horas);
if(tecla==3)
{
tecla=0;
h.horas--;
if( h.horas== -1)
h.horas=23;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",h.horas);
}
if(tecla==2)
{
tecla=0;
h.horas++;
if(h.horas>=24)
h.horas=0;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",h.horas);
}
if(tecla==1)
break;
delay_ms(200); //tempo de espera para se poder visualizar
} //fim do while
break;
} //fim if tecla ==1
delay_ms(200);
} //fim do while.
tecla=0;
return;
}
void menus_2(void) // função para acertar dia e mês - idêntica à anterior
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte dia ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Dia: %i",h.dia);
if(tecla==3)
{
tecla=0;
h.dia--;
if( h.dia == 0) // passa do dia 1 para 31 ao decrementar
h.dia=31;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Dia: %i",h.dia);
}
if(tecla==2)
{
tecla=0;
h.dia++;
if(h.dia>=32) // passa do dia 31 para dia 1 ao incrementar
h.dia=1;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Dia: %i",h.dia);
}
if(tecla==1)
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte mes ");
lcd_gotoxy(1,2);
printf(lcd_putc,"Mes: %i",h.mes);
if(tecla==3)
{
tecla=0;
h.mes--;
if( h.mes== 0) // passa de mês 1 para 12 ao decrementar
h.mes=12;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Mes: %i",h.mes);
}
if(tecla==2)
{
tecla=0;
h.mes++;
if(h.mes>=13) // passa de mês 12 para 1 ao incrementar
h.mes=1;
escrever_no_relogio(&h);
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Mes: %i",h.mes);
}
if(tecla==1)
break;
delay_ms(200);
} //fim do while
break;
} //fim if tecla ==1
delay_ms(200);
} //fim do while.
tecla=0;
return;
}
void menus_3(void) // função para acertar horas e minutos em que se pretende activar o alarme
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte minutos ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",amin);
h.segundos=0;
if(tecla==3)
{
tecla=0;
amin--; // variável "amin" que vai ser comparada com h.minutos que representa o tempo do RTC
if( amin == -1)
amin=59;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",amin);
}
if(tecla==2)
{
tecla=0;
amin++;
if(amin>=60)
amin=0;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Minutos: %i",amin);
}
if(tecla==1)
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte horas ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",ahora);
if(tecla==3)
{
tecla=0;
ahora--; //// variável "ahora" que vai ser comparada com h.minutos que representa o tempo do RTC
if( ahora== -1)
ahora=23;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",ahora);
}
if(tecla==2)
{
tecla=0;
ahora++;
if(ahora>=24)
ahora=0;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"Horas: %i",ahora);
}
if(tecla==1)
break;
delay_ms(200);
} //fim do while
break;
} //fim if tecla ==1
delay_ms(200);
} //fim do while.
tecla=0;
return;
}
void menus_4(void) // função para acertar dia e mês em que se pretende activar o alarme (idêntica à anterior)
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte dia ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"dia: %i",adia);
if(tecla==3)
{
tecla=0;
adia--;
if( adia == 0)
adia=31;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"dia: %i",adia);
}
if(tecla==2)
{
tecla=0;
adia++;
if(adia>=32)
adia=1;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"dia: %i",adia);
}
if(tecla==1)
{
tecla=0;
while(true)
{
lcd_putc("\f");
x=1;y=1;
lcd_gotoxy(x,y);
printf(lcd_putc," Acerte mes ");
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"mes: %i",ames);
if(tecla==3)
{
tecla=0;
ames--;
if( ames== 0)
ames=12;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"mes: %i",ames);
}
if(tecla==2)
{
tecla=0;
ames++;
if(ames>=13)
ames=1;
x=1;y=2;
lcd_gotoxy(x,y);
printf(lcd_putc,"mes: %i",ames);
}
if(tecla==1)
break;
delay_ms(200);
} //fim do while
break;
} //fim if tecla ==1
delay_ms(200);
} //fim do while.
tecla=0;
return;
}
///////////////////////////
//pcf8583.c
#define escrever_relogio 0b10100000 //0xA0 - comando para escrita
#define ler_relogio 0b10100001 //0xA1 - comando para leitura
struct Hora //estrutura para armazenar os valores do tempo
{
byte horas;
byte minutos;
byte segundos;
byte dia;
byte mes;
byte ano;
};
struct Hora h;
///////////////////////////////////////////////////////////////////////////////
// Função para passar de binário puro a BCD
// (os dados do relógio estão em BCD)
//////////////////////////////////////////////////////////////////////////////
byte bin_a_bcd(byte binario)
{
return (((binario/10) << 4) + binario%10);
}
///////////////////////////////////////////////////////////////////////////////
// Função para passar de BCD a binário puro
// (os dados do relógio estão em BCD)
//////////////////////////////////////////////////////////////////////////////
byte bcd_a_bin(byte bcd)
{
return (((bcd >> 4)*10) + (bcd & 0x0F));
}
////////////////////////////////////////////////////////////////////////////////
//Registo de controlo
////////////////////////////////////////////////////////////////////////////////
void registo_controlo(byte dado)
{
i2c_start();
i2c_write(0xA0),// para configurar o registo de controlo
i2c_write(0x00);// para começar a escrever no RTC
i2c_write(dado);
i2c_stop();
}
///////////////////////////////////////////////////////////////////////////////
// Funcão para ler um byte do relógio mediante bus i2c
///////////////////////////////////////////////////////////////////////////////
byte ler_byte(byte direccao)
{
byte dado;
i2c_start();
i2c_write(escrever_relogio);
i2c_write(direccao);
i2c_start();
i2c_write(ler_relogio);
dado=i2c_read(0);
i2c_stop();
return dado;
}
////////////////////////////////////////////////////////////////////////////////
// Funcão para ler o relógio, horas, minutos, segundos, dia e mês
// Estos dados estão armazenados numa estrutura.
////////////////////////////////////////////////////////////////////////////////
void ler_todo_o_relogio(struct Hora *h)
{
byte dado;
dado = ler_byte(0x02); //lemos os segundos
h->segundos = bcd_a_bin(dado); //passamo-los de bcd a binario e armazenamos
dado = ler_byte(0x03); //ler minutos
h->minutos = bcd_a_bin (dado);
dado = ler_byte(0x04); //horas
h->horas = bcd_a_bin(dado);
dado = ler_byte(0x05); //dias
h->dia = bcd_a_bin(dado);
dado = ler_byte(0x06); //mes
h->mes = bcd_a_bin(dado & 0x3f);
i2c_stop();
}
////////////////////////////////////////////////////////////////////////////////
// Funcão para por a hora no relógio
// escreve no relógio, mediante bus i2c
////////////////////////////////////////////////////////////////////////////////
void escrever_no_relogio(struct Hora *h)
{
byte dado=0;
i2c_start();
i2c_write(escrever_relogio);
i2c_write(0x01);
i2c_write(dado); //centesimas de segundo a zero...por defeito
dado = bin_a_bcd(h->segundos);
i2c_write(dado);
dado = bin_a_bcd(h->minutos);
i2c_write(dado);
dado = bin_a_bcd(h->horas);
i2c_write(dado);
dado = bin_a_bcd(h->dia);
i2c_write(dado);
dado = bin_a_bcd(h->mes);
i2c_write(dado);
i2c_stop();
}
////////////////////////////////////////////////////////////