Autor Tema: Contador 9999 display 7 segmentos con timer1  (Leído 3756 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado ALFREDOSKY

  • PIC16
  • ***
  • Mensajes: 118
Contador 9999 display 7 segmentos con timer1
« en: 22 de Enero de 2020, 17:05:14 »
Hola a todos, he implementado un contador de 0-9999 usando un decodificador BCD con un oscilador externo de 10MHz, un pic 16f876a y dos botones, INICIO, STOP; la idea es detener, reiniciar y resetear la cuenta de acuerdo los botones; el problema es que uso el TIMER1 para realizar la cuenta, pero me topo con como detener/reiniciar/resetear el timer para realizar las operaciones descritas, segun leo en los foros no es posible detener el timer1, he leido la documentacion y se puede habilitar el timer1 mediante TMR1ON, pero no me queda claro el funcionamiento mediante este bit; lo que he pensado realizar es, por ejemplo al presionar STOP, capturar el contenido de los registros LOW y HIGH del timer1 en dos variables y trabajar con eso, pero tengo muchas dudas; por favor si alguien ha implementado un contador con las caracteristicas similares a las detalladas y tiene algunas ideas que pueda compartir se lo agradecería mucho, saludos.  :lol:

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #1 en: 22 de Enero de 2020, 20:16:55 »
Que tal ALFREDOSKY,

El timer1 lo usas como timer para generar tiempo e incrementar el contador, (por ejemplo cada segundo)? O Usas el timer 1 como contador en sí usando el pin externo del microcontrolador como entrada del timer1?

Me imagino que estás usando lenguaje C para esto, ¿podrías decirnos cual compilador estás usando (CCS, XC8, Mikroe)?

Podrías compartir tu códico para poder ayudarte mejor?

elreypic.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #2 en: 23 de Enero de 2020, 06:06:33 »
La entrada del timer1 en ese micro es el pin RC1. Yo lo que haría sería poner ese pin a GND.

 Luego se puede poner la cuenta en marcha seleccionando el oscilador interno como fuente de pulso con su correspondiente prescalador si lo necesitas.   

  Para parar la cuenta seleccionas como fuente el pin externo. Como está a gnd pues la cuenta se queda detenida.

 Por último para resetear pues fijas manualmente a cero los dos registros tmrh y tmrl.

  Como dice Elreypic faltan datos de cómo haces funcionar el Timer, si tienes un oscilador externo como fuente de conteo, etc... 
 

 


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #3 en: 23 de Enero de 2020, 08:02:00 »
La entrada del timer1 en ese micro es el pin RC1. Yo lo que haría sería poner ese pin a GND.
Para parar la cuenta seleccionas como fuente el pin externo. Como está a gnd pues la cuenta se queda detenida.

Para que complicarse la vida?, si el Timer1 tiene un bit para pararlo y activarlo.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #4 en: 23 de Enero de 2020, 12:15:31 »
La entrada del timer1 en ese micro es el pin RC1. Yo lo que haría sería poner ese pin a GND.
Para parar la cuenta seleccionas como fuente el pin externo. Como está a gnd pues la cuenta se queda detenida.

Para que complicarse la vida?, si el Timer1 tiene un bit para pararlo y activarlo.

  Puede ser el bit 3 (T1oscen) que apaga el oscilador propio del timer1 , pero habría que ver si está usando ese oscilador.

  El otro bit es el cero TMR1ON. Pero ese bit realmente no sirve para que se pare el Timer sino para apagar el módulo completamente por lo que habría que probar a ver qué pasa con los valores que tengan los registros, si se mantienen y si al volver a encender el Timer no empieza de cero.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #5 en: 23 de Enero de 2020, 13:02:21 »
  El otro bit es el cero TMR1ON. Pero ese bit realmente no sirve para que se pare el Timer sino para apagar el módulo completamente por lo que habría que probar a ver qué pasa con los valores que tengan los registros, si se mantienen y si al volver a encender el Timer no empieza de cero.

Estas equivocado, el TMR1ON maneja el reloj del contador nada mas. Te dejo el diagrama:


Desconectado ALFREDOSKY

  • PIC16
  • ***
  • Mensajes: 118
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #6 en: 23 de Enero de 2020, 15:44:06 »
Gracias por sus respuestas elreypic2, remi04 y KILLERJC; Si, estoy usando lenguaje C con el compilador XC8, y uso el Timer1 como temporizador, empleo un cristal de 10 MHz como oscilador externo. Como me comentas remi04, podria probar T1OSCEN y TMR1ON para ver como se comporta la aplicación, haré unas pruebas; por otro lado, entendiendo un poco mas como lograr lo que deseo hacer, al parecer no sería necesario detener el timer1, se puede dejarlo correr y mas bien trabajar con la visualizacion empleando una variable que envie por el puerto D (puerto usado para enviar 4 bits bcd y 4 bits de control de switcheo con transistores), esta variable debe alojar el valor instantaneo y es ésta que debe reiniciarse/parase/limpiarse, ¿que les parece ese razonamiento? ; les comparto el codigo que he escrito, aun no estan implementados los botones START y STOP, pero la logica a plasmar sería como lo comenté lineas arriba, considerar que utilizo el decodificador bcd a 7 segmentos cd4511, saludos.

Código: [Seleccionar]
/*
*CRONOMETRO DE 4 DISPLAYS DE 7 SEGMENTOS, CUENTA 0 - 9999
*CONFIGURACION DE BITS PARA MICROCONTROLADOR PIC DE 8 BITS 16F876A, DECODIFICADOR DE BCD A 7 SEGMENTOS CD4511
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//CRISTAL DE 10Mhz (10000000 Hz)
#define _XTAL_FREQ  10000000

/*Configuration Bits*/
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON         // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)


//VARIABLES GLOBALES
char BCDNumeros[] = {0,1,2,3,4,5,6,7,8,9};
char contint = 0;
char _unidades = 0;
char _decenas = 0;
char _centenas = 0;
char _millares = 0;
char temp;

//PROTOTIPO DE FUNCIONES
void IniciarTimer1(void);
void interrupt Timer1(void);
void ControlCuenta(void);
void Contador(void);

//PROGRAMA PRINCIPAL
int main(int argc, char** argv) {

    //PUERTO D COMO SALIDA
    TRISD = 0;
   
//INICIALIZACION DE SALIDA EN CERO
PORTD = 0;

    //DECLARACION DE VARIABLES LOCALES
    char _switch = 0x10;    //CHAAR EN BITS -> 0001 0000
    char *bcd = NULL; //INICIALIZACION DE PUNTERO A TIPO DE DATO CHAR

    //bcd ES UN PUNTERO A LA POSICION DEL PRIMER ELEMENTO DEL ARREGLO BCDNumeros
    bcd = &BCDNumeros;

    //INICIAR TIMER1
    IniciarTimer1();

    while(1){

        //USANDO LOS 8 BITS DEL PUERTO D, LOS 4 BITS MAS SIGNIFICATIVOS CONTROLAN LOS TRANSISTORES DE CONMUTACION
        //LOS 4 BITS MENOS SIGNIFICATIVOS SON LOS NUMEROS BCD
        temp = *(bcd + _unidades) + _switch;
        PORTD = temp;
        _switch = _switch<<1;
        __delay_ms(10);

        temp = *(bcd + _decenas) + _switch;
        PORTD = temp;
        _switch = _switch<<1;
        __delay_ms(10);
       
temp = *(bcd + _centenas) + _switch;
        PORTD = temp;
        _switch = _switch<<1;
        __delay_ms(10);
       
temp = *(bcd + _millares) + _switch;
        PORTD = temp;
        _switch = 0x10;
        __delay_ms(10);

//CONTROL DE LA CUENTA
        ControlCuenta();
    }

    return (EXIT_SUCCESS);
}

//INICIALIZA EL TIMER1
void IniciarTimer1(void){
    T1CONbits.T1CKPS0 = 1;  //Preescaler 1:8
    T1CONbits.T1CKPS1 = 1;  //Preescaler 1:8
    T1CONbits.TMR1CS = 0;   //Timer1 como temporizador
    T1CONbits.T1OSCEN = 0; //BIT DE CONTROL DEL OSCILADOR DEL TIMER1 EN 0, NO SE USARA EL OSCILADOR
    T1CONbits.TMR1ON = 1;   //Interrupcion por debordamiento del Timer1 habilitado

    INTCONbits.GIE = 1; //HABILITACION DE INTERRUPCIONES GLOBALES
    INTCONbits.PEIE = 1;

    PIR1bits.TMR1IF = 0; //INICIALIZA EN 0 EL FLAG DE INTERRUPCION DEL TIMER1
    PIE1bits.TMR1IE = 1;    //Habilitar interrupcion desbordamiento timer1

//carga valor inicial a TMR1 (cargado 3036 para lograr 0.25seg)
    TMR1L = 0xDC;    //REGISTRO LOW DEL TIMER1
    TMR1H =0x0B; //REGISTRO HIGH DEL TIMER1
}

//INTERRUPCION POR DESBORDAMIENTO DEL TIMER1
void interrupt Timer1(void){
    if(PIR1bits.TMR1IF){ //CUANDO TIMER1 SE DESBORDA LOGRA EL EQUIVALENTE A 0.25 SEGUNDOS SE LLAMA A LA FUNCION CONTADOR()
        Contador();
    }
}

//CONTROL DE LA CUENTA
void ControlCuenta(void){
    switch(_unidades){
        case 10: _unidades = 0; _decenas++; break;
    }

    switch(_decenas){
        case 10: _decenas = 0; _centenas++; break;
    }

    switch(_centenas){
        case 10: _centenas = 0; _millares++; break;
    }

    switch(_millares){
        case 10: _millares = 0; break;
    }
}

//CUENTA
void Contador(void){
    PIR1bits.TMR1IF = 0;
    TMR1L = 0xDC;    //carga valor inicial a TMR1 (cargado 3036 para lograr 0.25seg)
    TMR1H =0x0B;
    contint++;   

    //1 SEGUNDO CUMPLIDO(contint=4)
    switch(contint){
        case 4: contint = 0; _unidades++; break;
    }
}

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #7 en: 23 de Enero de 2020, 18:42:55 »
Que tal ALFREDOSKY,

Para comenzar te puede decir que el tiempo que estás generando con la interrupción del Timer1 no es de 250ms o 0.25s. En realidad es de 200ms o 0.2s.
Explico el por qué.
Para generar un desborde del timer 1, este debe sobre pasar su cuenta máxima en 1, es decir cuando este llega a 65536. Pero tú inicializas el timer en 3036, por lo tanto 65536-3036 = 62500. Pero además tienes un prescalar de 1:8, lo que significa que esos 62500 cuentas se multiplican por 8, dando 500000.
Si tu cristal externo es de 10MHz, el cliclo instrucción es de 10MHz/4 = 2.5MHz; lo que quiere decir que el ciclo instrucción es de 400ns.
Por lo tanto si tienes una cuenta de 500000 multiplicado por el ciclo instrucción, es decir 500000(400ns), eso te da 0.2seg. Lo que significa que necesitas contar 5 interrupciones por desbordamiento del timer 1 en lugar de las 4 que tienes.

Por otro lado ya tiene ahí en tu función de configuración del timer 1 la instrucción para encender el timer1:

Código: [Seleccionar]
      T1CONbits.TMR1ON = 1;   //Esto enciende el timer 1 para que pueda contar, no es nada de la interrupción

Ahora bien si lo quq quieres es detener la cuenta del timer 1, solo tienes que hacerlo 0;

Código: [Seleccionar]
      T1CONbits.TMR1ON = 0;   //Apaga el el timer 1 y ya no realiza ninguna cuenta.

Ya solo queda implementar lo de los botones, y te lo voy a poner en una especie de algoritmo.

1) Timer 1 inicializado y apagado.
2) ¿Se ha presionado el botón de INICIO(START) (nivel bajo del botón)?
     Sí, entonces enciende el timer 1, con la instrucción antes mencionada
3) ¿Se ha presionado el botón de PARO(STOP) (Nivel bajo del botón)?
     Sí, entonces apaga el timer 1, con la instrucción antes mencionada.

Si conectas los botones en el puerto B del microcontrolador puedes activar las resistencias de pull-up internas y solo conectas los pulsadores directamente al puerto.
De esta manera cuando no está presionado el botón leeras un nivel lógico alto, y cuando se presiona leerás un nivel lógico bajo.
El algoritmo o secuencia descrita anteriormente la puedes implementar dentro de tu ciclo while(1), que es donde estás mostrando el valor de tu contador actual.

Espero esto te sirva.

elreypic.

Desconectado ALFREDOSKY

  • PIC16
  • ***
  • Mensajes: 118
Re:Contador 9999 display 7 segmentos con timer1
« Respuesta #8 en: 23 de Enero de 2020, 19:07:01 »
elreypic2 tienes razón, el tiempo es de 0,2s, voy a corregir la cuenta, que sea hasta 5  ((:-)) ;implementaré la logica que me sugieres para los botones y las resistencias internas de pull up, voy a ir probando y actualizando los resultados, muchas gracias por tu tiempo y ayuda.  :-/