TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: estalli2 en 09 de Agosto de 2010, 22:33:06
-
Queridos colegas, aca vengo con otra duda que tengo con la programacion en c para pic.
Estoy armando un aparato que simplemente es un contador regresivo de 60 segundos el cual debe funcionar asi:
1 solo boton que al presionarlo cuente a partir de 60 hacia 00, una vez contando si presiono el mismo boton tiene que detener la cuenta y si lo vuelvo a presionar vuelve a contar desde 60 hacia 00.
Por ahora solo vengo con lo mas simple(creo) que es la parte del contador, del cual pongo el codigo:
#include <16F628.h>
#USE DELAY( CLOCK=4000000)
#FUSES XT,NOWDT,NOPROTECT,NOPUT
#USE fast_IO (B)
#USE fast_IO (A)
byte CONST DISPLAY[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //codigo para bcd
signed char ud=0,dec=6;
char flag=0;
short soni=1;
short bott=0;
short ini=0;
void disp(void); //saca a display
void alarm(void); //alarma por puerto A3 por 5 segundos
void cuenta_reg(void); //programa de cuenta
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////programa principal
void main(void){
set_tris_b(0x00);
set_tris_a(0x10);
disable_interrupts(GLOBAL); //todas las interrupciones desactivadas
ud=read_eeprom(0); //lee los valores de ultima cuenta
dec=read_eeprom(1);
disp();
WHILE(1){
if (input(pin_A4)==1){cuenta_reg();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////rutina de salida al display/////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
void disp(void){
OUTPUT_A(0x02); //con 0 encendido en este caso unidades
OUTPUT_B(DISPLAY[ud]); //Digito unidades
delay_ms(100);
OUTPUT_A(0x01); //decenas
OUTPUT_B(DISPLAY[dec]);
delay_ms(100);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////rutina de la alarma cuando sale pone el flag en cero
///////////////////////////////////////////////////////////////////////////////////////////////////
void alarm(void){
if (soni=1){
OUTPUT_A(0x04);
delay_ms(1000);
}
soni=0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////rutina cuenta regresiva de 60 a 00//////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
void cuenta_reg(void)
{
signed char unidad,decenas;
for (decenas=5;decenas>-1;decenas--){ //Cuenta digito decenas
for (unidad=9;unidad>-1;unidad--){
OUTPUT_A(0x02); //cat_D=apagado,cat_U=encendido
OUTPUT_B(DISPLAY[unidad]); //Digito unidades
delay_ms(50); //Para evitar parpadeos
output_a(0x01); //Si decenas>0, cat_D=encendido
OUTPUT_B(DISPLAY[decenas]); //Digito decenas
delay_ms(50); //Para evitar parpadeos
}
}
}
bueno, el contador funciona ahora no tengo idea como seguir con lo demas ya que todavia no estoy muy familiarizado con los bucles for, while, if, etc.
me confundo un poco con las posibilidades de llamar subrutinas y diagramar las funciones que tendria que secuenciar el programa... :shock:
por otro lado no pense todavia como implementar las cuentas del tmr0 para manejar todo el sistema cuando lo tenga funcionando...
agradecere todo consejo-critica-etc etc...la idea es aprender de mis propios errores..
MIL GRACIAS POR ADELANTADO!!!
-
Hola estalli2
Te cuento, el código que pusiste tiene algunos errores como por ejemplo que al hacer la cuenta en un bucle, no hace otra cosa que contar y mostrar los displays, lo que estas haciendo es: decrementas la unidad en 1 y muestras los displays, decrementas otra vez y vuelves a mostrar los displays. Esto hace que la cuenta sea muy rápida.
Para contar segundos lo que tienes que hacer es precisamente eso, decrementar cada segundo y entre cuenta y cuenta, mostrar muchas veces los displays sino no verias nada, te dejo el codigo que hice, cuenta aproximadamente cada 1 segundo por medio del timer0.
#include <16F628.h>
#USE DELAY( CLOCK=4000000)
#FUSES XT,NOWDT,NOPROTECT,NOPUT
#USE fast_IO (B)
#USE fast_IO (A)
byte CONST DISPLAY[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //codigo para bcd
int Numero[2];
int Cifra;
int1 Pulso;
int1 anPulso;
int1 Flag;
int Tiempo;
#define Cat_U PIN_A0
#define Cat_D PIN_A1
#define Tecla PIN_A4
#int_rtcc
void isr(){ // cada 1024 ciclos salta esta interrupcion
if(--Tiempo>200){ // Decrementa Tiempo y se pasa de 0
Tiempo=60; // Pone Tiempo a 60
Disable_interrupts(int_rtcc); // y detiene la cuenta
Flag=False; // desactiva el flag
}
}
void main(void){
int tmp;
set_tris_b(0x00);
set_tris_a(0x10);
setup_timer_0(rtcc_internal|rtcc_div_4);
disable_interrupts(int_rtcc);
enable_interrupts(GLOBAL);
Flag=false;
WHILE(true){
tmp=tiempo/10;
Numero[1]=tmp;
Numero[0]=Tiempo-(tmp*10);
if (++Cifra>1)Cifra=0; //En cada iteracion muestra la decena o la unidad
output_high(Cat_U);
output_high(Cat_D);
OUTPUT_B(DISPLAY[Numero[Cifra]]);
if (Cifra==1)output_low(Cat_D); else output_low(Cat_U); // Activando los respectivos
// cátodos
if (Input(Tecla)) Pulso=true; else Pulso=false; // Si se pulso B4 carga pulso con true
// sino con false
if (Pulso&&!anPulso){ // Si Pulso es true y anPulso es false
// (La primera vez que detecta la pulsacion)
if (Flag){ // Si el Flag está activado
Disable_interrupts(int_rtcc); // detiene la cuenta
}else{ // Si el flag no está activado
Tiempo=60; // Pone el tiempo a 60
Enable_interrupts(int_rtcc); // y activa la cuenta
}
Flag=!Flag; // invierte el estado del flag
}
AnPulso=Pulso; // Para que detecte la pulsacion 1 sola vez.
delay_ms(10); // pausa entre iteracion e iteracion
}
}
Si hay algo que no se entienda me lo dices.
saludos.
-
Hola estalli2
Te cuento, el código que pusiste tiene algunos errores como por ejemplo que al hacer la cuenta en un bucle, no hace otra cosa que contar y mostrar los displays, lo que estas haciendo es: decrementas la unidad en 1 y muestras los displays, decrementas otra vez y vuelves a mostrar los displays. Esto hace que la cuenta sea muy rápida.
Para contar segundos lo que tienes que hacer es precisamente eso, decrementar cada segundo y entre cuenta y cuenta, mostrar muchas veces los displays sino no verias nada, te dejo el codigo que hice, cuenta aproximadamente cada 1 segundo por medio del timer0.
#include <16F628.h>
#USE DELAY( CLOCK=4000000)
#FUSES XT,NOWDT,NOPROTECT,NOPUT
#USE fast_IO (B)
#USE fast_IO (A)
byte CONST DISPLAY[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //codigo para bcd
int Numero[2];
int Cifra;
int1 Pulso;
int1 anPulso;
int1 Flag;
int Tiempo;
#define Cat_U PIN_A0
#define Cat_D PIN_A1
#define Tecla PIN_A4
#int_rtcc
void isr(){ // cada 1024 ciclos salta esta interrupcion
if(--Tiempo>200){ // Decrementa Tiempo y se pasa de 0
Tiempo=60; // Pone Tiempo a 60
Disable_interrupts(int_rtcc); // y detiene la cuenta
Flag=False; // desactiva el flag
}
}
void main(void){
int tmp;
set_tris_b(0x00);
set_tris_a(0x10);
setup_timer_0(rtcc_internal|rtcc_div_4);
disable_interrupts(int_rtcc);
enable_interrupts(GLOBAL);
Flag=false;
WHILE(true){
tmp=tiempo/10;
Numero[1]=tmp;
Numero[0]=Tiempo-(tmp*10);
if (++Cifra>1)Cifra=0; //En cada iteracion muestra la decena o la unidad
output_high(Cat_U);
output_high(Cat_D);
OUTPUT_B(DISPLAY[Numero[Cifra]]);
if (Cifra==1)output_low(Cat_D); else output_low(Cat_U); // Activando los respectivos
// cátodos
if (Input(Tecla)) Pulso=true; else Pulso=false; // Si se pulso B4 carga pulso con true
// sino con false
if (Pulso&&!anPulso){ // Si Pulso es true y anPulso es false
// (La primera vez que detecta la pulsacion)
if (Flag){ // Si el Flag está activado
Disable_interrupts(int_rtcc); // detiene la cuenta
}else{ // Si el flag no está activado
Tiempo=60; // Pone el tiempo a 60
Enable_interrupts(int_rtcc); // y activa la cuenta
}
Flag=!Flag; // invierte el estado del flag
}
AnPulso=Pulso; // Para que detecte la pulsacion 1 sola vez.
delay_ms(10); // pausa entre iteracion e iteracion
}
}
Si hay algo que no se entienda me lo dices.
saludos.
Ok! Muchas gracias! esta excelente y los comentarios me ayudaron muchisimo.
:-/ gracias de verdad!