#include <16f883.h>
#device ADC=10
#use delay(internal = 8MHz)
#define LCD_DATA_PORT getenv("SFR:PORTC")
#include <lcd.c>
#define led PIN_B5
int1 flagHayDatos=0;
float const ticks_us = 4.0; // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Interno)
//float const ticks_us = 8.0; // microsegundos por Tick del Timer 1 @ 8 MHz. (Osc. Cristal)
int8 flancos;
int8 flag_flanco;
int16 periodo1,periodo2,periodo3;
int16 tiempo_alto,tiempo_bajo,tiempo_total;
float us_alto,us_bajo,us_total;
float frecuencia;
#INT_EXT
void sdi_externa_RB0 (void)
{
flancos++; // Incrementar la variable "flancos"
if(!flag_flanco) // Si el flanco del pulso es bajo...
{
if(flancos == 1) // Si el conteo de flancos es 1...
{
set_timer1(0); // Limpiar el Timer 1
periodo1 = get_timer1(); // "periodo1" tendrá el tiempo del pulso en alto.
}
if(flancos == 3) // Si el conteo de flancos es 3...
periodo3 = get_timer1(); // "periodo3" tendrá el tiempo del pulso en alto.
EXT_INT_EDGE(H_TO_L); // Establecer la interrupción por flanco de bajada.
flag_flanco = 1; // Indicar que el próximo flanco será de bajada.
}
else // Caso contrario. (Pulso en estado alto)...
{
periodo2 = get_timer1(); // "periodo2" tendrá el valor del pulso en bajo.
EXT_INT_EDGE(L_TO_H); // Establecer la interrupción por flanco de subida.
flag_flanco = 0; // Indicar que el próximo flanco será de subida.
if(flagHayDatos==0){ // Si los datos anteriores han sido procesados ...
flagHayDatos=1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
if(flancos > 2)flancos = 0; // Si la variable "flancos" llega a 3, ponerla a 0.
}
void main()
{
long int var1=0, var2=0, var3=0;
float valor, valor1,valor2;
float duty;
int8 porcentaje;
setup_adc_ports(sAN1|sAN3);
setup_adc(ADC_CLOCK_INTERNAL );
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(int_ext);
ext_int_edge(0,L_TO_H);
enable_interrupts(global);
lcd_init();
#ZERO_RAM // Limpiar RAM. (Variables en 0)
while (true)
{
for(var1=0;var1<50;var1++)
{
valor=valor+ get_timer1();
delay_us(62);
}
periodo1=valor/50;
for(var2=0;var2<50;var2++)
{
valor1=valor1+ get_timer1();
delay_us(62);
}
periodo2=valor/50;
for(var3=0;var3<50;var3++)
{
valor2=valor2+ get_timer1();
delay_us(62);
}
periodo3=valor/50;
if(flagHayDatos==1){
output_HIGH(led);
if((periodo3 > periodo2) && (periodo2 > periodo1))
{
tiempo_alto = periodo2 - periodo1; // Obtener el periodo del pulso en estado alto.
tiempo_bajo = periodo3 - periodo2; // Obtener el periodo del pulso en estado bajo.
tiempo_total = tiempo_alto + tiempo_bajo; // Obtener el periodo de la frecuencia.
us_alto = ticks_us * tiempo_alto; // Obtener el periodo en microsegundos del pulso en alto.
us_bajo = ticks_us * tiempo_bajo; // Obtener el periodo en microsegundos del pulso en bajo.
us_total = ticks_us * tiempo_total; // Obtener los microsegundos en total de la frecuencia.
frecuencia = 1 / (us_total / 1000000); // Obtener la frecuencia.
duty = ((float) tiempo_bajo / (float)(tiempo_bajo + tiempo_alto));
porcentaje = (duty * 100) + 0.5; // Físicamente el + 0.5 puede no ser necesario. (Ajusta desviación pero consume ROM)
}
flagHayDatos=0;
}
lcd_gotoxy(1,1);
printf(lcd_putc,"CPS:%03.0fHz",frecuencia);
lcd_gotoxy(1,2);
printf(lcd_putc,"DUTY:%02u%c",porcentaje,0x25);
flagHayDatos=0;
delay_ms(100); // Retardo para disminuir parpadeos en la pantalla. (No afecta interrupción externa.)
if(flagHayDatos==0){
frecuencia = 0;
porcentaje=0;
output_low(led);
}
}
}