¿Cómo manipular este algoritmo de reloj en pic16f877?

Hola a todos cómo van?

Pues he estado trabajando en este reloj; pero tengo problemas para anexarlo a otro programa principal, lo que quiero hacer es vincularlo con el menú de otro programa para que por ejemplo cuando yo oprima una tecla, el reloj se active o se detenga, y pueda tener la capacidad de reanudar el conteo....así como está el algoritmo actualmente; comienza a contar automáticamente y lo que necesito es poder controlarlo....

Agradezco si alguno de ustedes me puede ayudar con éste programa.....

Un saludo...........

NOTA:
El código del que les hablo es el siguiente

#include <16f877a.h> // Selecciona el PIC
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT // Opciones de configuración
#use standard_io(C) // PORTB en estandar IO digital
#use fixed_io(c_outputs=PIN_C0,PIN_C1,PIN_C2,PIN_C3,PIN_C4,PIN_C5,PIN_C6,PIN_C7)
#use delay(clock=4000000) // Velocidad del Cristal : 4 Mhz
#include <kbd.c>
char const RTCCxS=15; // Número de RTCC's para 1 segundo con 4 Mhz / 1:256.

// VARIABLES GLOBALES

int nRTCC=0x00; // Contador de interrupciones RTCC completas
int segundo=0x0; // Segundos del Reloj
int minuto=0x0; // Minutos del Reloj
int D1=0x00; // Contenido de los Displays
int D2=0x00;
int D3=0x00;
int D4=0x00;
int l_digit, h_digit; // Resultado de la conversión bin2bcd
int i,tecla; // index general

void testdisplays(void); // Función que testea los displays
void display_reloj(void); // Función que muestra el contenido del reloj
void time2bcd(void); // Función que convierte minutos y segundos a 4 x BCD
void bin2bcd(int bcd); // Función que convierte de Binario a BCD
void reloj(void);



#int_RTCC // Interrupción por desbordamiento
RTCC_isr() { // del TIMER0 RTCC

if(++nRTCC==RTCCxS){
nRTCC=0x00;
if(++segundo>59){
segundo=0;
}
}
}

void main() {

kbd_init();
tecla=kbd_getc();
if (tecla=='C'){
reloj();
}
}

void reloj(void){
int ksegundo=0x00;
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno y Preescaler
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_RTCC);// Habilito Interrupción RTCC
enable_interrupts(global); // Habilito Interrupciones

do{ // Bucle infinito

if(segundo!=ksegundo){ // si cambia el segundo actualizo las
time2bcd(); // variables con lo que hay que mostrar
ksegundo=segundo;
}

display_reloj(); // Muestra constantemente

}While(TRUE);
}
//}

void display_reloj(void){ // Función que muestra el contenido del reloj

output_c(D1); // Muestro 1er carácter de segundo
output_high(PIN_C4);
delay_us(30);
output_c(D2); // Muestro 2do carácter de segundo
output_high(PIN_C5);
delay_us(30);
}

void time2bcd(void){ // Función convierte minutos y segundos a 4 x BCD

bin2bcd(segundo); // Paso de binario a BCD el segundo y actualizo
D1 = l_digit; // contenido a mostrar
D2 = h_digit;
}

void bin2bcd(int bcd){ // Función que convierte de Binario a BCD

h_digit=0;

if (bcd>=10){
do{
bcd-=10;
h_digit++;
} while (bcd>=10);
}
l_digit=bcd;
}
 
No manejo el CCS, aunque sí el C de Mplab, y creo que la estructura del programa se podría mejorar un poco. Una cosa que haría sin pensarlo mucho es hacer el bucle infinito adentro del main, algo así:

void main(void){

//instrucciones de inicialización: acá configuraria todo lo que sea escalas, bits de control,
//valores inicilales (reloj a 0 min, 0 seg, mostrar 0min 0seg en etc)
//trataría de dejar todo listo para que al presionar la tecla solo tenga que habilitar
//interrupciones y el timer. Todo lo que se ejecute una sola vez en el programa

while(1){

if(SePresionoTeclaArranque) {
ArrancarReloj();//habilitar INT y timer
}

if(cambioElSegundo){
ActualizarDisplay();//actualizar D1 y D2 por lo que ví del programa
}

Visualizar();//refresco del valor mostrado si hace falta, sino se puede meter
//adentro del if anterior

if (SePresionoTeclaParo){
PararReloj();//deshabilitar INT y timer
}

} //end while


}//end main

Bueno, solamente quería decir eso de la estructura del programa, no creo que pueda ayudar con otra cosa. Saludos
 
Del C de MPLAB tengo una versión estudiantil, me registré y la bajé.
Hay una buena cantidad de librerías para todos los periféricos, y la documentación no deja que desear.
También está el soft Application Maestro, que te genera archivos con código fuente según las librerías que quieras usar.

Por otro lado es el compilador C de microchip para PIC's, creo que son los que están en mejores condiciones para hacer el mejor compilador.
Pero también es cuestión de gustos, si uno desarrolla más fácil/rápido y con resultados similares con otro compilador como CCS o incluso Basic, no veo nada malo en eso.
 
HOla en cuanto a la respuesta que publico ardogán; realizé unos cambios en el PICC, pero temo decir que NO funciona, no sé si me puedas ayudar con eso; lo que digite fue lo siguiente:

main() {*************************menú
int ksegundo=0x00;
kbd_init();*********************se inicia el teclado************************
tecla=kbd_getc();
delay_ms(800);
if(tecla=='A'){*****************************tecla para pulsar*************
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno y Preescaler
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_RTCC);// Habilito Interrupción RTCC
enable_interrupts(global); // Habilito Interrupciones
}
//
do{ // Bucle infinito
if(segundo!=ksegundo){ // si cambia el segundo actualizo las
time2bcd(); // variables con lo que hay que mostrar
ksegundo=segundo;
}
display_reloj(); // Muestra constantemente
}
While(TRUE);//
}


void display_reloj(void){ // Función que muestra el contenido del reloj

output_c(D1); // Muestro 1er carácter de segundo
output_high(PIN_C4);
delay_us(30);
output_c(D2); // Muestro 2do carácter de segundo
output_high(PIN_C5);
delay_us(30);
}
 
Bueno, lo primero que veo es que el primer if esta fuera del bucle infinito.
Hay que ponerlo adentro porque no sabemos en que tiempo se va a presionar la tecla para arrancar el reloj, por lo tanto hay que chequearlo constantemente hasta que se pulse.
Para qué es ese retardo de 800 milisegundos?, tal vez intentaste evitar rebotes?, con el retardo solo no se logra nada, hay que chequear la entrada hasta que se estabilice. En el foro hay información sobre eso (Buscador -> rebotes).

Volviendo a la estructura del programa, yo decía meter ésto
Diederick dijo:
tecla=kbd_getc();
delay_ms(800);
if(tecla=='A'){*****************************tecla para pulsar*************
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno y Preescaler
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);

enable_interrupts(INT_RTCC);// Habilito Interrupción RTCC
enable_interrupts(global); // Habilito Interrupciones
}

dentro del loop, excepto lo que puse en negrita. O sea

void main(void){
....

  • setup_counters(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno y Preescaler
    setup_timer_1(T1_DISABLED);
    setup_timer_2(T2_DISABLED,0,1);

    do{ // Bucle infinito[list:de596358d8]
    tecla=kbd_getc();
    //delay_ms(800); anulo el delay porque no me sirve así como estaba para antirebotes
    if(tecla=='A'){// el conteo arranca cuando se pulsa la tecla A[list:de596358d8]
    enable_interrupts(INT_RTCC);// Habilito Interrupción RTCC
    enable_interrupts(global); // Habilito Interrupciones
    //Habilitar Timer0, viendo las instrucciones sería algo como setup_timer_2(T0_Enabled) ?
    }
if(tecla=='B'){// el conteo para cuando se pulsa la tecla B

  • disable_interrupts(INT_RTCC);// deshabilito Interrupción RTCC
    disable_interrupts(global); // deshabilito Interrupciones
    //desabilitar Timer0, setup_timer_2(T0_Disabled) ?
    }
if(segundo!=ksegundo){ // si cambia el segundo actualizo las

  • time2bcd(); // variables con lo que hay que mostrar
    ksegundo=segundo;
    }
display_reloj(); // Muestra constantemente
}[/list:u:de596358d8]
While(TRUE);//[/list:u:de596358d8]
}//end main

Bueno, aclaro otra vez, no sé las instrucciones con el CCS, tal vez alguien que lo use quiera revisar lo que puse (con rima y todo, já).
Fijate que el esquema que uso adentro del bucle infinito es: leer entradas (tecla)-> procesar (en este caso lo haría la interrupción)->escribir salidas (display_reloj). A veces no se puede usar este esquema de programa, pero si se puede usar es lo más fácil de implementar/entender, a mi juicio desde ya (gente con muchas más experiencia que yo en el foro podría refutarme en dos segundos, jaja).

En cuanto al tema de los rebotes, bueno primero fijate si eso anda y si hay problemas con los rebotes lo vemos. Lo que podría pasar es que al pulsar 'A' por una de esas recontra-casualidades por efecto de los rebotes aparezca como 'B', si bien en algún momento se estabiliza como 'A' y hasta acá estaría todo bien. Pero al soltar la tecla 'A' por ahí aparece transitoriamente un 'B' y termina sin arrancar. Pero no sé si la rutina kbd_getc() implementa algún tipo de antirebote.

Otra duda que me quedó es si usas la misma tecla para arrancar/parar, o si son distintas (lo de arriba lo planteé suponiendo que eran distintas).

-----------
PD: puse los espacios (identación) para que el código salga más claro pero no aparece en el mensaje publicado, aunque sí cuando lo edito. Si alguien sabe cómo hacer, avisen.
-------------
PD2: ya me dí cuenta, hay que usar
 
Hola...muchas gracias por tu corrección, ha funcionado relativamente bien, sucede que de este contador se derivan muchas variables que tengo que hacer para otro programa; así que pronto tendrás noticias mías, con nuevas inquietudes...

Un saludo....
 
Atrás
Arriba