Frecuencimetro y pantalla lcd con pic

adjunto una nota de aplicacion de microchip donde esta el programa de un frecuencimetro de
50 mhz en ensamblador, espero que alguien que sepa ensamblador explique un poco como funciona para hacerlo en c18 para un pic182525 que es el que tengo.
 

Adjuntos

  • frec_microchip.pdf
    130.3 KB · Visitas: 237
Saludos, es la primera vez que escribo en el foro, se podria decir que soy nuevo, aunque mi cuenta ya tiene años de creada :LOL:.
Bueno respondiendo a tu inquietud, si revisas la hoja de datos del microcontrolador verás en las ultimas hojas el cuadro: "TIMER0 AND TIMER1 EXTERNAL CLOCK REQUIREMENTS", que son las caracteristicas de los contadores del pic, ahi verás claramente que el mínimo ancho de pulso que puede medir el timer0 es de 10ns y el timer1 es de 30ns(timer0 es mas preciso); si utilizas el timer0 como contador extern, entonces podrás medir como máximo un periodo de 20ns, esto equivale a 50Mhz, esto en teoria y dependerá del pic en particular, algunos alcanzan mucho mas(60, 70Mhz).
Existen varias tecnicas, unas mas complejas que otras para hacer hacer un frecuencimetro usando el TMR0.
Ahora con respecto a la nota de microchip; utiliza una tecnica para alcanzar a medir altas frecuencias sin perder mucha resolucion, y consiste en usar el TMR0 y su preescaler, de manera que al final de la cuenta unes los dos valores que obtengas del TMR0 y el preescaler, para obtener el conteo exacto. Tanto el TMR0 como su preescaler tienen un tamaño de 8bits de manera que juntos hacen un contador de 16 bits, de manera que los dos juntos pueden contar hasta 65,536 cuentas(Hz).
Suponiendo que usas el preescaler a su maximo valor que es 256, entonces cada 256 cuentas el preescaler se desbordará a cero e incrementará en uno el TMR0.
Ahora, lamentablemente el valor del preescaler no se puede leer por software :rolleyes:; pero de nota de microchip AN592, muestra la unica tecnica para leer el valor del preescaler y consiste en usar un pin mas del pic.
Suponiendo que estas usando ademas del TOCKI, el pin RA3; inicialmente declaras como entrada el pin RA3, una ves terminado el tiempo de medicion declaras como salida el pin RA3 y lo pones en bajo, esto anulará la señal que estas midiendo. Una ves llevado a bajo el pin RA3, comienzas a hacer transiciones de alto a bajo en el pin RA3, y revisas si el TMR0 se ha incrementado en cada transicion, si no continúas hasta que se incremente el TMR0, una ves detectado el incremento del TMR0, lo que tienes que hacer(tienes que usar preescaler a 256) restar a 256 el numero de transiciones que hiciste en el pin RA3 para que se incremente el TMR0.
Esto es así:
Valor del preescaler = 256 - N(número de transiciones de H-L en el pin RA3).
Luego concatenas el valor de TMR0 con el valor del preescaler para obtener la cuenta real.
Si quieres mas precicion puedes usar la interrupcion del TMR0 de manera que cada ves que se desborde el TMR0, incrementes un tercer registro, uniendo este con el TMR0 y el preescaler obtienes un contador de 24 bits de manera que puedes contar hasta 16,777,216 cuentas(hz) con un tiempo de conteo de 1 segundo.
Ahora toda la explicacion que te he hecho es para un pic 16F :LOL:, no conozco mucho los 18F, pero supongo que tambien se puede aplicar(y).
Y si no te quieres complicar con los codigos y si solo quieres medir maximo hasta unos 120 khz, pues puedes usar el BASIC para pic, que tiene una instruccion que no usa el TMR0, y cuenta hasta 125KHz usando un crystal de 20MHz, de manera que en una sola linea de codigo de basic ya obtienes la cuenta :eek:.
Yo me inicie con assembler, ahora uso tanto el basic como el C, para programar pics.
Bueno espero haberte sacado de dudas, cualquier consulta no dudes en hacerlas que estamos para apoyarnos:apreton:.
 
Aca unas fotos de la simulacion de un frecuencimetro que usa la tecnica del AN592 de microchip.

http://imageshack.us/photo/my-images/401/1hz.png/
http://imageshack.us/photo/my-images/20/4mhz.png/
http://imageshack.us/photo/my-images/231/20mhz.png/
http://imageshack.us/photo/my-images/6/50mhz.png/
http://imageshack.us/photo/my-images/651/125hz.png/
http://imageshack.us/photo/my-images/710/500khz.png/
1hz.png

4mhz.png

20mhz.png

50mhz.png

125hz.png

500khz.png

1hz.png

4mhz.png

20mhz.png

125hz.png

500khz.png

50mhz.png




La resolucion es de 1 hz hasta los 16Mhz, luego es de 4 Hz hasta los 50Mhz. :aplauso:
En la simulacion, solo hay un pequeño error de 4 hz cuando se mide una señal de 50 Mhz, lo cual demuestra lo preciso que es el usar esta tecnica de leer el preescaler, el programa no esta escrito en ensamblador, nisiquiera en C, esta escrito en un modesto BASIC:D, y solo ocupa menos de 500 palabras de memoria; si pues aunque usted no lo crea!.:eek:
 
Última edición:
buenas , nececito medir el periodo de señales pequeñas hasta 5hz en un at89c52, pero tengo un problema, realize el programa midiendo el numero de pulsaciones por segundo, y no es nada preciso para mis requerimientos,asi q decidi hacerlo midiendo el periodo, ¿alguna idea?
 
Para el caso del amiguillo que quiere medir unos 450MHz...no se podría implementar un CD4040 y usar la salida en la que divide por 12 por ejemplo?

Así tendríamos a la salida unos 37,5MHz...ahi algunos pic's que trabajan hasta 40MHz...deberian funcionar

o no?
 
DJ Draco

Con viento intergalactico a favor puede ser que un CMos como el CD4040 llegue a los 10 MHz y tu le pides que acepte un clock de 450 MHz !!!!.



Saludos, JuanKa.-
 
Para adecuar frecuencias tan altas y mayores se usan divisores con la técnica ECL mucho mas costosos que los CMOS y los TTL F.

DJ Draco tiran cosas asi solo confunde mas a los jovenes que recien comienzan.



Saludos, JuanKa.-
 
Necesito hacer un frecuencímetro en MPLAB al cual se le meta una señal cuadrada a x frecuencia, esta frecuencia tiene que mostrarse en la LCD y debe mostrar de 0 a 2 Mhz como mínimo.
I
ntenté hacerlo con TMR0 y 1 pero no sé qué está fallando en mi código.
La librería "Basic4550" son solo la configuración de bits del PIC18F4550
El código es este:
C:
#include "Basic4550.h"

#define _XTAL_FREQ 48000000 // Reloj CPU

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "LCD-1.h"

// Variables globales
char buffer[16] = "";    // Buffer de texto
unsigned long pulseCount = 0;
unsigned long freq = 0;
unsigned long timer0InterruptCount = 0;

void config_ptos(void);
void config_timers(void);

// Configuración de interrupciones
void __interrupt() isr()
{
    // Si se generó una interrupción por Timer0
    if (INTCONbits.TMR0IF)
    {
        timer0InterruptCount++;  // Incrementar el contador de interrupciones del Timer0

        // Borrar la bandera de interrupción y resetear Timer0
        INTCONbits.TMR0IF = 0;
        TMR0 = 61;  // Valor inicial para generar una interrupción cada 1 ms
    }

    // Si se generó una interrupción por Timer1
    if (PIR1bits.TMR1IF)
    {
        pulseCount++;  // Incrementar el contador de pulsos del Timer1

        // Borrar la bandera de interrupción y resetear Timer1
        PIR1bits.TMR1IF = 0;
        TMR1 = 0;
    }
}

void main(void)
{
    config_ptos();
    config_timers();
    lcd_init();
    lcd_cmd(_LCD_CURSOR_OFF);  // Apagar cursor

    while (1)
    {
        // Calcular frecuencia
        freq = pulseCount / timer0InterruptCount;  // Dividir el número de pulsos por el tiempo de interrupción del Timer0

        // Imprimir la cantidad de pulsos en el buffer del LCD:
        sprintf(buffer, "Pulsos: %lu", pulseCount);

        // Imprimir en la primera fila:
        lcd_out(1, 1, buffer);

        // Mostrar frecuencia en la segunda fila del LCD
        sprintf(buffer, "Frec: %lu", freq);
        lcd_out(2, 1, buffer);
    }
}

void config_ptos(void)
{
    TRISD = 0x00;

    TRISA = 0xFF;
    LATA = 0x00;
    PORTA = 0x00;

    TRISB = 0b00000000;
    LATB = 0x00;
    PORTB = 0x00;

    PORTD = 0x00;
    LATD = 0x00;
    PORTCbits.RC0 = 0;
    LATCbits.LC0 = 0;
}

void config_timers(void)
{
    // Configurar Timer0
    T0CON = 0b10000011;   // Timer0 encendido, modo de 16 bits, incremento en transición de bajo a alto, prescaler 1:16
    INTCONbits.TMR0IE = 1;   // Habilitar la interrupción por Timer0

    // Configurar Timer1
    T1CON = 0b00000001;   // Timer1 encendido, incremento en transición de bajo a alto, prescaler 1:1
    PIE1bits.TMR1IE = 1;   // Habilitar la interrupción por Timer1

    // Configurar interrupciones
    INTCONbits.PEIE = 1;    // Habilitar interrupciones periféricas
    INTCONbits.GIE = 1;     // Habilitar interrupciones globales
}
 
Última edición por un moderador:
Atrás
Arriba