Medir la frecuencia de una onda cuadrada usando el módulo de captura

0

Escribí el siguiente código para medir la frecuencia de una onda cuadrada usando el módulo de captura del PIC16f1788. Escribí el código siguiendo paso a paso lo que se requiere en la hoja de datos de este PIC. Me gustaría saber si he omitido algún paso importante al hacerlo y si mi código tiene sentido. Esta es la primera vez que uso el módulo de captura, así que cualquier sugerencia es bienvenida. Gracias

    #include <xc.h>
    // Config word
    #define frequ  2
    #define _XTAL_FREQ   32000000

    // CONFIG1
    #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator:  I/O function on CLKIN pin)
    #pragma config WDTE = ON        // Watchdog Timer Enable (WDT enabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
    #pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
    #pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable bit (Vcap functionality is disabled on RA6.)
    #pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
    #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LPBOR = OFF      // Low Power Brown-Out Reset Enable Bit (Low power brown-out is disabled)
    #pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)





     void main(void)

     {

     int count=0;
     float rise1=0,rise2=0,frequency,period;

     OSCCON = 0b11111010;

     // clear the interrupts at beginning that way we are sure that our calculations will be exact no previous interrupt present 
     PIR1.CCP1IF=0;
     PIE1.CCP1IE=0;


    // output
    TRISBbits.TRISB0 = 1; // set it to input
    APFCON1bits.CCP1SEL=1;// toggle the CCP port output to RB0 from RC2


    // configure CCP1
    CCP1CONbits.CCP1M = 0x05;   // set it to Capture mode; on every rising edge



    While (count=! 2){

    count +=1; // increment the value of count

    // configure Timer 1
    T1CONbits.TMR1CS = 0; //set the  timer 1 clock to instruction clock Fosc/4 as mentioned in page300
    T1CONbits.TMR1ON = 1;       //  set Timer 1 on
    delay_us(10); //aquisition time
    T1GCON.T1GO/nDONE=1; // aquisition is ready wait for a rising edge
    while (T1GCON.T1GO/nDONE=1); //wait untill the aquisition is complete


     if (count==1) {

     rise1=CCPR1; }  //capture the first rising edge and store that value in rise1

     if count ==2) {

     rise2=CCPR1; } // capture the second rising edge and store the value in rise2

    }

    period = rise2-rise1;  // subtracte both values to get the period of the signal

    frequency=1/period;  

     // clear any interrupts that are set
     PIR1.CCP1IF=0;
     PIE1.CCP1IE=0;


}
    
pregunta sam brosteain

1 respuesta

1

Desde su solicitud, estoy tratando de explicar la medición de frecuencia usando dos temporizadores. Se puede usar un temporizador en varios modos, pero aquí solo necesitamos dos modos.

  1. Haciendo una duración de tiempo
  2. Usar como contador

Ya que estás trabajando con pulsos, crea Timer0 como contador. Utilice Timer1 para medir una duración de 1 segundo. Supongamos que Timer0 comienza a contar los impulsos, mientras tanto, Timer1 mide la duración del tiempo. Cuando mida 1 segundo, recoja el valor de contador. Si el valor del contador es 100, la frecuencia es 100Hz. Ambos temporizadores utilizan la interrupción, por lo que su código principal es libre de asignar cualquier otra tarea.

// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;

sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;
// End LCD module connections

int frequency,counter,cnt;
char txt[7];

void InitTimer1(){
  T1CON         = 0x31;
  TMR1IF_bit         = 0;
  TMR1H         = 0x0B;
  TMR1L         = 0xDC;
  TMR1IE_bit         = 1;
  INTCON         = 0xC0;
}

void Interrupt(){

  //Timer1 code to measure 1s duration
  if (TMR1IF_bit){
  cnt++;
    TMR1IF_bit = 0;
    TMR1H         = 0x0B;
    TMR1L         = 0xDC;
    //Enter your code here
    if (cnt >= 10) {      // 1s; after 10 interrupts LEDs will be toggled
          frequency=TMR0+(256*counter);
          TMR0=0;
          counter=0;
          cnt = 0;             // Reset cnt
        }
  }
  // Timer0 code to count incomming pulses
  if (TMR0IF_bit){
      TMR0IF_bit = 0;
     counter++;
  }
}

void main() {
frequency=0;
T0CS_bit=1;
T0SE_bit=0;
TMR0IE_bit=1;
InitTimer1();
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Out(1,1,"Frequency In Hz:");
do {
         IntToStr(frequency,txt);
         Lcd_Out(2,4,txt);

  } while(1);

}

Este código está escrito en MikroC. Puede convertirlo como sus requisitos de compilador. Puede ver este tutorial para obtener más detalles.

Vi un tutorial donde se hace un retraso de 1 segundo para medir la frecuencia. Pero un retraso de 1 s simplemente establece el procesador inactivo durante 1 segundo, lo que es un desperdicio de recursos. La idea clave es hacer este retardo mediante el método de interrupción, luego puedo realizar otras tareas para el controlador, como la medición de voltaje o corriente. Creo que esto será útil para todos.

    
respondido por el xcoder

Lea otras preguntas en las etiquetas